Как нарисовать объект фреймбуфера в фреймбуфере по умолчанию

#c #opengl #sdl-2 #framebuffer

#c #opengl #sdl-2 #фреймбуфер

Вопрос:

Предполагается, что этот код очистит фон желтым цветом, используя объект фреймбуфера и буферы рендеринга, но я получаю черный фон.

 #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, amp;fbo);
    glBindFramebuffer( GL_FRAMEBUFFER, fbo);

    GLuint color_rbr;
    glGenRenderbuffers(1, amp;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, amp;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( amp;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:

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, если преобразования формата не поддерживаются, что происходит при любом из следующих условий:

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