9
$\begingroup$

I've been playing around with shadow mapping in OpenGL using depth textures. The depth texture is fine and I can map it onto the scene but I have some strange artefacts on the back of the object:

Sphere casting a shadow, with artefacts on rear

My question is what is causing this and how can I fix it?

The fragment shader I'm using is fairly straightforward (I stripped out the colour for simplicity in case you're wondering why there's no blue here):

in vec4 vShadowCoord;

uniform sampler2DShadow shadowMap;

out vec4 fragColor;

void main()
{
    float bias = 0.005;
    float visibility = 1.0;
    if (texture(shadowMap, vec3(vShadowCoord.xy, vShadowCoord.z / vShadowCoord.w)) < (vShadowCoord.z - bias) / vShadowCoord.w)
        visibility = 0.25;

    fragColor = vec4(visibility);
}

Edit: As requested, minimum working example screenshot that uses only the above code (no colour).

Same sphere, minus colour

$\endgroup$
6
  • 1
    $\begingroup$ Can you confirm whether the code shown (with blue removed) also causes the artefacts? If you have narrowed down the code then showing the image from the narrowed down code will help exclude any irrelevant details and highlight the problem. $\endgroup$ Aug 30, 2015 at 17:23
  • $\begingroup$ Yes it does, I figured I'd take a screenshot with colour in there otherwise it looks even uglier :) $\endgroup$ Aug 31, 2015 at 4:54
  • $\begingroup$ I can understand that, but since it's the ugliness that you're asking for help with, you might have a better chance of someone seeing the problem if you include the screenshot that matches the code too. $\endgroup$ Aug 31, 2015 at 11:04
  • 1
    $\begingroup$ Fair enough. I've added an extra screenshot. $\endgroup$ Aug 31, 2015 at 13:35
  • $\begingroup$ Have you tried playing around a bit more with the bias? $\endgroup$
    – cifz
    Aug 31, 2015 at 19:36

1 Answer 1

11
$\begingroup$

This issue looks like standard shadow map acne artifacts. Additionally your's lighting equation is incomplete or wrong. Light shouldn't influence faces with normals facing away from it. This also means that with a proper equation the "dark" side of the sphere shouldn't have any acne artifacts.

There are three sources of acne artifacts:

  • First acne source is shadow map precision. Make sure that near and far planes of shadow casting light are as tight as possible. All objects before the near plane can be pancaked, as their exact depth isn't important.
  • Second acne source is shadow map resolution. For a directional light you should be doing cascaded shadow maps with at least 3 1024x1012 cascades for ~100-200m of shadow distance. It's hard to cover similar shadow distance with one shadow map with uniform projection.
  • Third acne source is wide shadow map filter like PCF, as using a single depth depth comparison value across a wide kernel is insufficient. There are many methods to fix it, but none of them is robust.

To sum up, a tight frustum with a few cascades and some bias tweaking is enough to get the general case working (directional light). Start tweaking by disabling shadow filtering and tweak for filtering only when basic shadow maps are robust enough.

Additionally apart from the constant depth bias (which you currently use) you should also add slope depth bias and max slope depth bias. Both can be be implemented either as render state or as shader code during shadowmap rendering. Slope depth bias is simply a magic bias value scaled by dot( normal, lightDir ).

There are some additional interesting methods and most of them are implemented in the excellent demo: Matt Pettineo - "A sampling of shadow techniques".

  • Flip culling during shadow map rendering (trades acne for Peter panning).
  • Normal offset shadow mapping does wonders for bias issues, but requires to have vertex normals around during shading.
  • Variance based methods (ESM, VSM, EVSM) completely remove bias issues, but have other drawbacks (light leaking and/or performance issues).
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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