0

I'm having a little trouble on implementing Shadow Mapping in the Engine I'm doing. I'm following the LearnOpenGL's tutorial to do so, and more or less it "works", but there's something I'm doing wrong, like if something in the shadowmap was reverted or something, check the next gifs: gif1, gif2

In those gifs, there is a simple scene with a directional light (which has an orthogonal frustum to make the shadow calculations and to ease my life), which has to cast shadows. Then, at the right there is a little window showing the "shadow map scene", the scene rendered from light's point of view only with depth values.

Now, about the code, it pretty follows the guidelines from the mentioned tutorial. I have a ModuleRenderer and I first create the framebuffers with the textures they have to have:

    glGenTextures(1, &depthMapTexture);
    glBindTexture(GL_TEXTURE_2D, depthMapTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, App->window->GetWindowWidth(), App->window->GetWindowHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

    glGenFramebuffers(1, &depthbufferFBO);
    glBindFramebuffer(GL_FRAMEBUFFER, depthbufferFBO);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMapTexture, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

Then, in the Module Renderer's post update, I make the 2 render passes and draw the FBOs:

    // --- Shadows Buffer (Render 1st Pass) ---
    glBindFramebuffer(GL_FRAMEBUFFER, depthbufferFBO);
    SendShaderUniforms(shadowsShader->ID, true);
    DrawRenderMeshes(true);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // --- Standard Buffer (Render 2nd Pass) ---
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    SendShaderUniforms(defaultShader->ID, false);
    DrawRenderMeshes(false);

    // --- Draw Lights ---
    std::vector<ComponentLight*>::iterator LightIterator = m_LightsVec.begin();
    for (; LightIterator != m_LightsVec.end(); ++LightIterator)
        (*LightIterator)->Draw();

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // -- Draw framebuffer textures ---
    DrawFramebuffer(depth_quadVAO, depthMapTexture, true);
    DrawFramebuffer(quadVAO, rendertexture, false);

The DrawRenderMeshes() function, basically gets the list of meshes to draw, the shader it has to pick, and sends all needed uniforms. It's a huge function to put here, but for a normal mesh, it gets a shader called Standard and sends all it needs. For the shadow map, it sends the texture attached to the depth FBO:

    glUniform1i(glGetUniformLocation(shader, "u_ShadowMap"), 4);
    glActiveTexture(GL_TEXTURE0 + 4);
    glBindTexture(GL_TEXTURE_2D, depthMapTexture);

In the standard shader, for the vertex, I just pass the uniform for lightspace (the light's frustum projection x view matrices) to calculate the fragment position in light space (the next is done in the vertex's main):

    v_FragPos = vec3(u_Model * vec4(a_Position, 1.0));
    v_FragPos_InLightSpace = u_LightSpace * vec4(v_FragPos, 1.0);
    v_FragPos_InLightSpace.z = (1.0 - v_FragPos_InLightSpace.z);
    gl_Position = u_Proj * u_View * vec4(v_FragPos, 1.0);

And for the fragment, I calculate, with that value, the fragment's shadowing (the diffuse+specular values of light are multiplied by the result of that shadowing function):

float ShadowCalculation()
{
    vec3 projCoords = v_FragPos_InLightSpace.xyz / v_FragPos_InLightSpace.w;
    projCoords = projCoords * 0.5 + 0.5;
    float closeDepth = texture(u_ShadowMap, projCoords.xy).z;
    float currDept = projCoords.z;

    float shadow = currDept > closeDepth ? 1.0 : 0.0;
    return (1.0 - shadow);
}

Again, I'm not sure what can be wrong, but I can guess that something is kind of inverted? Not sure... If anyone can imagine something and let me know, I would appreciate a lot, thanks you :)

Note: For the first render pass, in which all scene is rendered only with depth values, I use a very simple shader that just puts objects in their position with the common function (in the vertex shader):

gl_Position = u_Proj * u_View * u_Model * vec4(a_Position, 1.0);

And the fragment doesn't do anything, is an empty main(), since it's the same than doing what we want for shadows pass

gl_FragDepth = gl_FragCoord.z;
LuchoSuaya
  • 77
  • 10

0 Answers0