Hi. I want to implement a glow effect for the particular objects on the scene. This is how I do it using 2 framebuffers:
- Render the scene normally.
- Bind framebuffer 1 and render the objects which must be “glowed” with the simple shader on the black background with the color of the glow light.
- Bind framebuffer 2 and apply horizontal Gaussian filter using framebuffer 1 as the input texture.
- Bind framebuffer 1 and apply vertical Gaussian filter using framebuffer 2 as the input texture.
- Use additive blending to draw texture from framebuffer 1 over the main buffer with the rendered scene.
Also I must use the depth buffer from the main buffer to allow step 2 to be executed correctly (to draw only that parts of the glowing objects that are not overlapped by non-glowind objects)
This is how my FBO are initialized:
glGenFramebuffers (2, fbo);
glGenTextures (2, textures);
glGenRenderbuffers (1, &depthBuffer);
// Renderbuffer stores the depth buffer
glBindRenderbuffer (GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
// Attach textures to the framebuffers
for (int i = 0; i < 2; i++)
{
glBindFramebuffer (GL_FRAMEBUFFER, fbo[i]);
glBindTexture (GL_TEXTURE_2D, textures[i]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_FLOAT, NULL);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[i], 0);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
}
I attach renderbuffer with the depth values to both FBO but it used only once at step 2.
This is how I do the step 2:
fboHandler->activate ();
void FboHandler::activate ()
{
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, textures[0]);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, textures[1]);
glActiveTexture (GL_TEXTURE0);
glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, fbo[0]);
glBlitFramebuffer (0, 0, width, height, 0, 0, width, height,
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer (GL_FRAMEBUFFER, fbo[0]);
glClear (GL_COLOR_BUFFER_BIT);
}
// Paint the objects with the glow color
// ...
fboHandler->deactivate ();
glDisable (GL_DEPTH_TEST);
void FboHandler::deactivate ()
{
glBindFramebuffer (GL_FRAMEBUFFER, 0);
}
So to use the main depth buffer in my FBO I copy it using glBlitFramebuffer.
I create my FBO with the same size as the size of the main buffer because glBlitFramebuffer allows to copy unequal sized buffers only for color component but not depth.
Also glGetError returns 0 for glBlitFramebuffers.
As there is no need for depth buffer in the blur shader (Gaussian filter) in steps 3, 4, 5, I disable it.
As for now, the framebuffer’s 1 texture must contain the one-colored image of all object that must be glowed. And if that objects are behind other objects, they shouldn’t be in that texture because the I copied the main depth buffer to my FBO.
Then I do steps 3, 4 and 5.
// Apply the filters
// ...
// Draw the final glow texture
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
glDrawArrays (GL_QUADS, 0, 12);
glDisable (GL_BLEND);
And the glow is painted incorrect, sometimes in front of objects which are in front of the glowed objects, sometimes it disappears, sometimes it flickers.
And it is also low quality (with thin stripes) comparing to the glow effect rendered while using low-resolution FBO. But I can’t use low-resolution FBO because than I won’t be able to use glBlitFramebuffer.
So where is my mistake? How can I use depth information from the main buffer to draw the necessary objects correctly to the framebuffer?
Great thanks in advance.