问题
I've written a simple OpenGL test application about basic shadow mapping technique.
I have removed most artifacts except for the one on the occluder back face. This back face is concerned by artifacts because during the first rendering pass (shadow depth map filling) I enable the front face culling. Consequently I have self-shadowing z-fighting artifacts.
To solve this kind of problem it said on several tutorials the depth of the vertex position in light space need to be biased with a very small offset like 0.0005f.
Here's a screenshot of my problem (for a sake of visibility I have increased the ambient light value for the box). Here without depth offset:
As you can see there is a strong self-shadowing.
Here's a piece of code I use in my fragment shader:
if (ShadowCoords.w > 0.0f)
{
vec4 tmp_shadow_coords = ShadowCoords;
tmp_shadow_coords.z -= 0.0000f; //DEPTH OFFSET DISABLE HERE
shadowFactor = textureProj(ShadowMap, tmp_shadow_coords);
}
Now let's see what happen when using an offset equal to 0.0002f:
tmp_shadow_coords.z -= 0.0002f;
The screenshot:
As you can see the self-shadowing is decreased. Now let's try with an offset equal to 0.0003f :
tmp_shadow_coords.z -= 0.0003f;
The screeshot:
As you can see self-shadowinh has disappeared! But if I zoom towards the limit between the occluder and the shadow we can see an unshaded area. This artifact is called Peter Panning artifact.
So it's a strange situation : to avoid self-shadowing artifact I need to modify the vertex depth value in light space. But this modification of the depth value trains causes a Peter Panning artifact!
The problem is worse if I increase the offset value.
UPDATE
I also tried adding an offset. For example:
tmp_shadow_coords.z += 0.0002f;
Screenshot:
There's less self-shadowing but no Peter Panning artifact. But unfortunatly it appears some artifacts on the front faces of the cube. There's an overflow of the shadow on the front faces.
If I increase the offset:
tmp_shadow_coords.z += 0.0003f;
Screenshot:
The self-shadowing artifacts have completely disappeared but the shadow overflow in front faces is worse.
So I wonder if it's possible to have a render without both self-shadowing artifact and no Peter Panning artifact ?
回答1:
This works pretty well. There is a small gap where the casting surface is very close to the receiving surface.
The main thing to get right in the shader is how a shadow is applied. Scale just the added direct light, diffuse and specular terms, by the shadow/occlusion value (ambient terms should be left alone). An easy check is that surfaces in shadow should look exactly the same as surfaces facing away from the light with shadowing disabled. Shadows should not just make things darker (i.e. finalColour *= 1.0-shadowScale
or finalColour -= shadow
), instead they are the absence of direct light. This becomes very important when multiple lights are involved.
来源:https://stackoverflow.com/questions/26401223/basic-shadow-mapping-artifacts-using-opengl-and-glsl