Tuesday, May 24, 2011

Cube shadow maps and a bug in PIX

Originally I was rendering the scene with a given shadow map to a temporary texture.  This texture was then rendered additively (alpha blending ONE, ONE, ADD) to the default render target in order to accumulate the various light and shadow map effects.  The reason I was rendering to a temporary texture rather than the default render target directly was that the additive rendering would cause part of the floor to show through your character (and other similar problems).

Promit in the #gamedev IRC channel pointed out that you can solve this by filling the default depth buffer in a pre-pass (this pass would also include adding any ambient lighting) and then disabling writes to the default depth buffer and setting the z compare function to "equal".  This causes only the pixels on the top to be rendered additively in subsequent passes, so you don't get any bleedthrough where there shouldn't be any.

After making that change, I moved on to implementing omni shadow mapping using a cube texture rather than 6 explicit textures.  For details on implementing this, I recommend these two articles: Cubic Shadow Mapping in Direct3D and GPU Gems - Chapter 12. Omnidirectional Shadow Mapping.

One really annoying "bug" I encountered turned out to be the fault of PIX.  While debugging the cube texture version of the shadow mapping code, I discovered (through PIX) that the depth buffer being generated in the pre-pass was empty.  I eventually narrowed the problem down to a single render state: D3DRS_COLORWRITEENABLE.  When I set this render state to 0, writing to the depth buffer appeared to be turned off as well.  Enabling all color writing also appeared to enable depth buffer writing.  This made no sense at all, and I was starting to suspect that it was an obscure problem with the ATI Radeon X1000 series (again).  Fortunately, I discovered the real problem quite by accident; apparently when you disable color writing in your application, it is also disabled in PIX.  So when PIX goes to display the depth buffer, nothing is actually displayed.  The depth buffer can be seen perfectly fine after enabling color writing, but this is hardly an ideal situation.  Oh well, considering the software is free I can't really complain too much.

After using a cubic shadow map and a depth pre-pass I was able to get 6 omni lights with shadow mapping to be displayed on the screen at about 28 FPS.  Most situations won't call for many omni lights, so I can probably work with this restriction.

No comments:

Post a Comment