user2997707
user2997707

Reputation:

OpenGL Multiple Render Target - Black output

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 :

Color texture

Motion texture

Upvotes: 1

Views: 3585

Answers (1)

derhass
derhass

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

Related Questions