1
\$\begingroup\$

BACKGROUND INFO:

Using MonoGame.

To maximize shadow resolution, I've got a shadow map that covers only the area closest to the camera. (I am aware of Cascading shadow maps, but for now, I am willing to simply lose shadows far away, in exchange for higher resolution near the camera.)

Specifically, I am rendering shadows of tree billboards, that are then cast on to a ground terrain.

First version worked great except for one issue. If a shadow is drawn that touches an edge of the shadow map, then that final row (or column) of pixels is REPEATED by the "Clamp" setting of the sampler. Result is a shadow "streak" that continues from the edge of map into the distance on the ground.


To eliminate those streaks, give full illumination when "outside" of shadow map, I added test to my lookup function to return full illumination (1.0) if UV outside of valid range:

if (texCoord.x < 0 || texCoord.x > 1 || texCoord.y < 0 || texCoord.y > 1)
    return 1.0f;

... followed by the code that looks up in shadow map, returns an illumination in range 0..1.

This works.

I have two questions about this:

  1. Is there a more efficient way to test these 4 conditions, or to avoid the need to test?

  2. Is there an efficient way to solve this when the shadow map is created?
    The sampler is set to "clamp", so if the first and last row and column of map were all "untouched" (held the default depth value or illumination value, depending on the shadowing technique), then I would not need to do any special tests when using the map; "clamp" would retrieve an edge pixel, so if those all were "untouched" by shadows, I would get the desired result.

2.b. It just occurred to me that one solution to (2) is to write the default value back into the four edge rows/columns. [after all shadows are rendered] What is an efficient way to do that?

\$\endgroup\$
1
\$\begingroup\$

You could try using a sampler set up for "border" mode filtering I think (though I never tried it). You can specify a border color for a sampler as well. I guess that out of bounds samples will return the border color automatically. (Ouch and I just read that XNA seems not to support it for some reason)

That said, I think it is good to check if you are actually inside shadow map bounds.

  • You can avoid sampling for pixels that are outside the shadow map. If a lot of pixels are outside, this could gain you performance.
  • I don't like the abrupt change when going outside the shadow map and all shadows disappear. With the bounds check, you can also choose for example two shadow maps (high res and low res) when close to the border and blend between them smoothly.

Also, for the bounds check I like to use code like this:

if(!any(texCoord - saturate(texCoord)))
{
  // we are inside bounds, sample the shadow map...
}

My two cents, good luck with this! :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.