OpenGL 片段着色器未写入 fbo 颜色缓冲区

Posted

技术标签:

【中文标题】OpenGL 片段着色器未写入 fbo 颜色缓冲区【英文标题】:OpenGL fragment shader not writing to fbo color buffer 【发布时间】:2012-05-14 19:54:10 【问题描述】:

我在从片段着色器写入 FBO 中的颜色缓冲区时遇到问题。这个想法是绘制到这个纹理,然后把这个纹理绘制成一个四边形。 问题是,着色器在绘制到默认窗口缓冲区时起作用,因为如果我删除 FBO,则会显示场景。并且四边形的纹理也有效,我用导入的纹理尝试了它,它显示了。我得到的只是黑屏。可能出了什么问题? :(

创建 FBO 的代码:

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

glGenRenderbuffers(1, &depthbuff); //Add a depth renderbuffer for depth testing
glBindRenderbuffer(GL_RENDERBUFFER, depthbuff);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuff);

//Add the buffer to be drawn to and the buffer for the picking information
glGenTextures(1, &drawbuff);
glBindTexture(GL_TEXTURE_2D, drawbuff);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawbuff, 0);

glGenTextures(1, &pickingbuff);
glBindTexture(GL_TEXTURE_2D, pickingbuff);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, pickingbuff, 0);

渲染代码:

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLenum buffers[] =  GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 ;
glDrawBuffers(2, buffers);

shader->bind(); //If the three lines above are removed, it draws correctly to the window
drawStuff();

四边形代码:

quadshader->bind();
glEnable(GL_TEXTURE_2D);
int drawTexID = quadshader->uniformLocation("drawTex");

glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, anotherTexture); //This works. A texture imported from a TGA
glBindTexture(GL_TEXTURE_2D, drawbuff);
glUniform1i(drawTexID, 0);

drawQuad();

最后,碎片着色器,我只是将它设置为将所有内容绘制为纯色:

void main(void) 
    gl_FragData[0] = vec4(1.0, 1.0, 0.0, 1.0);
    gl_FragData[1] = vec4(0.0, 1.0, 1.0, 1.0);

编辑:如果有任何帮助,整个事情都在 Qt GLWidget 中。

【问题讨论】:

我发现明显缺少帧缓冲区清除代码。 什么意思?顺便说一句,FBO 返回完成。 致电glClearglClearBuffer。在使用它之前清除帧缓冲区。你在哪里做的? 在 drawStuff 函数的开始,我有 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);我没有glClearBuffer,它有什么作用? 事实证明 Nicol 是对的:虽然我确实清除了写入纹理的缓冲区,但我忘记在从纹理绘制之前清除默认缓冲区,这就是它没有刷新的原因。再次感谢。 【参考方案1】:

您是否注意确保您的纹理不会同时绑定到采样器 (glBindTexture) 和帧缓冲区?如果您尝试在纹理绑定到活动采样器时写入纹理,或者如果您尝试在纹理附加到活动帧缓冲区时对其进行采样,我认为该行为是错误或未定义。

【讨论】:

我在初始化时使用glBindTexture 将纹理绑定到FBO,就像上面的第一个代码框一样。我如何解绑它们?在初始化结束时,帧缓冲区未绑定,然后再次绑定以进行渲染,就像在第二个代码框中一样,FBO 在最后是未绑定的。然后再次绑定纹理,用于渲染到四边形。您认为这会导致问题吗? glBindTexture 不会将纹理绑定到 FBO,而是将其绑定到采样器。如果您在传递过程中没有主动对纹理进行采样,则应通过glBindTexture(GL_TEXTURE_2D,0); 或通过绑定不同的纹理将其从采样器中移除。此处的关键步骤是确保在写入帧缓冲区时,您的帧缓冲区绑定纹理都不会附加到采样器。 对不起,我刚试过,我在绑定帧缓冲区进行渲染之后(以及在渲染调用之前)添加了glBindTexture(GL_TEXTURE_2D,0);,但我仍然得到一个黑色方块。 @rabipelais 嗯,很抱歉当时不确定。如果您没有 gdebugger,您可能需要下载它,它可以查看内存中的 FBO,您可以查看是否有任何东西被实际绘制。 谢谢,我没听说过,我会尝试在这里发布任何消息:)

以上是关于OpenGL 片段着色器未写入 fbo 颜色缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL FBO 与 MRT 写入后台缓冲区

在 GLSL 中检索 FBO 数据

OpenGL 帧缓冲区颜色附件到计算着色器

Xcode 7 / iOS 9:在 SKNode 中使用 OpenGL 片段着色器未编译

OpenGL FBO 多个纹理

OpenGL:使用多个纹理渲染到 FBO