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

问题描述 投票:2回答:1

这段代码应该使用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;
    }

它首先使用指定的颜色清除framebuffer对象,然后将framebuffer对象blit到默认的帧缓冲区。代码中有什么问题吗?我似乎无法找到问题的确切位置。

c opengl sdl-2 framebuffer
1个回答
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错误,该错误在以下任何条件下发生:

  • 读缓冲区包含定点或浮点值,任何绘制缓冲区都不包含定点或浮点值。
  • 读缓冲区包含无符号整数值,任何绘制缓冲区都不包含无符号整数值。
  • 读缓冲区包含有符号整数值,任何绘制缓冲区都不包含有符号整数值。
© www.soinside.com 2019 - 2024. All rights reserved.