Game Development Reference

In-Depth Information

To output the second-order SH-coecients for all three color channels, we

render this time into three 2D texture arrays with half floating-point precision.

Since all calculations are done entirely in voxel space and are limited to voxels,

which actually contain geometry information, this technique scales very well with

an increasing number of light sources of all different types.

In many situations we can even abandon the use of shadow maps for point

lights and spotlights without noticeably affecting the final render output. How-

ever, for large point lights, spotlights, and directional lights, we do need to use

shadow maps to avoid light leaking. Here we can simply reuse the shadow maps

that have already been created for the direct illumination step.

7.3.3 Propagate VPLs

In this step the previously created VPLs are propagated iteratively across the grid

according to the LPV technique proposed by [Kaplanyan and Dachsbacher 10].

Basically each VPL cell propagates its light along the three axes of a Cartesian

coordinate system to its surrounding six neighbor cells. While doing this propa-

gation, the voxel grid from the first step is used to determine how strongly the

light transport to the neighbor cells is occluded. The results from the first prop-

agation step are then used to perform a second propagation step. This is done

iteratively until we get a visually satisfying light distribution. In the first iter-

ation no occlusion is used, in order to initially let the light distribute; from the

second iteration on, we use the geometry occlusion in order to avoid light leaking.

The iterative propagation is performed in DirectX 11 by utilizing a compute

shader since we do not need the rasterization pipeline for this job. Listing 7.3

demonstrates this.

// compute shader

Texture2DArray inputRedSHTexture:
register
(t0);

Texture2DArray inputGreenSHTexture:
register
(t1);

Texture2DArray inputBlueSHTexture:
register
(t2);

StructuredBuffer <VOXEL> gridBuffer:
register
(t3);

RWTexture2DArray <float4> outputRedSHTexture:
register
(u0);

RWTexture2DArray <float4> outputGreenSHTexture:
register
(u1);

RWTexture2DArray <float4> outputBlueSHTexture:
register
(u2);

// directions to six neighbor cell centers

static
float3 directions[6] =

{

float3(0.0f,0.0f,1.0f), float3(1.0f,0.0f,0.0f), float3(0.0f,0.0f,-1.0f),

float3(-1.0f,0.0f,0.0f), float3(0.0f,1.0f,0.0f), float3(0.0f,-1.0f,0.0f)

};

// SH-coefficients for six faces (ClampedCosineSHCoeffs(directions[0-5])

static
float4 faceCoeffs[6] =

{

float4(PI/(2*sqrt(PI)),0.0f,((2*PI)/3.0f)*sqrt(3.0f/(4*PI)),0.0f),

float4(PI/(2*sqrt(PI)),0.0f,0.0f,-((2*PI)/3.0f)*sqrt(3.0f/(4*PI))),

float4(PI/(2*sqrt(PI)),0.0f,-((2*PI)/3.0f)*sqrt(3.0f/(4*PI)),0.0f),

float4(PI/(2*sqrt(PI)),0.0f,0.0f,((2*PI)/3.0f)*sqrt(3.0f/(4*PI))),

Search Nedrilad ::

Custom Search