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\$
1
  • \$\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\$ May 22, 2017 at 15:45

1 Answer 1

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\$
1
  • \$\begingroup\$ Looks right to me \$\endgroup\$ Aug 1, 2017 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .