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