Skip to content

Spherical Harmonic Lighting

Spherical Harmonic Lighting: The Gritty Details

Spherical Harmonic Lighting A efficient method for capturing and displaying Global Illumination solutions across the surface of an object.

Background

Light Modeling

For a point \(x\) at the surface, the reflected light intensity from viewing direction $ \mathbf d_0$ is modelled as

\[\begin{align*} L(x, \mathbf d_0) &= L_e(x, \mathbf d_0) + \int_S f_r(x, \mathbf d_i - \mathbf d_0) L_r(x', \mathbf d_i) G(x,x') \mathbf I(x\text{ see } x')d\: \mathbf d_i\\ \end{align*}\]

where \(S\) is the unit sphere centered at \(x\) and
\(L_e(x, \mathbf d_0)\) is the direct emission light
\(f_r(x, \mathbf d_i - \mathbf d_0)\) is the BRDF term, transforming incoming light $ \mathbf d_i$ to \(\mathbf d_0\)
\(L_r(x,x')\) the the light reflected from \(x'\) to \(x\)
\(G(x, x')\) is the geometric relationship between \(x\) and \(x'\)

Of course, this computation is intractable and we do lots compromises (given up some terms, simplify the model).

Monte Carlo Integration

Known that the expectation is defined as

\[E(f(x)) = \int f(x)p(x) dx\]

for any function \(f\), thus if we have that \(f' = f/p\), we have

\[E(\frac{f(x)}{p(x)}) = \int \frac{f(x)}{p(x)}p(x) dx = \int f(x)dx \approx \hat E(\frac{f(x)}{p(x)}) = \frac{\sum^N f(x_i)/{p(x_i)}}{N}\]

More over, if we can uniformally sample \(N\) points on the sphere surface, then we have \(p(x_i) = 1/4\pi\) is constant. so that the equation is reduced to summing samples.

Note that uniform sampling from polar coordinate \((\theta\in [0,2\pi), \phi\in[-\pi/2,\pi/2))\) is not a uniform sampling over the sphere, since we are sampling over the circles with different radius \(\sin\phi\).

Instead, we transforms from unit square \((u,v)\)

\[(2\pi u, 2\cos^{-1}(\sqrt{1-v}))\rightarrow (\theta,\phi)\]
function sphere_sample(N) {
    const positions = new Float32Array(N * 3);
    for (let i = 0; i < N; i++) {
        // uniform sample from [0, 1) * [0, 1)
        const u = Math.random();
        const v = Math.random();
        // transform to polar
        const theta = 2 * PI * u;
        const phi = 2 * Math.acos(Math.sqrt(1 - v));
        // transform to xyz
        positions[3 * i] = Math.cos(theta) * Math.sin(phi);
        positions[3 * i + 1] = Math.sin(theta) * Math.sin(phi);
        positions[3 * i + 2] = Math.cos(phi);
    }
    return positions;
}

SH Projection

The projection onto SH is hence

\[c_l^m = \int_S f(s) y_l^m(s)ds\]

which can be evaluated using Monte-Carlo integration (since we have our unit sphere uniform sampling).

and the reconstruction is

\[\tilde f(s) = \sum_{l=0}^{n-l}\sum_{m=-l}^l c_l^m y_l^m(s) = \sum_{i=0}^{n^2} c_i y_i(s)\]

where \(i = l(l+1)+m\) is used to flatten the nested indexes into 1D.

Thus, we can connect everything together.

Properties

Rotation Invariance

SH functions are orthonormal, thus suppose that \(g:= f\circ R\) where \(R\in SO(3)\), then \(\tilde g = \tilde f \circ R\) is the same approximation of \(g\). Thus, if we do rotations of the light field (viewing from different angles, or in a dynamic lighting environment).

Integration to dot product

For the reflectance models, the light is an integral over a sampled area

\[\int_S L(s) t(s)ds\]

where \(L\) is the incoming light from direction \(s\), and \(t\) is the transfer function (e.g. BRDF). However, if we use spherical harmonics to approximate \(L\) and \(t\), and take \(L_i, t_i\) be the SH coefs. Then we have that

\[\int_S \tilde L(s) \tilde t(s)ds = \sum_{i=0}^{n^2} L_i t_i\]

which is the dot product of two coef vectors.