Update - November 15
I wanted to have better control over the lighting. The GL pipeline gives you black shadows. I wanted to be able to use a shadow lightness setting to allow some of the light to remain unblocked so that details might still be seen even in the shadows. In order to have better control over the lighting, I decided to use a vertex program written in Cg together with register combiners. I set up the shader to handle a point light that casts shadow, a directional fill light, and an optional spot-light orginating at the head. When I tried to use the vertex program I ran into another problem. I set up my vertex program on the outside of the rendering loop. I found out that another vertex program was being used to inside the loop for occlusion culling. I modified that vertex program so that it would not use the parameters that I was using for mine and made sure that occlusion culling saved and restored the previously active vertex program. That still didn't fix the problem. Many hours later I noticed that vertex attribute arrays were enabled in the rendering code and never disabled. This had been the cause of all my woes.
I also found a bug in my perspective shadow map implemenation that was
causing the shadows to get messed up when the light source became inverted
in post-perspective space. One of the biggest problems with shadow maps
is getting the right bias. Ideally you would like to vary the bias depending
on the depth-slope of the polygons. You need a higher bias in areas of
high depth slope to avoid surface self-shadowing effects. The bias gets
wrapped up in the texture matrix when doing hardware texture mapping so
there is no way to vary it per pixel. What you can do though is use PolygonOffset()
to render the shadowmap. In effect this "bakes" the per pixel bias into
the shadow map. When the light source becomes inverted you have to invert
the polygon offset as well. I forgot to do this which caused the problems
that I described in the previous update.
ResultsHere are some images of the partially loaded powerplant model:
Future DirectionI still have to drop in the code for perspective shadow maps. The power plant has much deeper perspective than the toy scene I was using to test the perspective shadow maps. I hope to be able to see greater benefit from using them in the power plant model. There are significant aliasing artifacts with the normal shadow maps.
I am currently integrating the shadow mapping code with SWITCH, a multi-GPU occlusion culling solution. I intend to extend SWITCH to perform occlusion culling from the light source. This will enable me to use dynamic lighting on the Double Eagle oil tanker at a decent frame rate. The GPU that renders the visible geometry will also have to render the shadow map. This will drop the framerate by about a factor of 2 or 3 depending on how much geometry needs to be rendered for the shadow map. One solution to this problem is to use a separate GPU for rendering the shadow map. Since the shadow map is large, it must stay on the GPU. The solution is introduce an extra frame of latency in order to render the shadow map a frame before it is actually used. Two GPUs would alternate, one rendering the visible geometry, while the other renders the shadow map. Compositing hardware can be used to direct the output from both CPUs to a single monitor.
I would also like to implement shadow volumes. The occlusion culling can be used to cull the number of shadow volumes necessary to render a particular view.