Shadow Volumes
|
Shadow volumes are a technique used in 3D computer graphics since 1977 to add shadows to a rendered scene. It is generally considered among the most practical general purpose real-time shadowing system given the capabilities of modern 3D graphics hardware, and has been popularized by Doom 3.
A shadow volume divides the virtual world into two; areas that are in shadow and areas that are not.
In order to construct a shadow volume, project a line from the light through each vertex in the shadow casting object to some point (generally at infinity). These projections will together form a volume; any point inside that volume is in shadow, everything outside is lit by the light.
Current research and implementations focus on the use of a hardware stencil buffer to optimize the algorithm making use of hardware acceleration - see Stencil shadow volume.
In order to test whether a given pixel in the rendered image is shadowed or not, the shadow volume itself is rendered, though to the stencil buffer only and not to the final image. For every front-facing face in the shadow volume the value in the stencil buffer is increased; for every back-facing face it is decreased.
Once all faces in the shadow volume have been rendered to the stencil buffer, any pixel with a value not equal to zero will be in shadow.
In order to understand why, think in terms of a ray of light heading back from the pixel on the screen - if it passes into the shadow volume, it will be through a front-facing face and so the stencil buffer value will be increased. If it then passes out through the back of the volume (through a back-facing face) it will be decreased.
If, however, the pixel is in shadow then the value will only be decreased when it leaves the shadow volume at the back, and so the value will be non-zero.
Figure 1 shows a simple scene containing a camera, a light, a shadow casting object (the blue circle) and three shadow receiving objects (the green squares), all represented in 2D. The thick black lines show the outline of the shadow volume. The line projecting from the camera (smiley face) is the line of sight.
The line of sight first hits object a; at this point it has not reached any faces of the shadow volume and so the stencil buffer will have a value of 0 - not in shadow. At point 1 a front face of the shadow volume is crossed and increment the stencil buffer. Next we hit object b; at this point we have a value of 1 in the buffer so the object is in shadow. Progressing down the line of sight we reach the back face of the shadow volume at 2, and decrement the stencil buffer back to 0. Finally we hit object c, again with a value of 0 in the stencil buffer so the object is not in shadow.
One problem with this algorithm is that if the camera (eye) is itself in the shadow volume then this approach will fail - the line of sight first crosses a back face of the shadow volume, decrementing the stencil buffer value so that it is non-zero when it reaches object c, even though that object should not be shadowed.
One solution to this is to trace backwards from some point at infinity to the eye of the camera. This technique was discovered independently by a number of people, but was popularized by John Carmack, and is generally known as Carmack's Reverse.