Return to Andrew's OpenGL Page


3.4 Shadows

3.4.1 Introduction

Shadows have been a much overlooked area in 3D games in the past but add a great deal of realism to a scene. I still see screen shots from soon to be released games that have wonderfully detailed scenes and player models but look odd because the models don't have shadows and so appear to have no contact with the ground. In this discussion, various techniques for rendering player model shadows will be covered with emphasis on the techniques used in Corridors of Power.

3.4.2 Simple Shadows

In this technique, a dark, circular shadow is rendered on the ground plane directly beneath the player model. This has the advantage of being very quick and easy to render but doesn't exhibit the outline or orientation of the object.

When developing this type of shadow for Corridors of Power I looked at the current range of games and the main problem with the shadows, particularly circular ones, was the sharp edge. I therefore decided to render the shadows using a texture containing a diffuse spot, this produces a much softer look to the shadow edge and so has a much improved look over the alternative. The RGB texture that is used is shown below:

Shadow Map

The steps used to render the simple shadows in Corridors of Power are as follows:

The size of the shadow can be varied by scaling the size of the shadow map with the object size.

NB: depending on the accuracy of the Z buffer and viewing distance, altering the depth function may not be enough to avoid visual artefacts. If this is the case then translating to a point slightly above the ground plane or specifying a polygon offset should solve the problem.

A screen shot showing an example of the output of the above routine is shown below:

Example of Simple Shadow

There are some interesting problems that can occur when rendering shadows for moving objects, such as sloping ground planes and intersections between flat and sloping ground planes. The solutions range from not drawing the shadow map on anything but a flat ground plane to detecting all the ground planes under the object and rendering the shadow map onto each one with clipping at the edges.

3.4.3 Complex Shadows

A circular shadow is very efficient but hardly gives an accurate representation of the shape of the object casting the shadow. For this we need to draw a complex shadow which basically involves re-rendering the model in a collapsed form on the ground plane. The key to this is to use the scaling function within GL; setting the y component to zero when the model is rendered causes it to be collapsed to a 2D form. In this case the shadow would be rendered as follows:

The above routine creates a very dark shadow which might look odd depending on the lighting conditions. It can alternatively be rendered with an alpha blend but artefacts can occur where the model polygons overlap. The routine generates a shadow as if the light source is directly above the objects. The appearance of the shadow can be improved in some cases by scaling and rotating the model such that when it is collapsed it looks to be cast by off-centre light source.

It is possible to render a shadow that adapts to the ambient lighting conditions and doesn't suffer from polygon overlap artefacts using the stencil buffer. The stencil buffer is useful because it allows shapes to be rendered without altering the contents of the colour buffers, once the desired shape has been achieved, a shadow polygon can be drawn into the colour buffer with its outline defined by the stencil buffer. The steps used in Corridors of Power to render stencil shadows are as follows:

NB The above routine assumes that a pixel format that includes stencil bits has been selected.

A screen shot showing an example of a complex shadow generated using the stencil buffer is shown below:

Example of Stencil Shadow

3.4.4 Shadow Volumes

This technique is an extension of the above in that a directional shadow is cast from each relevant light source in the scene. So far, I have only investigated techniques for rendering shadow volumes using the stencil buffer but haven't tried them yet. If I ever implement the technique I will expand this section.