Shadow maps use the depth buffer and projective texture mapping to create a screen space method for shadowing objects [84,92]. Its performance is not directly dependent on the complexity of the shadowing object.
The scene is transformed so that the eye point is at the light source. The
objects in the scene are rendered, updating the depth buffer. The depth
buffer is read back, then written into a texture map. This texture is
mapped onto the primitives in the original scene, as viewed from the
eye point, using the texture transformation matrix, and eye space texture
coordinate generation. The value of the texture's texel value, the
texture's ``intensity'', is compared against the texture coordinate's value
at each pixel. This comparison is used to determine whether the pixel is
shadowed from the light source. If the
value of the texture coordinate is
greater than texel value, the object was in shadow. If not, it was lit by
the light in question.
This procedure works because the depth buffer records the distances from
the light to every object in the scene, creating a shadow map. The smaller
the value, the closer the object is to the light. The transform and
texture coordinate generation is chosen so that ,
, and
locations of
objects in the scene map to the
and
coordinates of the proper texels in
the shadow texture map, and to
values corresponding to the distance from
the light source. Note that the
values and texel values must be scaled so
that comparisons between them are meaningful.
Both values measure the distance from an object to the light. The texel
value is the distance between the light and the first object encountered
along that texel's path. If the distance is greater than the texel value,
this means that there is an object closer to the light than this one.
Otherwise, there is nothing closer to the light than this object, so it is
illuminated by the light source. Think of it as a depth test done from the
light's point of view.
Shadow maps can almost be done with the OpenGL 1.1 implementation. However,
the ability to compare the texture's r component against the
corresponding texel value is missing. There is an OpenGL extension,
SGIX_shadow, that
performs the comparison. As each texel is compared, the results set the
fragment's alpha value to 0 or 1. The extension can be described as using
the shadow texture value test to mask out shadowed areas using alpha
values.
The ARB_multitexture extension to OpenGL 1.2 and EXT_texture_env_combine may be used on some implementations to perform the shadow map depth comparison in the texure environment, but the source textures are limited to the alpha or luminance component sizes, currently 8 bits on available accelerators. Using stencil or destination alpha, multipass techniques can be used to extend the shadow map precision to multiples of the component size.