Final Report

(NOTE: Click on any of the images for a larger version )

Shadow Maps in the Power Plant

To render dyanmic shadows in the power plant, I integrated my shadow mapping code, including pespective shadow maps with an extended SWITCH system. The new SWITCH uses two GPUs to perform occlusion culling for the eye and  two more for occlusion culling at the light. One GPU renders the shadow map and displays the visible geometry. In the power plant the light and viewpoint can be moved around at 15 fps, achieving my goal of dynamic lighting in a walkthru of a large model. It turns out that two rendering passes does not create a bottleneck in the current system because of other networking latency issues. We have had a number of strange networking problems that have proved an impediment to extensive exploration of the full impact of the shadows in the power plant. In particular, I would have liked to do a walkthru to show the light and viewpoint moving. I will present some stills though. 

Improving Quality

Rendering the shadow map with standard OpenGL does not look very good. The shadow is completely black. To alleviate this problem I used register combiners in conjunction with a vertex program to compute more complex lighting. Instead of having pure black shadows, I block only the contribution of the shadowed light source. Additional light sources may be used. In addition, I provide a shadow lightness parameter that determines the fraction of light that is actually block. Objects tend to look too flat if all the light is blocked because there is no shading variations to reveal surface curvature. Lightening the shadows also keeps them from being too "harsh".

The power plant does not have consistently oriented triangles. Thus some of the vertex normals are flipped. To fix this problem, the system uses two-sided lighting which flips the normals of backfacing triangles.  This can creates some serious problems with shadow maps.  Sometimes objects have triangles consistently defined in the wrong direction and vertex normals in the right direction. The two-sided lighting flips these normals effectively lighting the object from the opposite direction. When a shadow map is applied it shows up in the region where the surface is lit. The shadowed side of an object usually has pretty bad artifacts near the sillouhette because it as at a grazing angle to the light direction. The flipped lighting makes reveals these artifacts accentuates them. Fig.1 shows an example of a single object with this problem.

Figure 1: An object with flipped lighting and a shadow map applied.

To get more correct lighting, I flip the normal whenever it does not face the eye in the vertex program. This can create problems for triangles near silouhettes of curved objects where the vertex normal should face away from the eye because it is the average of the triangle face normals, some of which are facing away from the eye. In practice, these artifacts are much less objectionable than those caused by flipped lighting. More importantly, it permits us to use the models as they are. It is not possible to use a vertex program to do two-sided lighting exactly as is done in OpenGL because there is no access to winding information. Fig. 2 shows the power plant with normals flipped in the vertex program.





Figure 2: a) No shadows. b) Shadows provided by standard OpenGL. c) One-sided lighting without normal flipping. d) Shadows provided by programmable hardware.


Perspective Shadow Maps

Perspective shadow maps can make a great deal of difference for certain light-camera configurations as can be seen in Fig. 3. On average though, I get roughly twice the resolution out of perspective shadow maps as I do out of normal shadow maps. In the worse case they are roughly the same.



Figure 3: Shadows of trusses with a) a standard shadow map and  b) a perspective shadow map.

Fig. 4 shows how shadow maps can add a great deal of depth and realism to the walkthru. Without the shadows everything looks very flat. It is more difficult to understand the geometric relationships between objects. For instance, in Fig. 4a it appears that the geometry is floating above a plane that lies at an indeterminate distance. The shadows eliminate this illusion.




Figure 4: A view of intricate structure a) without shadows, b) with a standard shadow map, and c) with a perspective shadow map.


Though the shadow maps do enhance the walkthru considerably there are still a number of problems. The aliasing of shadow edges is very bad. Features are often missed completely due to the limited resolution of the shadow map. The aliasing problems are most noticeable on surfaces close to the viewer. In the distance, the resolution is usually adequate. This suggests that one possible solution would be to use more than one shadow map. We could render a restricted region close the viewer with one shadow map and the rest of the scene with another, giving us the higher resolution where we need it most.

Another solution is to use an object-based method like shadow volumes. Shadow volumes have recently become popular in games like Doom 3, but they are not a scalable solution. Consider the light configuration of most walkthrus shown in Fig. 5. The light is located somewhere overhead. There are also some occluders overhead that cast shadows on the objects in the view. Most of the shadow frusta are going to fill a large portion of the view. If we take the peak fill rate advertised for the GeForce4 of 4.8 billion pixels per second and divide by 1024x1024 pixels for a full screen we get roughly 4800 screen fills per second. There may 10,000s of shadow polygons generated in a large model. There is no way that the graphics card will be able to deliver the amount of fill power to render the shadow polygons at interactive rates. 

Figure 5: View configuration commonly encountered in walkthrus.

We are going to try another solution. Using the graphics hardware it is possible to determine the exact visible set of polygons for both the eye and light. The light polygons, occluders, that do not cast shadows on the eye polygons, and the eye polygons lying completely in shadow can also be culled. That leaves us with a much reduced set of light polygons that potentially cast shadows on the eye polygons. Since the CPUs are lying idle in the current SWITCH system, we can put them to use to do intersections of shadow frusta and eye polygons to produce shadow polygons on the objects.

One thing that I have learned from this project is that shadows with large models is not a trivial problem. There are a number of difficult issues such as choosing LODs for objects in the light space. Shadows are cast on objects over a wide range of distances and orientations making it difficult to use the projected error metric that the system currently uses. Perspective shadow maps introduce further non-linearities that make this issue more complicated. It will be exciting to see what solutions can be brought to bear on this problem in the future.