The setup
I have a working bloom shader implemented which creates a fbo with two textures attached to it.
- The first texture holds the entire scene
- The other only displays objects which are supposed to be bloomed in a postprocessing (ping pong) step
At the and the end both textures are added.
Here is the code which creates the according fbo:
void CreateHdrBloomFBO(GLuint &hdr_fbo, GLuint *color_buffers, GLuint *pingpong_fbo, GLuint *pingpong_color_buffers, GLuint &rbo_depth, float width, float height)
{
glGenFramebuffers(1, &hdr_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, hdr_fbo);
glGenTextures(2, color_buffers);
for (unsigned int i = 0; i < 2; i++)
{
glBindTexture(GL_TEXTURE_2D, color_buffers[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, color_buffers[i], 0);
}
glGenRenderbuffers(1, &rbo_depth);
glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_depth);
GLuint attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating HDR/BLOOM buffers." << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glGenFramebuffers(2, pingpong_fbo);
glGenTextures(2, pingpong_color_buffers);
for (unsigned int i = 0; i < 2; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[i]);
glBindTexture(GL_TEXTURE_2D, pingpong_color_buffers[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pingpong_color_buffers[i], 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating HDR/BLOOM-pingpong buffers." << std::endl;
}
}
So my renderloop looks something like this.
// 1. Bind fbo
// 2. Render scene
// 3. Blur cube and earth fragments with two-pass Gaussian Blur
bool horizontal = true, first_iteration = true;
unsigned int amount = 10;
blur_shader.use();
for (unsigned int i = 0; i < amount; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, pingpong_fbo[horizontal]);
blur_shader.set_int("horizontal", horizontal);
// Note on the first iteration I take the second texture from above, which holds the objects which are supposed to get bloomed.
glBindTexture(GL_TEXTURE_2D, first_iteration ? color_buffers[1] : pingpong_color_buffers[!horizontal]);
core::RenderQuad(&quad_geometry);
horizontal = !horizontal;
if (first_iteration)
first_iteration = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 4. Combine normal and bloom textures
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bloom_final_shader.use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color_buffers[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pingpong_color_buffers[!horizontal]);
bloom_final_shader.set_int("bloom", use_bloom);
bloom_final_shader.set_float("exposure", exposure);
core::RenderQuad(&quad_geometry);
This is what the output of the scene render looks like. The are the scene and the blooming targets:
In the first blooming step the correct image is passed and "ping ponged" afterwards.
The final image:
The problem
I want to implement antialiasing on top of the given process. Therfore I create a multisample fbo which also holds two textures:
void CreateMsaaFBO(GLuint &target_fbo, GLuint *target_fbo_textures, GLuint &rbo_depth_stencil, float width, float height)
{
glGenFramebuffers(1, &target_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, target_fbo);
glGenTextures(2, target_fbo_textures);
for (unsigned int i = 0; i < 2; i++)
{
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, target_fbo_textures[i]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, width, height, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D_MULTISAMPLE,target_fbo_textures[i], 0);
}
glGenRenderbuffers(1, &rbo_depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth_stencil);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,rbo_depth_stencil);
GLuint attachments[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, attachments);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "CORE::CREATE_FRAMEBUFFER_FAIL - Failed creating MSAA buffer." << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER_COMPLETE, 0);
}
So my Plan is to draw the scene as above this time using my msaa_fbo and use glBlitFramebuffer
to copy antialiased textures to my original fbo:
// 1. Bind msaa_fbo
// 2. Render scene
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaa_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdr_fbo);
glBlitFramebuffer(0, 0, viewport_width, viewport_height, 0, 0, viewport_width, viewport_height,GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 3. blur bright fragments with two-pass Gaussian Blur as above
// ...
It seems that only the first texture gets copied to the hdr_fbo
and therfore the entire image is bloomed.
The output of the msaa_fbo
looks correct:
This is the glBindFramebuffer
in renderdoc which seems to target only one texture (the scene):
That is why the input of the pingpong loop is the entire scene:
As far as I get it should copy both textures (scene + bloom) to my target hdr_fbo
buffer. Why doesn't it? I started learning those concept, so I am not ruling out that I am missing something fundamental.
Also note that a lot of the code is taken from learnopengl.com.