Saturday, December 6, 2008

Dual-Paraboloid Shadow Maps

Here is an interesting post on Dual-Paraboloid Shadow maps. Pat Wilson describes a single pass approach here

This is pretty cool. Culling stuff into the two hemispheres is obsolete here. Other than this the usual comparison between cube maps and dual-paraboloid maps applies:

  • the number of drawcalls is the same ... so you do not save on this front
  • you loose memory bandwidth with cube maps because in worst case you render everything into six maps that are probably bigger than 256x256 ... in reality you won't render six times and therefore have less drawcalls than dual-paraboloid maps
  • the quality is much better for cube maps
  • the speed difference is not that huge because dual paraboloid maps use things like texkill or alpha test to pick the right map and therefore rendering is pretty slow without Hierarchical Z.

I think both techniques are equivalent for environment maps .. for shadows you might prefer cube maps; if you want to save memory dual-paraboloid maps is the only way to go.

Update: just saw this article on dual-paraboloid shadow maps:

The basic idea is that you do the WorldSpace -> Paraboloid transformation in the pixel shader during your lighting pass. That avoids having the paraboloid co-ordinates interpolated incorrectly.


Aurelio said...

We used Dual-Paraboloids for a game I worked on and while it looked pretty good, the slowest part of the game was the scene traversal, so doing TWO traversals for both maps was a nightmare. Lots of late nights optimizing the PS3 code for it, as I'm sure you can imagine.

I like Dual-Paraboloid but the seam down the middle is really hard to hide, so if you notice that kind of stuff it's probably not your best bet.

Pat Wilson said...

The draw call number should be at the absolute minimum for the single-pass DPM idea. Basically what you are doing is a box query on your scene, and rendering everything inside the radius of the light. You only render each thing once, and there need not be any material switches in between.

There are exaggerated seam issues, though, and I have a few theories on where they are coming from, and how to avoid them. I have a feeling that the lack of a clip step is partly responsible for the artifacts. When you draw the front and back maps seperatly, verts which get transformed to the back side will get clipped as their z-coordinate goes negative. In the single pass case, no z-value goes negative. I have a suspicion that the result is improperly transformed triangles near the seams. What I am seeing on things like the floor of the level is that things are almost 'curving back' on the front map. This is the kind of artifact I would expect from a triangle which would otherwise have one or more of it's verts clipped.

The real performance implication that I am concerned about is rendering without a z-buffer, and using the alpha blend to do pixel rejection.

Brian said...

I also work(ed) on the game/engine that Aurelio is describing, and I remain a fan of the DPSM technique. We're still doing two passes (one per hemisphere), and based on the suggestions from the gamedev thread, I just moved the clipping plane back slightly in each case. Now, we have almost no seam whatsoever. I'm not sure why it took so long for us to realize the (very simple) fix.

We've also shrunk our paraboloids a tiny bit (leaving a few texels on either side), which is necessary to avoid artifacts at the extremes of X and Y when doing filtering (where the circle is tangent to the viewport).