Spherical Harmonic Lighting

This demo implements spherical harmonics (SH) lighting as seen in (Green 2001). Spherical harmonics is a method of sampling a spherical function over a unit sphere. It is very similar to the Fourier transform where we project a function in to the frequency domain. Spherical harmonics is more suitable for functions operating in the spherical coordinate system. A better analogy according to me is the discrete cosine transform (DCT) used in JPEG compression. In JPEG compression we calculate the DCT coefficients of a block of pixels and then quantise the less important coefficients (the high frequency coefficients) (Miano 1999). In an similar manner in spherical harmonic lighting, we sample the lighting contribution at a point over a sphere and keep only the low frequency components. This is based on the assumption that our light source produces low frequency lighting. Therefore, this method is ideal for simulating outdoor lighting with a cloudy sky.
Calculating the spherical harmonic coefficients of a function will generally result in complex numbers. In the case of lighting we are only interested in real numbers and hence actually project the function using real spherical harmonic basis functions. In most cases when we talk about spherical harmonics in graphics we are generally referring to real spherical harmonics as we rarely deal with complex numbers. What makes spherical harmonics truly amazing for lighting is that we can reduce an infinite number of light sources to a few coefficients (think compression). These lighting coefficients can then be combined with another spherical function by simply multiplying and adding the SH coefficients of each function. This second spherical function is generally the diffuse light contribution at a point from all different directions after being occluded by other objects and faces belonging to the same object (self-occlusion).

While this is all quite nice, there are several issues with spherical harmonics.
As mentioned previously, it is suitable only for low frequency lighting.  We could support increasingly high frequencies by increasing the number of bands, but that would increase the number of calculations required at run time.
While spherical harmonic basis are rotationally invariant, calculating the rotation matrices at run time is a fairly expensive operation. Furthermore the rotation matrix is an NxN matrix. Where N is the number of coefficients. So if we use 3 bands ( 9 coefficients) we would need to calculate a 9×9 matrix and multiply this matrix with every set of SH coefficients. This is fine if we are just rotating the light, but if we were rotating an object, we would need to do this matrix multiplication at every vertex. This is an area of active research (Blanco et al. 1997, Choi et al. 1999, Ivanic and Ruedenberg 1996, Krivánek et al. 2006) and several optimisations can be made, but it is still no where nearly as fast as we need it to be given the computational power available to us today.
Finally SH coefficients can be calculated for static objects and scenes. Moving these objects with relation to each other would require that the SH coefficients be recalculated. This could take anywhere from a few minutes to a few hours, no where near real time (0.30 seconds) mark.
Finally, SH best deals with only the diffuse lighting component (as it is pre calculated). Hence the specular component cannot be computed for two reasons – it is view dependent and generally has a high frequency.

Despite all this, spherical harmonics lighting has played a major part in several commercially successful engines.

Implementation details

Framework

The demo is based on my long time favorite library – G3D. The framework has been modified slightly to suit my whims and fancies, so you would need to download the framework as well if you would like to compile the code.

Controls

You can move camera around using first person style controls – WASD keys and right click and drag the mouse to change the view direction. The application allows you to rotate the lighting coefficients using ZαYβZγ (or rather the ZαX-90ZβX+90Zγ) convention. The three angles α β and γ may be selected by first pressing the ‘z’ ‘x’ ‘c’ keys respectively and then pressing the ’1′ or ’2′ key to decrease or increase it’s value. The value are clamped to the appropriate values.

Models

SH coefficients have be cached in the .smesh files. If you have a few spare hours of spare computational time available on your computer, you may delete these files. The application will load the original models and recompute the SH coefficients again. The demo uses a ray tracer provided in the G3D framework to check for occlusions over the hemisphere at each vertex hence generating shadowed coefficients.

Lighting

Lighting is assumed to come for a environment map. The lighting is reduced to 10% of the original lighting in the shader. This value is hard coded in the shader and can be modified in the sh9.vs file. The images that correspond to the faces of the cube map are as follows: 0 = +X, 1 = -X, 2 = +Z, 3 = -Z, 4 =  +Y, 5 = -Y. There is provision in the code to use a spherical function as your lighting function, but that would mean recompiling the project. The lighting coefficients are calculated every time the application starts, so you can simply change the individual images of the environment map on disk without the need to compile the application. The same goes for the shader file.

Nuances

There are several points to note before looking at the demo

  • I should really provide the ability to load arbitrary environment maps.
  • The ability to provide parameters to change the light contribution coming from the environment maps at run time
  • For the sake of clarity and lack of time, very few optimisations have been made, especially when calculating the SH bands and rotation matrices
  • The demo is hard coded to work on 3 SH bands (9 coefficients). This is largely due to the fact that I was unable to find a generic equation to calculate the X-90 and X+90 rotation matrices for arbitrary number of bands

Acknowledgements

The armadillo model used in the demo is sourced from the Stanford 3D Scanning Repository. The mesh was simplified using MeshLab. And thanks to the team behind G3D for providing a high quality framework that makes my life so much easier.

Links and downloads

References

  • Blanco, M. A, M. Flórez, and M. Bermejo. 1997. Evaluation of the rotation matrices in the basis of real spherical harmonics. Journal of Molecular Structure: THEOCHEM 419, no. 1: 19–27.
  • Choi, C. H, J. Ivanic, M. S Gordon, and K. Ruedenberg. 1999. Rapid and stable determination of rotation matrices between spherical harmonics by direct recursion. The Journal of Chemical Physics 111: 8825.
  • Green, R. 2003. Spherical harmonic lighting: The gritty details. In Archives of the Game Developers Conference.
  • Ivanic, J., and K. Ruedenberg. 1996. Rotation matrices for real spherical harmonics. Direct determination by recursion. J. Phys. Chem 100, no. 15: 6342–6347.
  • Krivánek, J., J. Konttinen, S. Pattanaik, K. Bouatouch, and J. Žára. 2006. Fast approximation to spherical harmonics rotation. In ACM SIGGRAPH 2006 Sketches, 154.
  • Miano, J. 1999. Compressed Image File Formats: Jpeg, Png, Gif, Xbm, Bmp. Addison-Wesley.