Tristan
Tristan

Reputation: 47

How to draw a framebuffer object to the default framebuffer

This code is supposed to clear the background with yellow color using framebuffer object and render buffers but what I get is black background.

#include <SDL2/SDL.h>
#include <GL/glew.h>

int main( int argc, char** argv)
    {
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1);

    SDL_Window* gWindow= SDL_CreateWindow( "Title",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        500, 500, SDL_WINDOW_OPENGL);
    SDL_GLContext gContext= SDL_GL_CreateContext( gWindow);

    glewExperimental= GL_TRUE;
    glewInit();

    GLuint fbo;
    glGenFramebuffers( 1, &fbo);
    glBindFramebuffer( GL_FRAMEBUFFER, fbo);

    GLuint color_rbr;
    glGenRenderbuffers(1, &color_rbr);
    glBindRenderbuffer( GL_RENDERBUFFER, color_rbr);
    glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA32UI, 500, 500);
    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_rbr);

    GLuint depth_rbr;
    glGenRenderbuffers( 1, &depth_rbr);
    glBindRenderbuffer( GL_RENDERBUFFER, depth_rbr);
    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 500, 500);
    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rbr);

    if( glCheckFramebufferStatus( GL_DRAW_FRAMEBUFFER)!= GL_FRAMEBUFFER_COMPLETE)
        return 1;
    if( glCheckFramebufferStatus( GL_READ_FRAMEBUFFER)!= GL_FRAMEBUFFER_COMPLETE)
        return 2;

    glViewport( 0, 0, 500, 500);
    glClearColor( 1, 1, 0, 0);
    SDL_GL_SetSwapInterval( 1);

    int quit= 0;
    SDL_Event event;
    glReadBuffer( GL_COLOR_ATTACHMENT0);

    while( !quit)
        {
        while( SDL_PollEvent( &event))
            if( event.type== SDL_QUIT)
                quit= 1;

        glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fbo);
        glDrawBuffer( GL_COLOR_ATTACHMENT0);
        glClear( GL_COLOR_BUFFER_BIT);
        glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0);
        glDrawBuffer( GL_BACK);
        glBlitFramebuffer(
            0, 0, 500, 500,
            0, 0, 500, 500,
            GL_COLOR_BUFFER_BIT, GL_NEAREST);
        SDL_GL_SwapWindow( gWindow);
        }
    SDL_DestroyWindow( gWindow);
    return 0;
    }

It first clears the framebuffer object with the specified color then blits the framebuffer object to the default framebuffer. Is there something wrong in the code? I can't seem to find where exactly the problem is.

Upvotes: 2

Views: 1980

Answers (1)

Rabbid76
Rabbid76

Reputation: 210880

The glBlitFramebuffer operation fails, because the read buffer contains unsigned integer values and the default framebuffer doesn't. This gains a GL_INVALID_OPERATION error.

The format of the read buffer is GL_RGBA32UI

glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA32UI, 500, 500); 

while the format of the draw buffer (default framebuffer) is an unsigned normalized integer format (probably GL_RGBA8).

If you change the internal format to GL_RGBA16 or GL_RGBA32F your code will proper work.

Note, formats like RGBA8 and RGBA16 are normalized floating point formats and can store floating point values in range [0.0, 1.0].
But formats like RGBA16UI and RGBA32UI are unsigned integral formats and can store integer values in the corresponding range.

The specification says that unsigned integer values can only be copied to unsigned integer values. So the source format has to be *UI and the target format has to be *UI, too.


See OpenGL 4.6 API Compatibility Profile Specification - 18.3.2 Blitting Pixel Rectangles page 662:

void BlitFramebuffer( int srcX0, int srcY0, int srcX1, int srcY1, 
    int dstX0, int dstY0, int dstX1, int dstY1, bitfield mask, enum filter );

[...]

Errors

[...]

An INVALID_OPERATION error is generated if format conversions are not supported, which occurs under any of the following conditions:

  • The read buffer contains fixed-point or floating-point values and any draw buffer contains neither fixed-point nor floating-point values.
  • The read buffer contains unsigned integer values and any draw buffer does not contain unsigned integer values.
  • The read buffer contains signed integer values and any draw buffer does not contain signed integer values.

Upvotes: 4

Related Questions