I’m trying to render the scene to a depth attachment of a specific framebuffer. I’ve been fiddling around with this for a long time, trying lots of different things.
No matter what I try, all of my draw calls for this framebuffer write no fragments.
(Note that I am drawing to both a G-Buffer and directly to the default framebuffer in other parts of the program and have no such problems at all)
Nsight framecapture shows that, for every single one of these draw calls, no fragments are written.
Note that these fragments aren’t failing depth/stencil tests (as Nsight would say so if they were).
(My best guess is that they’re all falling outside of the view frustum?)
However, it gets weirder.
If I use a completely uninitialised shader program during the rendering process, fragments are drawn! Naturally, these don’t have the correct matrix projections etc applied to them. However, this was a shock to me nonetheless.
(My guess was that OpenGL is falling back to a previously attached shader program and using that. However, if I explicitly use any of these previous shader programs for drawing to this framebuffer, I don’t get the same results, and still no fragments are written.)
In any case, I just really want my own shaders to correctly write fragments to the depth-buffer cubemap.
========
This is all in order to implement point-light shadow-mapping into a project of mine.
To do this, I’m using a cubemap (depth_component) texture.
glGenTextures(1, &Shadow_Cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, Shadow_Cubemap);
for (size_t W = 0; W < 6; W++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + W, 0u, GL_DEPTH_COMPONENT32F,
Shadow_Mapper::Shadow_Map_Width, Shadow_Mapper::Shadow_Map_Height, 0u,
GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, Shadow_Cubemap, 0u); // This is likely redundant as I later use the glFramebufferTexture2D() function to attach specific faces to the framebuffer. Note that removing or modifying this line yielded no fix
For all 6 faces, I use a different side of this cubemap texture for the depth attachment and render the scene using the appropriate faces’ projection/view matrix.
void Render_All_Shadows()
{
Bind_Shadow_Frame_Buffer(); // See below for elaboration
Shadow_Object_Shader.Activate(); // This function just uses the shader program
for (size_t Face = 0; Face < 6; Face++)
{
glUniformMatrix4fv(glGetUniformLocation(Shadow_Object_Shader.Program_ID, "Shadow_Matrix"), 1, GL_FALSE, &View_Matrices[Face][0][0]); // This gives the desired view/projection matrix to the shader
glBindTexture(GL_TEXTURE_CUBE_MAP, Shadow_Cubemap);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + Face, Shadow_Cubemap, 0u); // This sets the desired face of the cubemap to be the framebuffer's depth attachment.
glClear(GL_DEPTH_BUFFER_BIT); // For shadow mapping, we only care about the depth buffer. This call just clears the depth buffer of the currently selected face
for (size_t W = 0; W < Scene_Models.size(); W++)
Render_Object_To_Shadow_Map(Scene_Models[W]); // This function just binds vertex/uniform buffers and then makes the draw call. Nothing crazy
}
Unbind_Shadow_Frame_Buffer(); // See below for elaboration
}
The shader, framebuffer, and view/projection matrices are initialised earlier in the program, and the bind/unbind shadow framebuffer functions are straight forward
// (Initialisation function)
glGenFramebuffers(1, &Shadow_Frame_Buffer);
glBindFramebuffer(GL_FRAMEBUFFER, Shadow_Frame_Buffer);
Shadow_Object_Shader.Create_Shader("Shader_Code/Shadow_Test_2.vert", "Shader_Code/Shadow_Test_2.frag", nullptr); // This is the line that I commented out to make sure the shader isn't initialised. With this line here, no fragments are written. However, when this line is removed, the fragments are written (albeit incorrectly).
Shadow_Projection_Matrix = glm::perspective(glm::radians(90.0f), 1.0f, 0.01f, 25.0f);
// Later in the program, I initialise the view-matrices like so:
View_Matrices[0] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3( 1.f, 0.f, 0.f), glm::vec3( 0.f,-1.f, 0.f));
View_Matrices[1] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3(-1.f, 0.f, 0.f), glm::vec3( 0.f,-1.f, 0.f));
View_Matrices[2] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3( 0.f, 1.f, 0.f), glm::vec3( 0.f, 0.f, 1.f));
View_Matrices[3] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3( 0.f,-1.f, 0.f), glm::vec3( 0.f, 0.f,-1.f));
View_Matrices[4] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3( 0.f, 0.f, 1.f), glm::vec3( 0.f,-1.f, 0.f));
View_Matrices[5] = Shadow_Mapper::Shadow_Projection_Matrix * glm::lookAt(Position, Position + glm::vec3( 0.f, 0.f,-1.f), glm::vec3( 0.f,-1.f, 0.f));
// Note that "Position" is just the position of the point-light. In both the debugger and in Nsight, these matrices seem to be okay
// However, there may be problems with it that I don't see
// And here are the bind/unbind shadow framebuffer functions:
void Bind_Shadow_Frame_Buffer()
{
glViewport(0, 0, Shadow_Map_Width, Shadow_Map_Height);
glBindFramebuffer(GL_FRAMEBUFFER, Shadow_Frame_Buffer);
glDisable(GL_CULL_FACE); // This is just to ensure that the lack of fragments isn't due to back-face culling
}
void Unbind_Shadow_Frame_Buffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0u);
glViewport(0, 0, Window_Width, Window_Height);
glEnable(GL_CULL_FACE); // Returns to normal after rendering to shadow-map
}
Because I feel it necessary, despite the shader programs being so basic, here are the fragment/vertex shaders for rendering to this framebuffer:
#version 440
layout(location = 0) in vec3 In_Position;
layout(location = 1) in vec3 In_Normal;
layout(location = 2) in vec2 In_UV;
uniform mat4 Model_Matrix;
uniform mat4 Shadow_Matrix;
void main()
{
// gl_Position = vec4(In_Position, 0.0f); //
gl_Position = Shadow_Matrix * Model_Matrix * vec4(In_Position, 0.0f);
}
#version 440
void main()
{
// gl_FragColor = vec4(0, 0, 0, 0);
// gl_FragDepth = gl_FragCoord.z;
}
// Note that I've tried with/without explicit writes to gl_FragDepth and I've experimented with writing values like 0.0f straight to gl_FragDepth among other things.
// I've also tried creating and attaching a colour buffer to see if I could write to that with this shader but, as previously, no fragments were written.
This issue has been plaguing me for a long time now, and I’m dying for some answers.
If anyone has any idea how I can get my shaders working and drawing to this framebuffer properly, I’d be open to hear them, and I’m more than happy to answer any questions you have.
Many, many, many thanks in advance!