c++ - 我的帧缓冲区有什么问题?

标签 c++ opengl 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 位 float ,但我可能会用一个带符号的 short?)
  • 一个包含 8 位模板缓冲区的 24 位深度缓冲区
  • (总共 96 位,或 12 个字节)

我能看到的可能的问题区域可能是对普通缓冲区使用 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 绘制到纹理中,您真的不关心后面的部分,因为这是它从中获取任何数据的唯一地方。

关于c++ - 我的帧缓冲区有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22258567/

相关文章:

Android OpenGL ES 2.0 重用前一帧

Android读取fb0总是给我黑屏

c++ - 如何获取 RapidJSON 模式来处理默认属性

c++ - C++ 11 触发异步任务并忘记它的方法是什么?

c - OpenGL 中矩阵堆栈的意义何在?

c++ - 现代 OpenGL 3.3 核心黑色纹理

iphone - OpenGL ES 2.0 FBO 创建出错并出现未知错误

c++ - 我可以在编译和链接时将 C++ 主函数和类与 Objective-C 和/或 C 例程分开吗?

c++ - 为什么在将 C 样式数组传递给需要 std::string 的方法时出现链接器问题?

opengl - 为什么retina屏幕坐标值是像素值的两倍