Heskey0 (Bilibili)
December 2021
Based On Mark Pauly's Thesis[1999] and 《PBRT》
There are many techniques for generating random variates from a specified probability distribution such as the normal, exponential, or gamma distribution. However, one technique stands out because of its generality and simplicity: the inverse CDF sampling technique.
The algorithm is as follows:
Example of inverse CDF method:
Let \(p(\theta)=sin\theta\) be the probability density function, \(F(\theta)=1-cos\theta\) the cumulative density function of \(\theta\)
generate a draw \(\xi\) from the standard uniform distribution \(U∼Unif(0,1)\)
the draw \(\theta\) from the PDF \(p(\theta)\) is given by \(\theta=F^{-1}(\xi)=arccos(1-\xi)\)
a uniform distribution means that the density function is a constant, so we know that \(p(x)=c\)
\[\int_{S^2} p(\omega) d\omega=1\Longrightarrow c\int_{S^2}d\omega=1\Longrightarrow c=\frac1{2\pi} \]hence \(p(\omega)=\frac1{2\pi}\), \(d\omega=sin\theta d\theta d\phi\), \(p(\theta,\phi)=\frac{sin\theta}{2\pi}\)
Consider sampling \(\theta\) first. To do so, we need \(\theta\)'s marginal density function \(p(\theta)\):
\[p(\theta)=\int_0^{2\pi}p(\theta,\phi)d\phi=\int_0^{2\pi}\frac{sin\theta}{2\pi}d\phi=sin\theta \]Now, compute the conditional density for \(\phi\):
\[p(\phi|\theta)=\frac{p(\theta,\phi)}{p(\theta)}=\frac1{2\pi} \]Notice that the density function for \(\phi\) itself is uniform, then use the inverse CDF sampling technique to sample each of these PDFs in turn
\[P(\theta)=\int_0^{\theta}sin\theta^{\prime}d\theta^{\prime}=1-cos\theta\Longrightarrow \theta=arccos\xi_1 \]\[P(\phi|\theta)=\int_0^{\phi}\frac1{2\pi}d\phi^{\prime}=\frac{\phi}{2\pi}\Longrightarrow\phi=2\pi\xi_2 \]Converting these back to Cartesian coordinates, we get the final sampling formula:
\[x=sin\theta cos\phi=cos(2\pi\xi_2)\sqrt{1-\xi_1^2} \]\[y=sin\theta sin\phi=sin(2\pi\xi_2)\sqrt{1-\xi_1^2} \]\[z=cos\theta=\xi_1 \]def sample_area_light(hit_pos, pos_normal): # sampling inside the light area x = ti.random() * light_x_range + light_x_min_pos z = ti.random() * light_z_range + light_z_min_pos on_light_pos = ti.Vector([x, light_y_pos, z]) return (on_light_pos - hit_pos).normalized()
We could use the inverse CDF sampling technique as before, but instead we can use a technique known as Malley’s method to generate these cosine-weighted points.
The algorithm is as follows:
sample a unit disk (Concentric Mapping)
\[r=x;\phi=\frac yx\frac{\pi}4 \]project up to the unit hemisphere
MIS allows us to combine \(m\) different sampling strategies to produce a single unbiased estimator by weighting each sampling strategy by its probability distribution function.
\[\langle I_j\rangle=\sum_{i=1}^m\frac1{n_i}\sum_{j=1}^{n_i}w_i(X_{i,j})\frac{f(X_{i,j})}{p_i(X_{i,j})} \]where \(X_{i,j}\) are independent random variables drawn from some distribution function pi and \(w_i(X_{i,j})\) is some heuristic for weighting each sampling technique with respect to pdf.
balance heuristic:
\[w_s(x)=\frac{n_sp_s(x)}{\sum_in_ip_i(x)} \]power heuristic:
\[w_s(x)=\frac{(n_sp_s(x))^{\beta}}{\sum_i(n_ip_i(x))^{\beta}} \]Veach determined empirically that \(\beta=2\) is a good value