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\$ Commented 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\$ Commented Aug 1, 2017 at 17:24

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.