openglshadershadowshadow-mappingdirectional-light

Understaing shadow acne better


I'm currently learning about shadow mapping from here.

I'm trying to figure why shadow acne is happening at-all, I've tried looking at every video/resource I found online, some relate the issue to floating point rounding errors, other say it's about the size of the shadow map and if it could be infinitely large then this problem wouldn't occur,
but none of the explanation I've seen connects as to why I see this "trippy line pattern": enter image description here

Some explanations even include some sort of abstract drawing that can visually relate to the phenomenon on screen but really don't explain well the underlying reason this happens: enter image description here

I've been scratching my head about this looking everywhere for a whole day for a suffice explanation.
I'm basically looking for a new explanation to this phenomenon, hopefully a clear and friendly one.

Also I would like to know after hopefully understanding the cause of this, how biasing/face culling helps solve this problem, and how they trade this problem for peter penning problem, as I think there's no clear explanation to the why this happens instead of this.


Solution

  • Shadow Acnee can come from different causes.

    The first one is a problem with the precision of your shadow map and the actual depth you compute in your shader. The depth you store in your depth map is mapped from [near, far] to [0, 1].

    You go from a linearized floating point value of 32 bits in the [near, far] range to a non linearized depth (more precision the closer you get from 0) in the [0, 1] range stored in maybe 24 bits. To put it an other way some depth value you compute in your fragment shader will be mapped to the same "texture color" wich will cause the depth test to fail.

    For example with the given formula

    enter image description here

    with near = 1 and far = 1000

    F(700) = 0.99957, F(701) = 0.99948 ~= 0.9995 
    

    Ence if thoose 2 values are mapped to 0.9995 in the depth map due to precision error. When you will compute the depth test the one of them will fail cause 0.9995 < 0.9957.

    The other problem, can come from a shadowMap being too small for your your actual camera point of view (perspective aliasing).

    enter image description here

    As you can see in this pictures the side of the tree takes more place in the camera point of view than in the sadowMap. There are more pixels that covers the side of the tree in the screen than in the shadowMap, ence some pixels you compute in the camera point of view will use the same depth information in the lightPoint of view, some tests might point to the same shadow map pixel and will fai. d > ds

    Adding a bias in both cases, will remove the floating point error, or will compensate the error when 2 depth test point to the same shadowMap pixel. Adding a bias can be seen as margin of error. With the the bias you accept some tests that were rejected before