Game Development Reference
float3 facePosition = directions[j]*0.5f;
float3 dir = facePosition -neighborCellCenter;
float fLength = length(dir);
dir /= fLength;
// Get corresponding solid angle.
float solidAngle = 0.0f;
solidAngle = (fLength>=1.5f) ? (22.95668f/(4*180.0f)) :
// Calculate SH-coefficients for direction.
result.x = 1.0f/(2*sqrt(PI));
result.y = -sqrt(3.0f/(4*PI));
result.z = sqrt(3.0f/(4*PI));
result.w = -sqrt(3.0f/(4*PI));
result.wyz *= dir;
// Calculate flux from neighbor cell to face of current cell.
flux.r = dot(redSHCoeffs,dirSH);
flux.g = dot(greenSHCoeffs ,dirSH);
flux.b = dot(blueSHCoeffs ,dirSH);
flux = max(0.0f,flux)*solidAngle;
// apply occlusion
float occlusion = 1.0f-saturate(dot(occlusionCoeffs ,dirSH));
flux *= occlusion;
// Add contribution to SH-coefficients sums.
float4 coeffs = faceCoeffs[j];
sumRedSHCoeffs += coeffs*flux.r;
sumGreenSHCoeffs += coeffs*flux.g;
sumBlueSHCoeffs += coeffs*flux.b;
// Write out generated red, green, and blue SH-coefficients.
outputRedSHTexture[elementPos] = sumRedSHCoeffs;
outputGreenSHTexture[elementPos] = sumGreenSHCoeffs;
outputBlueSHTexture[elementPos] = sumBlueSHCoeffs;
Listing 7.3. Propagation of VPLs.
For each propagation step the compute shader is dispatched with 4
thread groups so that altogether 32
32 threads are utilized, which corre-
sponds to the total cell count of the grid.
7.3.4 Apply Indirect Lighting
In this step the previously propagated VPLs are finally applied to the scene. For
this we need a depth buffer from which the world-space position of the visible pix-
els can be reconstructed, as well as a normal buffer that contains the perturbed
normal information for each pixel. Obviously, deferred rendering as a direct illu-
mination approach is perfectly fitted for our case since both pieces of information
are already available and no extra work has to be done.