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) )
And here what it should looks like (Not my project, but just for the colors)
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:

