Problems rendering shadows with deferred shading

Hi,
Rendering shadows with deferred shading is driving me crazy!!! :doh:

I’ve been following this tutorial http://www.codinglabs.net/tutorial_opengl_deferred_rendering_shadow_mapping.aspx
in order to have shadows in my deferred implementation.

I already had the deferred with lights working, but I have to implement shadows with spotlights.

My pipeline follows in this order:

  • Create the shadow map in a FBO with Depth_component32 texture (is 32 because I had problems creating the texture and I did different tests).
  • I create the gbuffer
  • I add a directional light using a quad.
  • I add pointlights.
  • I add a spotlight, the one that has to compute shadows.

Here you have the code of the render calling the shadow map function:



glBindFramebuffer(GL_FRAMEBUFFER, shadow_buffer_.id);
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);
    
    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    // Create shadow maps.
    drawShadowMaps(program_shadow_map_, projection_xform);

and here the shadow map render.


void MyView::drawShadowMaps(GLuint program, glm::mat4 projection_light) {

  glUseProgram(program);

  const auto& light = scene_->getAllSpotLights();

  glm::mat4 view_light = glm::lookAt(light[2].getPosition(), 
    light[2].getPosition() + light[2].getDirection(),
    glm::vec3(0, 1, 0));

  // I save the matrices that shadow map use to be able to change the
  // the pixels to world coordinates in the spot frag shader.
  shadow_info_[0].light_view = view_light;
  shadow_info_[0].light_projection = projection_light;

  glm::mat4 view_projection_light = projection_light * view_light;

  for (const auto& instance : scene_->getAllInstances()) {

    glm::mat4 model = (glm::mat4x4)instance.getTransformationMatrix();
    glm::mat4 mvp = view_projection_light * model;

    glUniformMatrix4fv(glGetUniformLocation(program, "projection_view_model_xform"),
      1, GL_FALSE, glm::value_ptr(mvp));

    glUniformMatrix4fv(glGetUniformLocation(program, "model_xform"),
      1, GL_FALSE, glm::value_ptr(model));

    glBindVertexArray(mesh_map_[instance.getMeshId()].vao);
    glDrawElements(GL_TRIANGLES, mesh_map_[instance.getMeshId()].num_elements,
      GL_UNSIGNED_INT, 0);
  }
}

I have tested that the texture was ok drawing it into the fragment shader of the spotLight. Here you have the code of the fragment shader:


#version 330

#extension GL_ARB_explicit_uniform_location : enable

layout(location = 0) uniform sampler2DRect tex_position;
layout(location = 1) uniform sampler2DRect tex_normal;
layout(location = 2) uniform sampler2DRect tex_ambient;

uniform SpotLight_str{
  vec3 light_position;
  float light_range;
  vec3 light_direction;
  float light_angle;
  vec3 light_intensity;
  //float pad0;
};

uniform ShadowMapInfo_str{
  mat4 light_view;
  mat4 light_projection;
  mat4 camera_view;
};

layout(location = 3) uniform sampler2DRect shadow_map_tex;
uniform vec3 camera_position;

out vec4 fragment_colour;

float readShadowMap(vec3 eye_dir) {

  //mat4 mvp_camera = light_projection * camera_view;
  mat4 camera_to_world = inverse(camera_view);

  mat4 camera_to_light = light_projection * light_view * camera_to_world;
  vec4 eye_to_light = camera_to_light * vec4(eye_dir, 1.0);

  eye_to_light = eye_to_light / eye_to_light.w;

  float bias = 0.0001;
  vec2 tex_coord = eye_to_light.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5);
  float depth_value = texelFetch(shadow_map_tex, ivec2(tex_coord.x, tex_coord.y)).r - bias;

  if (eye_to_light.z * 0.5 + 0.5 < depth_value
  ) { return 1.0f; }
  return 0.0f;
  //return depth_value;
}
 
void main(void)
{
  vec3 position = texelFetch(tex_position, ivec2(gl_FragCoord.x, gl_FragCoord.y)).rgb;
  vec3 normal = texelFetch(tex_normal, ivec2(gl_FragCoord.x, gl_FragCoord.y)).rgb;
  vec3 ambient = texelFetch(tex_ambient, ivec2(gl_FragCoord.x, gl_FragCoord.y)).rgb;

  float shad = texelFetch(shadow_map_tex, ivec2(gl_FragCoord.x, gl_FragCoord.y)).r;

  // Calculating the direction and the size of the cone.
  vec3 light_to_position = normalize(position - light_position);
  vec3 ldirection = normalize(light_direction);
  float spot_factor = dot(light_to_position, ldirection);

  // Vector from the light to the pixel.
  vec3 L = light_position - position;
  float d = length(L);

  // normalize Light and normal vector.
  L = normalize(L);
  vec3 N = normalize(normal);

  /////// SHADOW TEST!!
  vec3 eye_direction = position - camera_position;

  // The half of the angle. This is because we have to compare the angle
  // between direction and 
  float cutoff = light_angle * 0.5;

  float shadow = readShadowMap(eye_direction);

  if (spot_factor > cos(cutoff)) {

    float attenuation = (1.0 - (1.0 - spot_factor) * 1.0 / (1.0 - cos(cutoff)));
    float Iin = d / (1.0 + 0.005 *d + 0.009*d*d);

    float Iout = max(0, dot(L, N)) * shadow * Iin * attenuation;
    //float depth = 1.0 - (1.0 - shad) * 25.0;

    fragment_colour = vec4(vec3(Iout), 1.0);
  }
  else {
    fragment_colour = vec4(vec3(0.0, 0.0, 0.0), 1.0);
  }
}

the problem I have is that when I’m looking the light in the opposite direction, it always returns 0.0f.
[ATTACH=CONFIG]1040[/ATTACH]

But if I put the camera looking in the same direction of the light, then I receive some white floats, depending of my view, the “light” moves…
[ATTACH=CONFIG]1041[/ATTACH][ATTACH=CONFIG]1042[/ATTACH]

The weirdest thing is that if I return depth_value var (The value that stores the reading pixel) and I render the value. if I move the camera, it makes the same moving “light”, and
I don’t understand why is happening that because I’m not making any comparison or calculation, I’m just reading the texture and rendering directly… :confused:

Here you can see the light working without calculating shadows.
[ATTACH=CONFIG]1043[/ATTACH]

Any idea about what’s happening? I am a little bit lost right now.
Thank you very much!! :slight_smile:

Edit:
Changing the texture to GL_TEXTURE2D instead of G_TEXTURE_RECTANGLE made significant changes. Now I can see shadows… but it depends on where is the camera, and of course are wrong…
but at least in the picture below you can see the shadow of the buda…
[ATTACH=CONFIG]1044[/ATTACH]

I couldn’t fix this problem yet…
I tested the matrices, the shadow map texture etc… with no results.

Could anyone help with the problem? I really need to fix it!!

Thank you!