shadow mapping - texture clamping

I implemented a simple shadow mapping. In a shader I use sampler2DShadow and textureProj when accessing a texture. Then I multiply a color(diffuse and specular) by a shadow value. A depth texture has following parameters:


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);    

A point light is situated close to the object and this is a good occasion to understand how texture clamping works. In the first case I use these settings for clamping:


GLfloat border[] = {0.0f,0.0f,0.0f,0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

That give following result: image1

When I change a border color to {1.0f,0.0f,0.0f,0.0f } the entire ground should be illuminated but I get this result: image2 and I don’t understand why.

[QUOTE=Triangle;1243350]


GLfloat border[] = {0.0f,0.0f,0.0f,0.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

… When I change a border color to {1.0f,0.0f,0.0f,0.0f } the entire ground should be illuminated but I get this result: image2 and I don’t understand why.[/QUOTE]

That’s your light-space near and far clip plane cutting into the plane.

You set what happens for S and T wrapping (i.e. when you’re off-to-the-side of your shadow map frustum in light space). But you didn’t set what happens when you’re in front of or behind the shadow map frustum in light space (R wrap behavior I’d guess).

Haven’t tried this myself, but my guess is you want:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);

The R value is your depth value. Thus TEXTURE_COMPARE_MODE == COMPARE_R_TO_TEXTURE.

A perspective matrix for shadows has zNear = 1.0 and zFar = 50.0 for above pictures. When I increase zFar (for example zFar = 70.0) I get following result (clamping to border(1, 0, 0, 0) s,t) : image3. When I add


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);

nothing is changing. I don’t understand why when I set clamping to border (1, 0, 0, 0) iluminated area is bigger but only “before” the projection from the image1.

Think I’ve got something for you. Obviously when you pushed the light-space (shadow-space) far clip out to extend your shadow frustum out further, you got valid shadow testing results out further in your scene. I think the reason is this (and I should have thought of it before). When you do a lookup into your shadow map into an area where there are no shadow casters, what do you get? A window-space Z of 1 (i.e. the frustum’s far clip value). What window-space Z value do points on your plane object within the left/right/top/bottom bounds of your light-space frustum but beyond its far clip plane have? A window-space Z value > 1. So what happens with the depth comparison? The “far clip” pixels in your shadow map end up occluding those more-distant points on the plane. So your shadow map appears to shadow things behind it’s frustum.

Seems like to deal with the “receiver pixels beyond light-space far clip” issue you need to have your shadow map extend to encompass all potential receiver pixels, OR (as a not-perfect work-around), you need to treat far clip values (i.e. 1 values) in the shadow map as non-occluders. Not sure if/how you can do that with hardware depth comparisons (may have forgotten something here though). Could do it with your own lookups But simplest to do the former.

As to your “receiver pixels in front of the light-space near clip” (or light-space origin – i.e. the light source location), seems its a different but similar problem. You know that nothing in front of the light-space near clip can be occluded. In fact you’re going to get invalid math in the perspective divide for points at the same light-space Z as the eyepoint. Not really sure what happens internally in shadow2Dproj in this case, but you could just treat visibility as 1 for this case.

Also, not sure that clamp to border 1 makes any sense for S and T either. I think this says to substitute the light-space far Z clip value for areas outside the shadow map which is bogus and could lead to false occlusion problems.

So generally, if when applying shadows to the scene in the eye-frustum pass, for fragments outside the light-space frustum (you can check this) then it’s not occluded. The one possible exception you might make being for areas beyond the light-space far clip, where you might want to let these shadows cast beyond the light-space frustum (in the case that you’re tight-fitting your light-space frustum to only the shadow casters). However I think it’s more common to ensure your shadow map(s) encompass all potential “receiver” pixels. With this approach, you can deal with out-of-frustum casters closer to the light by smashing them onto the near plane of the shadow map with depth clamp when rasterizing the shadow map.