Reputation:
I'm currently working on a game project for my school using C++, SFML (for OpenGL context creation, core 3.3), and OpenGL for the rendering part.
Recently, I decided to implement a motion blur. To do this, I need a motion vector for each pixel rendered in my framebuffer object. So in my FBO, i have two texture target :
The color ouput is correctly filled, but the motion vector is always black. I use BuGLe to check the content of my FBO textures.
I know that my issue may come from my texture creation cause I don't understand well all about internal texture format and so on.
Here is my framebuffer creation :
void Framebuffer::create(int sizeX, int sizeY, bool depthBuffer, int repeatMode)
{
_texture = new GLuint[2];
std::memset(_texture, 0, sizeof(GLuint) * 2);
// Create OpenGL framebuffer
glGenFramebuffersEXT(1, &_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _fbo);
// Create texture
glGenTextures(textNbr, _texture);
for (unsigned int i = 0; i < 2; ++i)
{
glBindTexture(GL_TEXTURE_2D, _texture[i]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Color - 4 float components
if (i == 0)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, sizeX, sizeY, 0, GL_RGBA, GL_FLOAT, NULL);
// Motion vector - 2 float components
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, sizeX, sizeY, 0, GL_RG, GL_FLOAT, NULL);
// Even if I use "glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sizeX, sizeY, 0, GL_RGBA, GL_FLOAT, NULL);" for both texture, my motion texture is black
glBindTexture(GL_TEXTURE_2D, 0);
// getColorAttachment only return GL_COLOR_ATTACHMENTi_EXT
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, getColorAttachment(i), GL_TEXTURE_2D, _texture[i], 0);
}
// Generate depth buffer
if (depthBuffer == true)
{
glGenRenderbuffersEXT(1, &_depth);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, sizeX, sizeY);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, _depth);
}
// Check completion
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
ogl::error("Can't complete framebuffer creation");
// Clean
unbind();
}
Framebuffer binding :
void Framebuffer::bind(void)
{
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _fbo);
GLuint *attachment = new GLuint[2];
for (unsigned int i = 0; i < 2; ++i)
attachment[i] = getColorAttachment(i);
glDrawBuffers(2, attachment);
delete[] attachment;
}
Then my Fragment shader which should write into both texture target at the same time :
#version 330
in vec4 Color0;
layout(location = 0) out vec4 FragmentColor;
layout(location = 1) out vec2 MotionVector;
void main(void)
{
FragmentColor = Color0;
MotionVector = vec2(1);
}
Result :
Upvotes: 1
Views: 3585
Reputation: 45362
In the comments, you mentioned that enabling GL_BLEND
causes the issue. That is to be expected. Color values outputted by the fragment shader are always 4-component RGBA vectors, no matter what format your framebuffer will have. The following stages of the GL still work with those 4 comoponents. They might just discard them later when writing to the actual frame buffer. If you just declare them as vec2, the other components are just undefined. The expansion to a vec4 of the form (0,0,0,1) is not applied in that case (that is only done when you read from input attributes or textures, so the quote of the GL documentation you braught up in the comments is irrelevant in that case). So the blending works just with an undefined alpha value, which might as well be always 0 by accident.
However, since you just want to blend your real color buffer, I suggest you use glEnablei()
instead of glEnable()
to just enable blending for the first draw buffer.
Another option would be to use out vec4
and explicitely write 1 to alpha - you still can use a 2 channel framebuffer in that case. Bit the additionall frame buffer read triggered by the unneeded blending for this buffer will still be a performance penalty, so I'd prefer the first option.
Upvotes: 3