2

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.

Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
MikeFadeCrew
  • 107
  • 2
  • 11

1 Answers1

5

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

Community
  • 1
  • 1
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • In case it was not clear in the answer, I also adjusted your code so that it scales and biases the clip-space `z` coordinate into the range [**0**,**1**] (from [**-1**,**1**]). The value fetched from the shadow map is going to be in [**0**,**1**] so you cannot ignore that step. You need to do it for `xyz`, not just `xy` like you were originally. – Andon M. Coleman Dec 13 '14 at 18:55
  • A 'gotcha' with sampler2DShadow is that is samples using nearest even if linear is used for the min/mag filters. This can be confusing if you were looking to reduce shadow acne by utilizing linear interpolation on the shadow map depth. See http://gamedev.stackexchange.com/questions/88187/c-opengl-shadowmap-issue-artifacts – Paul Renton Dec 13 '14 at 20:24
  • @PaulRenton: Indeed, what it actually interpolates is the result of the 4 binary pass/fail depth tests for the 4 nearest neighbor depth samples. That's explained in the answer I linked to. – Andon M. Coleman Dec 13 '14 at 22:56
  • Wow! That was the problem. I have already tried to divide by w but I forgot to do the multiplication and the addition in the z component... so when i compared the depths... weird things happened. Thank you very much for your time. – MikeFadeCrew Dec 14 '14 at 15:28