This sample shows how to apply Spherical Harmonic diffuse lighting as Global Illusion (GI). GI could give some more realistic effect to improve the global lighting effect than the traditional ambient lighting that will break whole the scene color contrast. If you check some more advanced rendering engine, you will find that the artist will always use shaders to implement more cool effect instead of following the old way of direct lighting methods. For example, some one could like to use a sky light sphere to lit the objects considering the vertex normal.
Spherical Harmonic is a compress method, that could be used to compress some low short wave data among a sphere. Here, SH was used to compress the sample point lighting data over a sphere. I used a cube (6 textures) map mapping to sphere to build those sample points. The result of the SH compressing process is a group of coefficients. (the number of the coefficients based on the order that you choose)
Build SH coefficients
The SH data compress process is the process to find the SH coefficients. There are two ways to achieve that : 1) Calculate the value by integral mathematical function; 2) use statistical method – calculate the sum average weight value with a lots of random sampling data, that just Gore Integral does.
![]() | ![]() |
As you see from the above function, the left one is the mathematical integral version one, and the right one is the sum average weight value calculation one. N means the number of the sample point, and “4PI” means the area over a unit sphere (also the possibility that this point will be sampled, equal the inverse of the area). Maybe you have already know that all the sample point have the same weight, but of course you could increase some special sample weight to make them become more contribute to the whole sampling. For more details about the concept, you could refer to spherical-harmonic-lighting.pdf.
Average sum weight calculation
Just take 3 sample as an example, the sample will like this (sample_value, weight) :
(V_0, W_0), (V_1, W_1), (V_2, W_2). And the Average sum weight will be calculated like this:
Result = ( V_0 * W_0 + V_1 * W_1 + V_2 * W_2 ) / (W_0 + W_1 + W_2)
Restore the RGB from SH coefficients
Restore the RGB from the SH coefficients given by a normal is very easy, the code is as following:
const Colour sharm[9]; Colour LightNormal ( Vector &dirn ) { Colour colour = sharm[0]; colour += sharm[1] * dirn.x; colour += sharm[2] * dirn.y; colour += sharm[3] * dirn.z; colour += sharm[4] * (dirn.x * dirn.z); colour += sharm[5] * (dirn.z * dirn.y); colour += sharm[6] * (dirn.y * dirn.x); colour += sharm[7] * (3.0f * dirn.z * dirn.z - 1.0f); colour += sharm[8] * (dirn.x * dirn.x - dirn.y * dirn.y); return colour; }
As you see, the above could be achieved with shader, that will work with the normal mapping.
The full source code could found here.