PDA

View Full Version : Masking out pixels from a shadowmap. ( sampling shadowmap texture with z > 1.0 )



RenHoek
10-19-2014, 01:42 PM
Hi all

I'm currently working on an environment renderer which needs to cover large scales.
Because of this I'm needing to optimize our shadow mapping to make better use of precision.
One step I've taken is to separate the concept of shadow casters from shadow receivers.

Agents on the Terrain = shadow casters + shadow receivers
The Terrain = shadow receiver

This works well because the agents cover a much smaller bounding area than the terrain, so it allows us to concentrate our shadowmap precision only over that area. And people only care about the agent shadows on the terrain ( rather than the terrain casting any shadow itself. actually, they prefer to not have any terrain shadows anyway : ) )

The problem I have during rendering is having to sample the shadowmap at a range past its far clip area.
ie....
float shadow = texture(shadowMapSampler, coordinate);
where coordinate.z > 1.0

Currently I'm getting black because the shadowmap depth values were all initialized to a maximum of 1.0 before construction.
My current fix is to just clamp the coordinate.z to 0.999 ( chosen arbitrarily )
But this seems like a hack.

My questions is this.
Is there a more elegant way to cope with this problem?
eg
- is it possible to tell openGL to ignore all pixels of value 1.0?
- is there a less-arbitrary value to clamp my z coordinate too?
- ...?

Given that this must be a common problem for people, I hope there's a standard way of dealing with this.
Thanks everyone
Ren

mlfarrell
10-22-2014, 12:25 AM
This is an interesting idea. I'd be curious to know myself.

Have you tried using glDepthRange to limit the max Z ?

Dark Photon
10-25-2014, 07:20 PM
You've got a few choices. One is to just the light-space far clip of your shadow frustum out beyond the furthest possible receiver.

If you don't, then you're right -- you've got this wall of "far clip values" in your light-space frustum shadowing everything behind it, ...if you use a standard fixed-point depth buffer with a clear value of 1.0.

If you do your own depth comparisons, then you could conceivably fetch from your shadow map and treat value == 1.0 lookups as unoccluded (unshadowed) samples. Or use glDepthRange to limit your valid depth values to 0..something_less_than_1.0 so you know for sure that 1.0 is "definitely" an untouched shadow texel. Or use a floating-point depth buffer and clear it to something outside the 0..1 range so you know for sure which texels are completely untouched since clear.

OTOH if you use hardware depth comparisons, this isn't gonna work too well unless you arbitrarily "push" your fragment's depth value up to the next depth step just less than the your max shadow depth value (e.g. for a 24-bit depth buffer with a 0..1 depth range, 0xfffffe). Also, that falls apart if you've got anisotropic texture filtering going on (which can cause a wider area of your depth map to be sampled), but generally you should disable aniso filtering on shadow maps for this reason (applying it causes you to have to apply alot more bias than you should to avoid crazy non-local shadowing from this wide-area texture filtering when sampling edge-on.

So it's somewhat a hack, but you've got some options if you want to try this.