I want to render my scene into a cubemap FBO but I can't seem to get it working properly. Only 1 side of my cube is showing the rendered cubemap as a test.
This is my FBO setup:
// create cubemap FBO
unsigned int cubemapFBO;
glGenFramebuffers(1, &cubemapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, cubemapFBO);
// create color cubemap texture
unsigned int colorCubemap;
glGenTextures(1, &colorCubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, colorCubemap);
for (unsigned int i = 0; i < 6; ++i)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_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);
// create depth cubemap
unsigned int depthCubemap;
glGenTextures(1, &depthCubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);
for (unsigned int i = 0; i < 6; ++i)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT24, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_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);
// attach depth texture as FBO's depth buffer
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorCubemap, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0);
//glDrawBuffer(GL_COLOR_ATTACHMENT0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR on cubemapFBO: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// -- End cubemap FBO -- //
This is my projection and view matrices to capture 6 cubemap faces
// set up projection and view matrices for capturing 6 cubemap faces
glm::mat4 captureProjection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f);
glm::mat4 captureViews[] = {
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)),
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
captureProjection * glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f))
};
// -- End projection and view matrices setup -- //
This is my scene rendering to cubemap FBO
// render scene to cubemap FBO
glViewport(0, 0, size, size);
glBindFramebuffer(GL_FRAMEBUFFER, cubemapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
simpleDepthShader.Use();
for (unsigned int i = 0; i < 6; ++i)
{
simpleDepthShader.setMat4("shadowMatrices[" + std::to_string(i) + "]", captureViews[i]);
}
// skybox test
cubemap.Use();
glm::mat4 cubemapModel = glm::translate(glm::mat4(1.0f), positions);
//glm::mat4 cubemapRotate = glm::rotate(glm::mat4(1.0f), glm::radians(-(float)glfwGetTime() * 0.2f), glm::vec3(0.0f, 1.0f, 0.0));
//glm::mat4 cubemapRotate = glm::rotate(glm::mat4(1.0f), glm::radians(-(float)glfwGetTime() * 0.2f), glm::vec3(0.0f, 1.0f, 0.0));
//cubemapModel = cubemapModel * cubemapRotate;
cubemap.setMat4("projection", projection);
cubemap.setMat4("view", skyboxView);
cubemap.setMat4("model", cubemapModel);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, secondCubemapTexture);
renderCubemap();
glDepthFunc(GL_LESS);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// -- End render to cubemap FBO -- //
And this is my vertex + geometry + fragment shader
#shader vertex
#version 450 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
void main()
{
gl_Position = model * vec4(aPos, 1.0);
}
#shader fragment
#version 450 core
out vec4 FragColor;
in vec4 FragPos;
void main()
{
FragColor = FragPos;
}
#shader geometry
#version 450 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()
{
for(int face = 0; face < 6; ++face)
{
gl_Layer = face; // built-in variable that specifies to which face we render.
for(int i = 0; i < 3; ++i) // for each triangle's vertices
{
FragPos = gl_in[i].gl_Position;
gl_Position = shadowMatrices[face] * FragPos;
EmitVertex();
}
EndPrimitive();
}
}
And then testing out the cubemap onto a cube with the fbo cubemap texture
// test cube with FBO cubemap
cube.Use();
cube.setMat4("projection", projection);
cube.setMat4("view", view);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, silverTeapotTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, colorCubemap); // <-- here
glm::mat4 cubeModel = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -0.5f, 0.0f));
cube.setMat4("model", cubeModel);
renderTexturedCube();