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
↧