Shadow map heeeeeeeeeeeelp please.

Hi,

I am trying to get shadow mapping working …have exhausted my own ideas.

I am using this tutorial Tutorial 16 : Shadow mapping but failing to get it working in my own code.

I know the first pass is rendering data into the texture, as I have read it back using:
glReadPixels (0, 0, x, y, GL_DEPTH_COMPONENT, GL_FLOAT, pFloat.getPointer());
and if I create a new texture with this data in the red channel I can see the scene from the light pov. The depth buffer contains values ranging from 0.7 (which is my nearest object) to 1.0 for the background.

I think the problem I have is the reading the depth data back in the subsequent fragment shader.

The tutorial uses sampler2DShadow, and reads it using texture( shadowMap, vec3(ShadowCoord.xy, (ShadowCoord.z)/ShadowCoord.w) ); I have tried this & can’t see any shadows.

I have also tried substituting the shadow texture for regular textures - at this stage just to see if I can read the data. I use sampler2D in the fragment shader, and “texture ( Texture, tx).z” to read it. I have created the texture using :

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);

I find the documentation really confusing. Just focusing on how to read the texture with the depth map in - which sampler & calls should I use to read the depth data?

Thanks for any ideas.

Please post your shaders - I can’t stand to look at those hideous backgrounds in the tutorial you mentioned. :sick:

//
// Vertex & fragment shader to generate the depth map
//

#version 150
// Simple pass through shader that passes 3d position to fragment shader
// Used for generating shadow map textures

in vec4 vPosition;

uniform mat4 ModelView;
uniform mat4 Projection;

void main()
{
gl_Position = (ProjectionModelViewvPosition);
}

#version 150
// Writes the depth of the fragment to the out buffer,
// which is assumed to hold a single float value

out float fDepth;

void main()
{
fDepth = gl_FragCoord.z;
}

//
// vertex & fragment shaders for generating the actual image
//

#version 150
// Shader passes 3d position and light positions to fragment shader
// Plus texture coordinates

in vec4 vPosition;
in vec3 vNormal;
in vec2 vTexture;

// output values that will be interpretated per-fragment
out vec3 fN;
out vec3 fE;
out vec3 fL;
out vec2 tx;
out vec4 fShadowPosition;

uniform mat4 ModelView;
uniform mat4 Projection;

uniform vec4 LightPosition;

uniform mat4 DepthModelView;
uniform mat4 DepthProjection;

uniform mat4 Bias = mat4 (0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);

void main()
{
vec4 normal4 = vec4(vNormal, 0.0);

fN = (ModelView * normal4).xyz;
fE = (ModelView * vPosition).xyz;

if( LightPosition.w != 0.0 )
    fL = LightPosition.xyz - vPosition.xyz;

else
fL = LightPosition.xyz;

gl_Position = (Projection*ModelView*vPosition);

tx = vTexture;
fShadowPosition = (Bias * DepthProjection * DepthModelView * vPosition);
}

#version 150
// Standard 3-component lighting (ambient+diffuse+specular)
// Combined with texture 0

// per-fragment interpolated values from the vertex shader
in vec3 fN;
in vec3 fL;
in vec3 fE;
in vec2 tx;
in vec4 fShadowPosition;

out vec4 fColor;

uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct;
uniform mat4 ModelView;
uniform vec4 LightPosition;
uniform float Shininess;
uniform float Alpha;
uniform sampler2D Texture;
uniform sampler2D DepthMap;

void main()
{
// Normalize the input lighting vectors
vec3 N = normalize(fN);
vec3 E = normalize(-fE);
vec3 L = normalize(fL);

vec3 H = normalize( L + E );

vec4 ambient = AmbientProduct;

float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd*DiffuseProduct;

float Ks = pow(max(dot(N, H), 0.0), Shininess);
vec4 specular = Ks*SpecularProduct;

// discard the specular highlight if the light's behind the vertex
if( dot(L, N) < 0.0 ) 

{
specular = vec4(0.0, 0.0, 0.0, 1.0);
}

float visibility = texture2D ( DepthMap, tx).z; // This is where I am trying to read the depth map
                                                                                           // If I use the regular texture in 'Texture' instead (without the .z), it works
fColor = (ambient + diffuse + specular) * visibility;

fColor.a = Alpha;
}

  1. Use [ code ]…[ /code ] tags when posting code.
  2. You shouldn’t be passing in texture coordinates, you should be using fShadowPosition.
  3. A depth texture only has a single component, so you should be using .x not .z on the result of the texture lookup.
  4. OpenGL 3.3 and later has dedicated shadow samplers (sampler2DShadow) which will perform the depth comparison for you (possibly on multiple texels, allowing for smoother edges). See glTexParameter(GL_TEXTURE_COMPARE_MODE).

The general idea is that in the second pass, you generate an extra set of position coordinates based upon the light position and direction. The light-relative X/Y coordinates are used to perform a lookup in the depth map, and the result of the lookup is compared against the light-relative Z coordinate to determine whether the point is in shadow.

The light-relative coordinates generated in the second pass must match those generated in the first pass, apart from the conversions from the -1…1 range to the 0…1 range.

The shadow logic can be condensed down to just:


// **** Vertex Shader ****

uniform mat4 camera_mv;
uniform mat4 camera_proj;

uniform mat4 light_mv;
uniform mat4 light_proj;

out vec3 t;

void main()
{
    gl_Position = camera_proj * camera_mv * gl_Vertex;
    vec4 q = light_proj * light_mv * gl_Vertex;
    t = (q.xyz / q.w + 1) / 2;
}

// **** Fragment Shader ****

uniform sampler2D depth_map;

in vec3 t;

void main()
{
    float depth = texture(depth_map, t.xy).x;
    float k = t.z < depth ? 1.0 : 0.0;
    gl_FragColor = vec4(k,k,k,1);
}

In practice, the depth test would determine whether or not specular and diffuse lighting are added (ambient would be added regardless).

  1. Use [ code ]…[ /code ] tags when posting code.
    > Ok.

  2. You shouldn’t be passing in texture coordinates, you should be using fShadowPosition.
    > yes, get it … given that didn’t work, in the code above I am just checking I can read information from the texture. If I use UV cords I would expect to see the shadow map on the face of the object I am drawing. right?

  3. A depth texture only has a single component, so you should be using .x not .z on the result of the texture lookup.
    > Will give this a try.

  4. OpenGL 3.3 and later has dedicated shadow samplers (sampler2DShadow) which will perform the depth comparison for you (possibly on multiple texels, allowing for smoother edges). See glTexParameter(GL_TEXTURE_COMPARE_MODE).
    > will give this a go once I can see some shadows, somewhere …


...
    t = (q.xyz / q.w + 1) / 2;
...

> Looks like that is what I am missing - although not yet confident about reading the depth texture.

I will give the whole thing another go in the light on your help, thanks.

[QUOTE=2Wheels;1252370]
2. You shouldn’t be passing in texture coordinates, you should be using fShadowPosition.
> yes, get it … given that didn’t work, in the code above I am just checking I can read information from the texture. If I use UV cords I would expect to see the shadow map on the face of the object I am drawing. right?[/QUOTE]
Yes.

Note that the result may be very faint. Due to the non-linear mapping between eye-space Z and depth, It’s not uncommon for the range of depth buffer values to be quite narrow .

Note that your code was using the “Bias” matrix to perform the conversion from -1…1 to 0…1.

Conversion from homogeneous coordinates can be done either in the vertex shader (passing a vec3 to the fragment shader) or in the fragment shader (e.g. using textureProj() instead of texture()).