Rendering deferred lights using Stencil culling algorithm

Yuriy O'Donnell, March 14th, 2009
Updated July 12, 2011

This algorithm works for all lights regardless of whether camera is inside the light volume or not.

However, it will only work well on PC hardware. It will not work on PS3 or 360, where setting up early Stencil culling functionality needs some special attention.

Each light volume (low poly sphere) is rendered it two passes.

Pass 1:

This pass creates a Stencil mask for the areas of the light volume that are not occluded by scene geometry.

Pass 2:

This pass is where lighting actually happens. Every pixel that passes Z and Stencil tests is then added to light accumulation buffer.

Diagram below shows effects of Z and Stencil tests:

alt text

Light 1 has both near and far faces in front of all world geometry. It will pass Z test for near face, but will fail Z test for far face. Therefore it's pixel shader will not run.

Light 2 will fail Z test for near face, write non-zero value to Stencil and then fail Stencil test for far face. Again, no pixels will get through.

Light 3 will behave like Light 2 in the bottom part, but top part will pass both Z and Stencil tests and therefore will get rendered.

If camera is inside a light volume, near faces will not get rendered. Stencil value will be zero for back faces and so only Z test will decide if pixel shader should run.

Demo

Download

You should be able to inspect it using NVIDIA PerfHUD.

alt text

Demo controls:

WASD -- up/down/left/right
EQ -- forward/back
ZX -- rotate
Arrows/Left mouse button -- look around
Space -- animate lights