我的帧缓冲有什么问题?

时间:2014-03-07 19:04:19

标签: c++ opengl framebuffer

我正在创建一个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:

  • 一个32位RGBA颜色缓冲区(我使用24位但我害怕对齐惩罚),
  • 一个32位RG普通缓冲区(每个组件使用一个16位浮点数,但我可能会使用带符号的短消息?)
  • 一个24位深度缓冲区,内置8位模板缓冲区
  • (总共96位,或12个字节)

我可以看到的问题可能是GL_FLOAT用于普通缓冲区,GL_FLOAT用于深度模板缓冲区。我想GL_HALF_FLOAT更适合法线,但这不在我可以用于glTexImage2D的类型列表中。同样,我不知道哪种类型最适合用于深度模板缓冲区。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

您对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绘制纹理,你真的不关心后面的部分,因为这是它从中获取任何数据的唯一地方。