Question

I wrote a shadow map shader for my graphics engine. I followed these tutorials: Part 1 and the following part.

Unfortunately, the results I get are quite a bit off. Here are some screenshots. They show what my scene normally looks like, the scene with enabled shadows and the content of the shadow map (please ignore the white stuff in the center, thats just the ducks's geometry).

This is how I compute the coordinates to sample the shadow map with in my fragment shader:

float calcShadowFactor(vec4 lightSpacePosition) {
    vec3 projCoords = lightSpacePosition.xyz / lightSpacePosition.w;
    vec2 uvCoords;
    uvCoords.x = 0.5 * projCoords.x + 0.5;
    uvCoords.y = 0.5 * projCoords.y + 0.5;
    float z = 0.5 * projCoords.z + 0.5;
    float depth = texture2D(shadowMapSampler, uvCoords).x;
    if (depth < (z + 0.00001f))
        return 0.0f;
    else
        return 1.0f;
}

The lightSpacePosition vector is computed by:

projectionMatrix * inverseLightTransformationMatrix
    * modelTransformationMatrix * vertexPosition

The projection matrix is:

[1.0f / (tan(fieldOfView / 2) * (width / height)), 0.0f, 0.0f, 0.0f]
[0.0f, 1.0f / (tan(fieldOfView / 2), 0.0f, 0.0f]
[0.0f, 0.0f, (-zNear - zFar) / (zNear - zFar), 2.0f * zFar * zNear / (zNear - zFar)]
[0.0f, 0.0f, 1.0f, 0.0f]

My shadow map seems to be okay and I made sure the rendering pass uses the same lightSpacePosition vector as my shadow map pass. But I can't figure out what is wrong.

Was it helpful?

Solution

Although I do not understand this entirely, I think I found the bug: I needed to transform the coordinates to NDC space and THEN multiply the matrices. My shadow coordinate computation now looks like this:

mat4 biasMatrix = mat4(
    0.5f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.5f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.5f, 0.0f,
    0.5f, 0.5f, 0.5f, 1.0f
);
vec4 shadowCoord0 = biasMatrix * light * vec4(vertexPosition, 1.0f);
shadowCoord = shadowCoord0.xyz / shadowCoord0.w;

where

light = projectionMatrix * inverseLightTransformationMatrix
* modelTransformationMatrix

Now the fragment shader's shadow factor computation is rather simple:

float shadowFactor = 1.0f;
if (texture(shadowMapSampler, shadowCoord.xy).z < shadowCoord.z - 0.0001f)
    shadowFactor = 0.0f;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top