如何将帧缓冲区对象绘制到默认帧缓冲区

时间:2019-03-10 05:12:32

标签: c opengl sdl-2 framebuffer

该代码应该使用framebuffer对象和渲染缓冲区用黄色清除背景,但我得到的是黑色背景。

#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;
    }

它首先清除具有指定颜色的帧缓冲区对象,然后将其缓冲到默认的帧缓冲区。代码有问题吗?我似乎找不到确切的问题所在。

1 个答案:

答案 0 :(得分:3)

glBlitFramebuffer操作失败,因为读取缓冲区包含无符号整数值,而默认帧缓冲区不包含。这将获得GL_INVALID_OPERATION错误。

读取缓冲区的格式为GL_RGBA32UI

glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA32UI, 500, 500); 

,而绘制缓冲区的格式(默认帧缓冲区)是无符号的规格化整数格式(可能为GL_RGBA8)。

如果您将内部格式更改为GL_RGBA16GL_RGBA32F,则代码将正常工作。

请注意,RGBA8RGBA16之类的格式是规范化的浮点格式,可以存储[0.0,1.0]范围内的浮点值。
但是RGBA16UIRGBA32UI之类的格式是无符号整数格式,可以存储相应范围内的整数值。

规范说,无符号整数值只能复制为无符号整数值。因此,源格式也必须为*UI,目标格式也必须为*UI


请参见OpenGL 4.6 API Compatibility Profile Specification - 18.3.2 Blitting Pixel Rectangles第662页:

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

[...]

     

错误

     

[...]

     

如果不支持格式转换,则会生成INVALID_OPERATION错误,该错误在以下任何一种情况下发生:

     
      
  • 读取缓冲区包含定点或浮点值,并且任何绘制缓冲区都不包含定点或浮点值。
  •   
  • 读取缓冲区包含无符号整数值和任何绘制缓冲区   不包含无符号整数值。
  •   
  • 读取缓冲区包含有符号整数值,任何绘制缓冲区都可以   不包含有符号整数值。
  •