Как нарисовать объект фреймбуфера в фреймбуфере по умолчанию - PullRequest
2 голосов
/ 10 марта 2019

Этот код должен очищать фон желтым цветом, используя объект 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 в стандартный кадровый буфер. Что-то не так в коде? Кажется, я не могу понять, где именно проблема.

1 Ответ

3 голосов
/ 10 марта 2019

Операция glBlitFramebuffer завершается неудачно, поскольку буфер чтения содержит целочисленные значения без знака, а кадровый буфер по умолчанию - нет. Это получает ошибку GL_INVALID_OPERATION.

Формат буфера чтения: GL_RGBA32UI

glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA32UI, 500, 500); 

, в то время как формат буфера отрисовки (кадровый буфер по умолчанию) является беззнаковым нормализованным целочисленным форматом (вероятно, GL_RGBA8).

Если вы измените внутренний формат на GL_RGBA16 или GL_RGBA32F, ваш код будет работать правильно.

Обратите внимание, что форматы, такие как RGBA8 и RGBA16, являются нормализованными форматами с плавающей запятой и могут хранить значения с плавающей запятой в диапазоне [0.0, 1.0].
Но форматы, такие как RGBA16UI и RGBA32UI, являются целочисленными форматами без знака и могут хранить целочисленные значения в соответствующем диапазоне.

В спецификации сказано, что целочисленные значения без знака могут быть скопированы только в целочисленные значения без знака. Таким образом, исходный формат должен быть *UI, а целевой формат тоже должен быть *UI.


См. Спецификация профиля совместимости API OpenGL 4.6 - 18.3.2 Прямоугольники бликов пикселей стр. 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 генерируется, если преобразования формата не поддерживаются, что происходит при любом из следующих условий:

  • Буфер чтения содержит значения с фиксированной или плавающей запятой, а любой буфер отрисовки не содержит ни значений с фиксированной, ни с плавающей запятой.
  • Буфер чтения содержит целочисленные значения без знака и любой буфер отрисовки. не содержит целочисленных значений без знака.
  • Буфер чтения содержит целочисленные значения со знаком, и любой буфер рисования не содержит целочисленных значений со знаком.
...