I am currently working on an assignment that requires us to generate a cube map that will be used for environment mapping (without using any built-in OpenGL cube mapping functionality). Currently only the last image rendered is valid. The rest are entirely black, regardless of the clear color I have set.
It appears as though detaching a texture from an FBO is invalidating it (clearing it to black). If I draw to one texture, then detach the texture from the fbo by calling glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0)
, the texture I just wrote to is black.
bind FBO
for each viewpoint to be rendered (+- each axis, 6 total)
calculate transformation matrices needed for viewpoint
attach next texture to FBO at GL_COLOR_ATTACHMENT0
clear color and depth
render scene
unbind FBO
Is this a reasonable method for rendering the same scene to multiple textures, or should I use multiple FBOs? What is the recommended method of doing this (again, avoiding OpenGL cube map functionality)?
Initializing FBO
// Setup FBO
glGenFramebuffers(1, &_env_map_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, _env_map_fbo);
// Setup depth buffer
glGenTextures(1, &_env_map_depth);
glBindTexture(GL_TEXTURE_2D, _env_map_depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 512, 512, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0); // unbind depth texture
// Attach depth buffer to FBO
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _env_map_depth, 0);
// Configure FBO
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_NONE);
glViewport(0, 0, 512, 512);
// Verify framebuffer is complete
GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);(void)fb_status;
pcerror_if(fb_status != GL_FRAMEBUFFER_COMPLETE, "Error setting up FBO!");
Initializing Textures
glGenTextures(6, _tex_ids);
for(uint i = 0; i < 6; ++i)
{
glBindTexture(GL_TEXTURE_2D, _tex_ids[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
}
glBindTexture(GL_TEXTURE_2D, 0);
Inside Render Loop
// Bind frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, _env_map_fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
// Calculate transformation matrices for viewpoint 1
// ...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _tex_ids[0], 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_graphics.render(); // Render entire scene using the same code I normally use.
// Calculate transformation matrices for viewpoint 2
// ...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _tex_ids[1], 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_graphics.render();
// Etc. for each viewpoint
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
// Draw scene as normal
Some more information in-case it is useful:
It appears as though my method does work. I was putting a little too much faith in gDEBugger. Drawing the textures to the HUD I see the output I expect.
My results gDEBugger