Introduction

This document is meant as both a quick reference as well as documentation of a few sampling techniques that can be used in path tracing. It mostly came about because I found it hard to find such a reference or the derivations themselves.

This is of course not every kind of sampling technique (for example, no stratified sampling) or distribution, just a few, but maybe someone else can use it as well.

Each Sampling method will have the algorithm and probability density functions listed first and afterwards a derivation. So if you are just looking up how to implement it, you can find it below the images. The images (for the 3D directions) show a heatmap hemisphere corresponding to a number of samples chosen with the showcased method. The heatmap values correspond to number of points per area. Regions with high values will receive more samples than regions with low values.

In general I tried to include every step in the derivation so hopefully it is easy enough to follow.

You can run and all the presented code and change parameters as you like and add points to the current heatmap.

Common helper functions

These are the two functions used to convert from spherical/polar to Cartesian coordinates:

Note: We use a right-handed spherical coordinate system with the y-axis pointing upwards, as that is common in computer graphics. You can easily transform this to a system more common in physics with z up by shifting the coordinates such that z aligns with y: yz,zx,xyy\rightarrow z, z \rightarrow x, x \rightarrow y.

function spherical_to_cart(theta, phi, r = 1.0) {
    const st = Math.sin(theta);
    const ct = Math.cos(theta);
    const sp = Math.sin(phi);
    const cp = Math.cos(phi);

    const x = r * st * sp;
    const y = r * ct;
    const z = r * st * cp;
    
    return [x, y, z];

}

function polar_to_cart(r, alpha) {
    const sa = Math.sin(alpha);
    const ca = Math.cos(alpha);

    const x = r * ca;
    const y = r * sa;

    return [x, y];

}

Inverse Transform Sampling

The following sections will explore some ways to sample points/directions used for the Monte Carlo integration. The recipe for calculating the sampling formulas is called inverse transform sampling (there are, of course, other methods)

  1. Generate a uniform random number in the interval [0,1][0,1]
  2. Find the cumulative distribution function (CDF) PP of the desired distribution pp
  3. Calculate v=P1(u)v=P^{-1}(u). vv will be distributed with pp

Here we can see a visual demonstration of this method. You can see how the uniformly distributed points on the y-axis get automatically spread out over the x-axis according to the rate of change in the function.

Since we usually need two-dimensional values, we have to modify it a bit

  1. Generate two uniform random numbers u1,u2u_1, u_2 in the interval [0,1][0,1]

  2. The probability density function pp is dependent on x1,x2x_1, x2, so p(x1,x2)p(x_1,x_2)

    1. Calculate the marginal distribution px1(x1)=Ω2p(x1,x2)dx2p_{x_1}(x1)= \int_{\Omega_2}p(x1,x2)dx_2
    2. Calculate the conditional probability distribution of x2x_2 with respect to x1x_1 with the Bayes theorem: p(x2x1)=p(x1,x2)px1(x1)p(x2\vert x1)=p(x_1,x_2)p_{x_1}(x_1)
  3. Calculate the CDFs Px1(x1)P_{x_1}(x_1) and Px2(x2)P{x_2}(x_2).

  4. Calculate v1=Px11(u1)v_1=P_{x_1}^{-1}(u_1) and v2=Px21(u2)v_2=P_{x_2}^{-1}(u_2) . v1v_1 and v2v_2 will have the desired distribution

(see for example: https://www.slac.stanford.edu/slac/sass/talks/MonteCarloSASS.pdf)