Area Light Shadows

The basic steps of the idea are:

  1. Generate shadow map:
    In my demo I used a regular spot light shadow map, but it would be also possible to use omni-directional shadow maps.
  2. Generate shadow mask:
    In this step first the average occluder depth is determined in the spirit of PCSS. We sample the shadow map per pixel with 4 randomly distributed samples over the area light shape that change per screen pixel location and over time and 1 additional sample that is located in the center of the area light. It turned out that this gives almost the same visual results as using 256 randomly distributed samples per pixel. The resulting average occluder depth is used to form a virtual occluder plane, with which 4 rays from the pixel to shade to the randomly distributed light samples are intersected. At each intersection a shadow map comparison is performed and the average shadowing value is written into the shadow mask.
  3. Denoise shadow mask:
    To eliminate noise that stems from changing the light samples per screen pixel location and over time, first 2 bilateral blur passes are performed followed by a temporal pass, similar to the one used for temporal anti-aliasing.

A reference raytracing-based approach generates the shadow mask by tracing 1 ray per pixel to the same stochastic light samples and applies the same denoising step as described above. In the below comparison screenshots from my demo, the images on the left were generated via the described shadow map-based approach and the images on the right via the reference raytracing-based approach. The top row shows a 50x50cm rectangular area light, the middle row a 100x10cm rectangular area light with 45 degree rotation, and the bottom row a 20x100x50cm cuboid area light. Please note that the demo uses the Crytek Sponza scene and the dwarf model from the Microsoft DirectX SDK as dynamic mesh.

Finally I combined the stochastically generated shadow mask with the analytically computed lighting according to “Combining Analytic Direct Illumination and Stochastic Shadows” (by E. Heitz, S. Hill and M. McGuire). Below the left screenshot used the shadow map-based approximation, while the right screenshot the raytracing-based approach.

Performance-wise I got following results for generating the denoised shadow mask for a 50x50 cm rectangular area light source on a Nvidia Geforce GTX 1070 at 1080p:

Since the demo is using the DXR fallback layer, it has the same requirements for building and running. You can download the demo with complete source code here: