I am attempting to create omnidirectional point lights that cast shadows using a depth cube map. However, when sampling the cube map, I seem to get a value of 1 in every case (making everything look black).
Here is how I generate the depth cube map and associated FBO:
glGenTextures(1, &m_cubeMapID);
// Bind as cube map and set default settings
glBindTexture(GL_TEXTURE_CUBE_MAP, m_cubeMapID);
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);
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_MIN_FILTER, GL_NEAREST );
//glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
//glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
// Generate textures for faces
for(int f = 0; f < 6; f++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, 0, GL_DEPTH_COMPONENT, m_resolution, m_resolution, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
// Generate mipmaps for the color texture
//glGenerateMipmap(GL_TEXTURE_2D);
GL_ERROR_CHECK();
// ------------------------------ FBO ------------------------------
glGenFramebuffers(1, &m_fboID);
glBindFramebuffer(GL_FRAMEBUFFER, m_fboID);
// Not using color buffer
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// Attach at least on part of cube map so completeness check succeeds. Attach and detach sides later when rendering
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapID, 0);
GL_ERROR_CHECK();
#ifdef DEBUG
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cerr << "Could not created FBO!" << std::endl;
#endif
// Unbind FBO, revert to main framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Unbind texture
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
GL_ERROR_CHECK();
I then render to it like this:
// For each face, render the scene
glBindFramebuffer(GL_FRAMEBUFFER, m_fboID);
// Set up viewport for the map side
glViewport(0, 0, m_resolution, m_resolution);
// Set projection to 90 degrees
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0f, 1.0f, 0.01f, distance);
glMatrixMode(GL_MODELVIEW);
glColorMask(false, false, false, false);
// Side +X
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x + 1.0f, position.y, position.z, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
// Side -X
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x - 1.0f, position.y, position.z, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
// Side +Y
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x, position.y + 1.0f, position.z, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
// Side -Y
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x, position.y - 1.0f, position.z, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
// Side +Z
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x, position.y, position.z + 1.0f, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
// Side -Z
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, m_cubeMapID, 0);
glClear(GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position.x, position.y, position.z, position.x, position.y, position.z - 1.0f, 0.0f, 1.0f, 0.0f);
pScene->ExtractFrustum();
pScene->Render(distance);
glColorMask(true, true, true, true);
glFlush();
// Unbind the FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
GL_ERROR_CHECK();
Rendering to the cube map worked when using color textures, but I am not sure that it is rendering properly when using the textures as depth attachments.
Here is the shader I use for rendering the shadows:
Vertex:
uniform vec3 light_position;
// Used for shadow lookup
varying vec4 shadowDir;
void main()
{
shadowDir = gl_Vertex * gl_ModelViewMatrix - vec4(light_position, 1.0);
gl_Position = ftransform();
gl_FrontColor = gl_Color;
}
Fragment:
uniform samplerCube shadowMap;
varying vec4 shadowDir;
void main()
{
float frag_depth = length(shadowDir.xyz);
vec3 norm_shadowDir = normalize(shadowDir).xyz;
float shadow_map_depth = textureCube(shadowMap, norm_shadowDir).r;
float light = 0.0;
if(shadow_map_depth > frag_depth + 0.0005)
light = 1.0;
gl_FragColor = gl_Color;
gl_FragColor.rgb *= light;
}
What am I doing wrong here? Thanks for any help you can offer!