2
\$\begingroup\$

I am facing a really frustrating problem. After looking at a lot of tutorials (probably all existing on net, not kidding), i tried to do the point light shadow mapping using a cube texture.

The problem is: when i try to visualize my cube map, EVERYTHING is white.

I have no clue what is causing this.

Here is what it looks like when i try to visualize my cube map:

(NOTE THAT MY MODELS ARE at (-1,0,0) and (1,0,0) respectively and my light is at (0,2,0) )

enter image description here

And here what it should looks like (Not my project, but just for the colors)

enter image description here

Here is my cubeTexture class:

Shadow::Shadow(e_LightType* light) {
    m_type = light;


    [.... non-usefull code before ....]

    else if (*m_type == e_PointLight) {
        glGenFramebuffers(1, &m_depthMapFBO); //Create frame buffer
        m_shadowWidth = 1024; //Set shadow map size
        m_shadowHeight = 1024;

        glGenTextures(1, &m_depthMap);
        glBindTexture(GL_TEXTURE_CUBE_MAP, m_depthMap);

        for (GLuint i = 0; i < 6; i++) { //MAYBE ERROR WITH ++I
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT32F, m_shadowWidth, m_shadowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
        }

        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);


        glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO);
        glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_depthMap, 0);

        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);

        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            std::cout << "Framebuffer not complete!" << "\n";

        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        m_aspect = (GLfloat)m_shadowWidth / (GLfloat)m_shadowHeight;
        m_near = 1.0f;
        m_far = 25.0f;
        SetShadowProjection();
    }

}


void Shadow::SetShadowProjection() { //Private
    m_shadowProjection = glm::perspective(90.0f, m_aspect, m_near, m_far);
}

void Shadow::SetShadowTransformMatrixs(glm::vec4& position) { 
    glm::vec3 lightPos = glm::vec3(position.x, position.y, position.z);
    m_shadowTransformMatrixs.clear();
    SetShadowProjection();


    for (int i = 0; i < 6; ++i) {
        glm::mat4 m(1);
        glm::mat4 r;

        switch (i) {
        case 0:
            r = glm::mat4(glm::vec4(0, 0, -1, 0), glm::vec4(0, -1, 0, 0), glm::vec4(-1, 0, 0, 0), glm::vec4(0, 0, 0, 1));
            break;
        case 1:
            r = glm::mat4(glm::vec4(0, 0, 1, 0), glm::vec4(0, -1, 0, 0), glm::vec4(1, 0, 0, 0), glm::vec4(0, 0, 0, 1));
            break;
        case 2:
            r = glm::mat4(glm::vec4(1, 0, 0, 0), glm::vec4(0, 0, 1, 0), glm::vec4(0, -1, 0, 0), glm::vec4(0, 0, 0, 1));
            break;
        case 3:
            r = glm::mat4(glm::vec4(1, 0, 0, 0), glm::vec4(0, 0, -1, 0), glm::vec4(0, 1, 0, 0), glm::vec4(0, 0, 0, 1));
            break;
        case 4:
            r = glm::mat4(glm::vec4(1, 0, 0, 0), glm::vec4(0, -1, 0, 0), glm::vec4(0, 0, -1, 0), glm::vec4(0, 0, 0, 1));
            break;
        case 5:
            r = glm::mat4(glm::vec4(-1, 0, 0, 0), glm::vec4(0, -1, 0, 0), glm::vec4(0, 0, 1, 0), glm::vec4(0, 0, 0, 1));
            break;
        }

        m = glm::translate(m, lightPos);
        m = r * m;

        m_shadowTransformMatrixs.push_back(m_shadowProjection * m);
    }


    /*m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
    m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
    m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
    m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
    m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
    m_shadowTransformMatrixs.push_back(m_shadowProjection * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));*/
}


void Shadow::RenderToDepthMap() {
    switch (*m_type) {
        case e_DirectionnalLight:
        case e_Spotlight:
            glViewport(0, 0, m_shadowWidth, m_shadowHeight);
            glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO);
            glClear(GL_DEPTH_BUFFER_BIT);
            break;
        case e_PointLight:
            glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO);
            glViewport(0, 0, m_shadowWidth, m_shadowHeight);
            glClear(GL_DEPTH_BUFFER_BIT);
            break;
    }
}

I create a new light that incorporate a shadow of type point light.

Here is my render function (With both rendering pass)

void Render() {
    //--------------- SHADOW ------------------
    glCullFace(GL_FRONT);



    GLuint texLoc;

    m_Shaders[e_CubeShadowMap]->Bind();

    m_lights[0]->GetShadow()->RenderToDepthMap();
    m_lights[0]->GetShadow()->SetShadowTransformMatrixs(m_lights[0]->GetPosition());


    for (int i = 0; i < 6; i++) { //i++ maybe error since i did ++i in shadow class
        GLuint location = glGetUniformLocation(*m_Shaders[e_CubeShadowMap]->GetProgram(), "shadowMatrices");
        glUniformMatrix4fv(location + i, 1, GL_FALSE, glm::value_ptr(m_lights[0]->GetShadow()->GetShadowTransformMatrixs()->at(i)));
    }


    m_Shaders[e_CubeShadowMap]->SetUniform("lightPos", m_lights[0]->GetPosition());
    m_Shaders[e_CubeShadowMap]->SetUniform("far_plane", m_lights[0]->GetShadow()->GetFar());


    if (m_objectPool.size() > 0) {
        for (Model* m : m_objectPool) {
            m->Render(m_Shaders[e_CubeShadowMap]->GetProgram());
        }
    }

    m_lights[0]->GetShadow()->Unbind();

    //--------------- Normal rendering with shadow  ------------------
    glCullFace(GL_BACK);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Set black as clear color - Set him the depth
    glViewport(0, 0, glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT));



    m_Shaders[e_Shadow]->Bind();
    m_Shaders[e_Shadow]->SetUniform("lightPos", m_lights[0]->GetPosition());
    m_Shaders[e_Shadow]->SetUniform("viewPos", m_camera->position());
    m_Shaders[e_Shadow]->SetUniform("far_plane", m_lights[0]->GetShadow()->GetFar());

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_CUBE_MAP, *m_lights[0]->GetShadow()->GetDepthMap());

    if (m_objectPool.size() > 0) {
        for (Model* m : m_objectPool) {
            m_Shaders[e_Shadow]->Bind();

            texLoc = glGetUniformLocation(*m_Shaders[e_Shadow]->GetProgram(), "diffuseTexture");
            glUniform1i(texLoc, 0);

            texLoc = glGetUniformLocation(*m_Shaders[e_Shadow]->GetProgram(), "depthMap");
            glUniform1i(texLoc, 1);

            m->GetMaterial()->GetDiffuseTexture()->UseTexture(GL_TEXTURE0); //Use diffuse

            m->Render(m_Shaders[e_Shadow]->GetProgram());
        }
    }


    glFlush();
}

And finally here are all 5 shaders used for doing all this

(first pass : vertex, geometry, fragment)

PASS 1 - VERTEX #version 330 core in vec3 position; in vec2 texture; in vec3 normal;

uniform mat4 model;

void main(){ 
    gl_Position = model * vec4(position,1.0);
}

PASS 1 - GEOMETRY

#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices=18) out;

uniform mat4 shadowMatrices[6];

out vec4 FragPos; // FragPos from GS (output per emitvertex)

void main()
{

     //iterate over the 6 cubemap faces
     for(gl_Layer=0; gl_Layer<6; ++gl_Layer) {
        for(int tri_vert=0; tri_vert<3; ++tri_vert) {
            FragPos = gl_in[tri_vert].gl_Position;
            gl_Position = shadowMatrices[gl_Layer] * FragPos;
            EmitVertex();
        }
        EndPrimitive();
     }

}  

PASS 1 : FRAGMENT

#version 330
in vec4 FragPos;

uniform vec4 lightPos;
uniform float far_plane;

out float color;

void main()
{
    // get distance between fragment and light source
    float lightDistance = distance(FragPos,lightPos);

    // map to [0;1] range by dividing by far_plane
    lightDistance = lightDistance / far_plane;

    // Write this as modified depth
    gl_FragDepth = lightDistance;
}  

(second pass: vertex, fragment)

PASS 2 : VERTEX

#version 430 
in vec3 position;
in vec2 texture;
in vec3 normal;



#define MAX_SHADOW_MATRIX 10

out VS_OUT {
    vec4 FragPos;
    vec3 Normal;
    vec2 TexCoords;
} vs_out;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;



void main()
{
    gl_Position = projection * view * model * vec4(position,1.0f);
    vs_out.FragPos = model * vec4(position,1.0f);
    vs_out.Normal = transpose(inverse(mat3(model))) * normal;
    vs_out.TexCoords = texture;
}

PASS 2 : FRAGMENT

#version 430
out vec4 FragColor;

in VS_OUT {
    vec4 FragPos;
    vec3 Normal;
    vec2 TexCoords;
    vec4 FragPosLightSpace;
} fs_in;

uniform sampler2D diffuseTexture;
uniform samplerCube depthMap;

uniform vec4 lightPos;
uniform vec3 viewPos;


void main()
{           
    // Get vector between fragment position and light position
    vec3 fragToLight = fs_in.FragPos.xyz - lightPos.xyz;
    // Use the fragment to light vector to sample from the depth map    
    float closestDepth = texture(depthMap, fragToLight).r;      

    FragColor = vec4(vec3(closestDepth * 255) , 1.0); 

}

To be honest, im pretty sure its about the first pass (cube texture aint filling anything in) but i dont know why.

Here are the main sources i used:

\$\endgroup\$
  • \$\begingroup\$ This seems to be C++ code, so I've tagged it as such. Please correct that tag if it's not accurate (e.g. if it's [c++cli] instead) \$\endgroup\$ – doppelgreener May 22 '17 at 15:45
1
\$\begingroup\$
void main()
{
    // get distance between fragment and light source
    float lightDistance = distance(FragPos,lightPos);

    **// map to [0;1] range by dividing by far_plane
    lightDistance = lightDistance / far_plane;**

    // Write this as modified depth
    gl_FragDepth = lightDistance;
}  

If you map the planes into a linear mapping like this then you can easily get results like this.

Typically you want a mapping that puts the near geometry into a much wider range than the far geometry. Otherwise you can often run into issues like this if the geometry is close to the camera.

This tutorial talks about it.

http://www.learnopengl.com/#!Advanced-OpenGL/Depth-testing

Try implementing this into your shader. I suspect that will clear up your problem.

\$\endgroup\$
  • \$\begingroup\$ Looks right to me \$\endgroup\$ – Arthur P. R. Aug 1 '17 at 17:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.