c++openglframebuffer

glBlitFramebuffer - glReadBuffer and glDrawBuffer refer to the same buffer


Just for learning purposes I test what happens when I call glBlitFramebuffer when glReadBuffer and glDrawBuffer refer to the same buffer. The custom framebuffer is defined this way:

bool initFBO()
{
    glGenFramebuffers(1, &fboId);
    glBindFramebuffer(GL_FRAMEBUFFER, fboId);

    glGenTextures(1, &fboTexId);
    glBindTexture(GL_TEXTURE_2D, fboTexId);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTexId, 0);

    GLuint rboDepth;
    glGenRenderbuffers(1, &rboDepth);
    glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    if (status != GL_FRAMEBUFFER_COMPLETE)
    {
        return false;
    }

    return true;
}

Here is the rendering:

glBindFramebuffer(GL_FRAMEBUFFER, fboId);

render();
//now fboTexId is filled

glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, w, h, 0, 0, w / 2, h / 2, GL_COLOR_BUFFER_BIT, GL_LINEAR);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

//render to the screen
renderTex(fboTexId);

When I render a fbo texture to the screen I get the render function result - glBlitFramebuffer does nothing. I have expected to get the render function result with the second layer two times smaller on the top. I don't know if calling glReadBuffer and glDrawBuffer with the same argument is allowed. Should it work as I expected ?


Solution

  • From OpenGL 4.6 Core Profile Specification - 18.3.1 Blitting Pixel Rectangles

    If the source and destination buffers are identical, and the source and destination rectangles overlap, the result of the blit operation is undefined as described in the introduction to section 18.3.

    In your case, not only are the buffers identical but also overlap.

    If you want to combine different framebuffers into a single one, you usually have a composition (or background) layer that is the only drawing buffer.