Thoughts About the ZP+ Alorithm

A couple of months ago, a paper entitled ZP+: Correct Z-pass Stencil Shadows came across my inbox. I gave it a cursory scan, but nothing earth-shattering jumped out at me, so I didn’t give it much more thought. Recently, the paper has been brought to my attention several more times, so I decided to take a deeper look.

In general, I think the ZP+ algorithm is a poor substitute for a robust implementation of mixed z-pass/z-fail. Here are my reasons:

  1. ZP+ places restrictions on the spatial relationships between lights and geometries. What the authors call the “light pyramid” cannot contain any shadow-casting geometry, so you’re out of luck if you want to do something like place a light in the center of a torus or have a light pass through any concavity that a model might have. Mixed z-pass/z-fail handles these situations nicely without any need for detection or special action.
  2. The ZP+ algorithm does not render without artifacts in all cases. The authors even admit that there is at least one case in which they must switch to z-fail to get correct results. In other cases, I’m not convinced that the sparkles are as infrequent or as unnoticeable as the authors subjectively claim they are. The whole idea of trying to align two completely different projections and then attempting to compensate for the inevitable artifacts seems very inelegant to me.
  3. The authors’ implementation of the z-fail method (for performance comparisons) is extremely poor. They separate all of the triangles in a mesh into independent faces with unique vertices in order to sort for light and dark caps in a vertex program, effectively killing the post-transform cache performance. I don’t think their comparison between ZP+ and z-fail is fair because of this reason, and indeed the authors state that the results were highly dependent on vertex count.
  4. Lastly, the authors make no mention of combining z-pass and z-fail, using the latter on a per-geometry basis only when necessary. They claim that ZP+ is generally about 10% slower than z-pass, but have neglected to consider that less than 10% of the shadow-casting geometries in many scenes actually require switching to z-fail. Thus, using mixed z-pass/z-fail should still be faster in general, and the added complexity of ZP+ can be avoided altogether.

One more claim that the authors make is that z-fail can be up to 80% slower than z-pass. I ran some tests in the C4 Engine, and found that forcing z-fail all the time was an average of 9% slower than using z-pass all the time. (Of course, using z-pass all the time produces artifacts.) Rendering shadow volumes robustly with mixed z-pass/z-fail was only 6% slower than using z-pass all the time. In my opinion, this is pretty good, and the hassle of something like ZP+ simply isn’t worth it.