Jump to content
  • Advertisement
Thibault Ober

OpenGL Adaptive Depth Bias for Shadow Maps Ray Casting

This topic is 388 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts


I have found this paper dealing with how to compute the perfect bias when dealing with shadow map.

The idea is to:

  • get the texel used when sampling the shadowMap
  • project the texel location back to eyeSpace (ray tracing)
  • get the difference between your frament.z and the intersection with the fragment's face and your ray.

This way you have calculated the error which serve as the appropriate bias for z-fighting.

Now I am trying to implement it, but I experiment some troubles: I am using a OrthoProjectionMatrix, so i think I don't need to divide by w back and forth.

I am good until I am computing the ray intersection with the face. I have a lot of faces failing the test, and my bias is way to important.

This is my fragment shader code:


 float getBias(float depthFromTexture)
    vec3 n = lightFragNormal.xyz;
    //no need to divide by w, we got an ortho projection
    //we are in NDC [-1,1] we go to [0,1]
    //vec4 smTexCoord = 0.5 * shadowCoord + vec4(0.5, 0.5, 0.5, 0.0);
    vec4 smTexCoord = lightProjectionMatrix * lightFragmentCoord;
    smTexCoord = 0.5 * smTexCoord + vec4(0.5, 0.5, 0.5, 0.5);
    //we are in [0,1] we go to texture_space [0,1]->[0,shadowMap.dimension]:[0,1024]
    //get the nearest index in the shadow map, the texel corresponding to our fragment
   	//we use floor (125.6,237.9) -> (125,237)
    vec2 delta      = vec2(xPixelOffset, yPixelOffset);
    vec2 textureDim = vec2(1/xPixelOffset, 1/yPixelOffset);
    vec2 index      = floor(smTexCoord.xy * textureDim);

    //we get the center of the current texel, we had 0.5 to put us in the middle (125,237) -> (125.5,237.5)
    //we go back to [0,1024] -> [0,1],    (125.5,237.5) -> (0.125, 0.235)
    vec2 nlsGridCenter = delta*(index + vec2(0.5f, 0.5f));

    // go back to NDC [0,1] -> [-1,1]
    vec2 lsGridCenter = 2.0 * nlsGridCenter - vec2(1.0);

    //compute lightSpace grid direction, multiply by the inverse projection matrice or
    vec4 lsGridCenter4 = inverse(lightProjectionMatrix) * vec4(lsGridCenter, -frustrumNear, 0);
    vec3 lsGridLineDir = vec3(normalize(lsGridCenter4));

    /** Plane ray intersection **/
    // Locate the potential occluder for the shading fragment
    //compute the distance t we need to continue in the gridDir direction, the point is "t" far
    float ls_t_hit = dot(n, lightFragmentCoord.xyz) / dot(n, lsGridLineDir);
        return 0; // i got a lot of negativ values it shouldn t be the case
    //compute the point p with the face
    vec3  ls_hit_p = ls_t_hit * lsGridLineDir;

    float intersectionDepth = lightProjectionMatrix * vec4(ls_hit_p, 1.0f).z / 2 + 0.5;
    float fragmentDepth     = lightProjectionMatrix * lightFragmentCoord.z / 2 + 0.5;
    float result = abs(intersectionDepth - fragmentDepth);

    return result;

My intersectionDepth don't match my fragmentDepth, they should be really close

I am struggling with this line of code and the ray plane intersection:

vec4 lsGridCenter4 = inverse(lightProjectionMatrix) * vec4(lsGridCenter, -1.0, 0);

I need to go from NDC space to Eye space, i don't know what should be my z and w component. I am starting with a point in the shadowMap I think my z component should match the near plane so in NDC space it should be -1 but i am not sure. Same for w it's a ray so maybe 0 is a better a choice than one.

I don't know if my plane/ray intersection is wrong but from wikipedia:

\(d = { dot(Po - O) \cdot n \over dir \cdot n}\)


  • dir = my vector normalized direction
  • Po = a point belonging to the the plane
  • O = point belonging to the ray, the origin should match. in eye space the origin should be my light position -> (0,0,0) ?
  • n = normal of the plane, the normal of my fragment in eyespace
Edited by Thibault Ober

Share this post

Link to post
Share on other sites

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!