Single-pass midpoint shadow maps

Tuesday May 10, 2011

Here’s a little idea I had today. I haven’t seen this posted anywhere else so I thought I’d note it down.

How to generate a midpoint shadow map in one pass:

  • Create a shadowmap render target with two channels, which supports blending (e.g. D3DFMT_G16R16F). No z-buffer is needed here.
  • Clear your shadowmap texture to the far clip (in both channels).
  • Turn off z-writes and z-tests.
  • Set the framebuffer blend mode to ‘MIN’.
  • Turn off backface culling.
  • Render your model.

The trick is, in the shader, simply check the VFACE semantic and based on the result, either write [r=depth, g=+inf] or [r=+inf, g=depth] out (where +inf is the far-clip value).

There’s probably other ways too to work out if it’s a backfacing triangle instead of VFACE.

To test against this, when you read the shadowmap simply average the R and G channels to obtain the midpoint depth. You can run a pass to do this first if you like, or you can do it as you sample the texture.

Disclaimer: I do not claim that this will stop shadowmaps from making you cry yourself to sleep at night.

— Kayamon
---

Tuesday May 10, 2011

  1. You can just write out r=depth and g= -depth, then r will be min depth and g will be the max depth (because it will be the most negative).

    — imccown
    ---

    · May 10, 08:17 AM · #

  2. imccown, that’s not the same thing. That gives you the furthest depth in the scene, not the secondmost depth (which is what you’d want for midpoint shadow maps).

    — Kayamon
    ---

    · May 10, 01:36 PM · #

  3. interesting logic, but disables several flavors of nifty depth hardware. similar in spirit: disable BF culling. in GS, send triangle to RT A or B depending on facing.

    let me zoom out a bit – there is no honest way to map shadows. tracing rays per pixel is required, but algorithms from ray tracing literature are useless.

    — bryan mcnett
    ---

    · May 12, 02:48 PM · #

  4. Oh yeah, it definitely fixes one problem and opens up a whole set of new ones :-)

    I think the main problem with shadow maps is biasing, and wide PCF kernels which make the whole thing much worse.

    I think the real solution to this is PCSS, and specifically screen-space PCSS. Do the shadow test only once per pixel, using a very thin filter kernel, and then blur the results out. That way, every shadow test will track the receiving geometry exactly, and needs little bias.

    — Kayamon
    ---

    · May 12, 07:56 PM · #

  5. If that means there’s no shadow map data structure, then I agree. The relevant data structure is a bitmask per screen pixel, where the ratio of on bits to off bits determines the degree of shadowing. 32 or 64 bits per pixel should suffice.

    — Bryan McNett
    ---

    · May 13, 11:18 PM · #

  6. It’s so great. Thanks.
    I use this method as first pass of creating shadow map.
    In second pass, I use simple pixel shader that computes Mid-point depth and write mid-point depth to shadow depth buffer.
    After second pass, A shadow projection is same as normal H/W shadow mapping.

    — Changmin
    ---

    · Nov 20, 07:20 PM · #

(optional, only used to notify you of replies)
(optional)
 
---