Я создаю объект framebuffer, который будет моим gbuffer для отложенного затенения. Я в основном учился у http://ogldev.atspace.co.uk/, и модифицированный, чтобы быть немного более … вменяемым. Вот исходный код, где я создаю фреймбуфер:
/* Create the FBO */
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
/* Create the gbuffer textures */
glGenTextures(GBUFFER_NUM_TEXTURES, tex);
/* Create the color buffer */
glBindTexture(GL_TEXTURE_2D, tex[GBUFFER_COLOR]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[GBUFFER_COLOR], 0);
/* Create the normal buffer */
glBindTexture(GL_TEXTURE_2D, tex[GBUFFER_NORMAL]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, width, height, 0, GL_RG, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, tex[GBUFFER_NORMAL], 0);
/* Create the depth-stencil buffer */
glBindTexture(GL_TEXTURE_2D, tex[GBUFFER_DEPTH_STENCIL]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex[GBUFFER_DEPTH_STENCIL], 0);
GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, drawBuffers);
glReadBuffer(GL_NONE);
/* Check for errors */
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
error("In GBuffer::init():\n");
errormore("Failed to create Framebuffer, status: 0x%x\n", status);
fbo = 0;
return;
}
// restore default FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Когда я запускаю это, однако, статус возвращается GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
, Если не понятно, я пытаюсь создать 3 gbuffers:
Возможные проблемные области, которые я вижу, могут использовать GL_FLOAT для обычного буфера и GL_FLOAT для буфера глубины трафарета. Я полагаю, что GL_HALF_FLOAT будет более подходящим для нормалей, но этого нет в списке типов, которые я могу использовать с glTexImage2D. Точно так же я понятия не имею, какой тип наиболее подходит для буфера глубины трафарета.
Что я делаю неправильно?
Ваше использование GL_FLOAT
является в основном не имеет значения, так как передача пикселя на самом деле не происходит.
Вы можете указать там все, что захотите, если это значимый тип данных. Хотя при передаче не происходит передача пикселей NULL
для данных GL все еще проверяет тип данных передачи пикселей по набору допустимых типов и выдает ошибку, если вы делаете что-то не так. С этой целью, если возникнет ошибка, текстура будет неполной и, следовательно, не может быть использована в качестве вложения FBO.
Вот в чем проблема, GL_FLOAT
не является значимым типом данных для переноса пикселей в упакованный GL_DEPTH_STENCIL
формат изображения … он ожидает упакованный тип данных, такой как GL_UNSIGED_INT_24_8
или что-то действительно экзотическое, как GL_FLOAT_32_UNSIGNED_INT_24_8_REV
(64-битный формат с плавающей запятой + формат трафарета).
В любом случае, на самом деле есть два компонента, которые должны быть упакованы в ваш тип данных. GL_FLOAT
можно описать только один из двух компонентов, потому что буферы с плавающей точкой трафарета не имеют смысла.
Кстати, всего этого запутанного беспорядка о типе данных передачи пикселей можно полностью избежать, если вы используете что-то вроде glTexStorage2D (...)
в только выделить память для текстуры. glTexImage2D (...)
выполняет двойную функцию, выделяя хранилище для текстуры LOD и предоставляя механизм для его инициализации данными. Вы действительно не заботитесь о более поздней части, если вы рисуете в текстуру с FBO, так как это единственное место, откуда она получает какие-либо данные.
Других решений пока нет …