Shadow mapping with a deferred rendering

2.4k views Asked by At

I am trying to implement a shadow mapping technique and I have some problems to make it works.

I have a camera in the light's position and this is the shadow map I get. All the vertex have been multiplied by each modelViewProjectionMatrix.

Camera light's view

I also have a texture with the world positions of the vertex. It's a GL_RGBA32F texture because all the points have been multiplied by each ModelMatrix to have the points in world space.

enter image description here

And the shader:

layout(binding=5) uniform sampler2D shadowMap;
layout(binding=6) uniform sampler2D positionMap;

in vec2 texcoord;
uniform mat uViewProjectionMatrix;

out vec4 color;

void main() {

   vec4 pos = texture(positionMap, texcoord);

   vec4 ShadowCoord = uViewProjectionMatrix * pos;
   ShadowCoord.xy = ShadowCoord.xy * vec2(0.5,0.5) + vec2(0.5,0.5);

   float a = texture(shadowMap, ShadowCoord.xy).z;
   color = vec4(a, a, a, 1.0);
}

The output (the camera is almost in the same position of the light):

enter image description here

I am just trying to see if the projection of each vertex is right from the camera's position but looks like it's not. The point of all this is to compare:

if ( texture(shadowMap, ShadowCoord.xy).z <  ( ShadowCoord.z-bias ) )

but it also doesn't work.

I would appreciate any help. Thank you.

1

There are 1 answers

4
Andon M. Coleman On BEST ANSWER

You are missing the perspective divide and you seem to be completely ignoring depth range.

The general idea here is to get ShadowCoord.xyz into the range [0,1] (for texture lookup and depth comparison). Your code operates under the assumption that uViewProjectionMatrix * pos (clip-space coordinates) is in the range [-1,1] but that is not really guaranteed unless you divide by w (NDC coordinates).

I would consider something like this instead:

void main() {
  vec4 pos = texture(positionMap, texcoord);

  vec4 ShadowCoord = uViewProjectionMatrix * pos;
  ShadowCoord /= ShadowCoord.w;

  ShadowCoord.xyz = ShadowCoord.xyz * vec3 (0.5f, 0.5f, 0.5f) + vec2 (0.5f, 0.5f, 0.5f);

  float a = texture(shadowMap, ShadowCoord.xy).z;
  color = vec4(a, a, a, 1.0);
}

After this, ShadowCoord.xy will be a texture coordinate to lookup in your shadow map, and ShadowCoord.z will be the current fragment's depth from your light's point of view. You can use ShadowCoord.z for comparison versus the sampled depth.

In fact, you might even consider using a sampler2DShadow to do this more efficiently. For an example of that, see this related question and answer