Advertisement

Adaptive Depth Bias for Shadow Maps Ray Casting

Started by October 27, 2017 09:08 AM
0 comments, last by Thibault Ober 7 years, 3 months ago

Hi,

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);
    if(ls_t_hit<=0){
        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}\)

where:

  • 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

This topic is closed to new replies.

Advertisement