我有2个FBO + MRT,它们具有相同的附件(每个附件4个颜色)。使用glBlitFrameBuffer对于深度缓冲区和一种 color_attachment可以按预期工作。但是,当我打开多个颜色附件时,情况就会变糟。我做了很多研究,尝试了很多不同的方法,但都没有效果。我没有使用renderBufferStorage,因为我的纹理具有不同的内部格式(RGBA和RGB16F)。 This听起来像是一个类似的问题,除了我不使用多重采样,仅使用MRT。

OpenGL版本4.3

原因:我想创建一个地形预光照计算状态,以便仅在发生变化(即摄像机移动)时才渲染地形,然后将这些颜色附件复制到下一个FBO。这是用于延迟着色,FBO与gBuffer非常相似。

起初,我期望我应该使用在初始设置中使用的glDrawBuffers,但是没有glReadBuffers,因此我假设我没有办法链接它们。我在这里可能是错的,还不是专家=)

原始代码是用Golang编写的,应该可以轻松地转移到C++(如果需要,可以翻译)。

更新/已解决:适用于绊脚石的任何人。当您使用glDrawBuffers()并调用glDrawBuffer()时,您将覆盖glDrawBuffers()状态。需要将其重置为其原始的glDrawBuffers()状态。

Update2:对于那些对这种方法感兴趣的人,如果您拥有非动画世界并且相机不经常移动,我可以确认它具有令人难以置信的性能结果。对我来说,它很棒(RTS),但对于CS这样的FPS游戏,这是非常的错误做法。

划线后添加以下内容(视情况而定):

var attachments = [4]uint32{gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3}
gl.DrawBuffers(4, &attachments[0])

FBO设置
gl.GenFramebuffers(1, &fbo.ID)
gl.BindFramebuffer(gl.FRAMEBUFFER, fbo.ID)

//setting up color attachments

gl.GenTextures(1, &fbo.Position)
gl.BindTexture(gl.TEXTURE_2D, fbo.Position)
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB16F, windowWidth, windowHeight, 0, gl.RGB, gl.FLOAT, nil)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbo.Position, 0)

//repeated 3 times for the additional color attachments

var attachments = [4]uint32{gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3}
gl.DrawBuffers(4, &attachments[0])

gl.GenRenderbuffers(1, &fbo.DepthBuffer)
gl.BindRenderbuffer(gl.RENDERBUFFER, fbo.DepthBuffer)
gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT, windowWidth, windowHeight)
gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fbo.DepthBuffer)

gl.BindFramebuffer(gl.FRAMEBUFFER, 0)

现在到污点部分。
gl.BindFramebuffer(gl.READ_FRAMEBUFFER, fboIn.ID)
gl.BindFramebuffer(gl.DRAW_FRAMEBUFFER, fboOut.ID)

//works as expected
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.DEPTH_BUFFER_BIT, gl.NEAREST)

//works as expected
gl.ReadBuffer(gl.COLOR_ATTACHMENT0)
gl.DrawBuffer(gl.COLOR_ATTACHMENT0)
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.COLOR_BUFFER_BIT, gl.LINEAR)

//fails - no errors but produces some weird occurrences.
gl.ReadBuffer(gl.COLOR_ATTACHMENT1)
gl.DrawBuffer(gl.COLOR_ATTACHMENT1)
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.COLOR_BUFFER_BIT, gl.LINEAR)

gl.BindFramebuffer(gl.FRAMEBUFFER, 0)

最佳答案

glDrawBuffer(x)在概念上等效于调用GLenum bufs[1]={x}; glDrawBuffers(1, bufs)。由于绘制缓冲区状态是FBO状态的一部分,因此您的blitting代码将覆盖这些状态,并且如果未手动还原这些状态,则随后的渲染将无法按预期进行。如果在循环中调用它,可能会得出错误的结论,即问题是问题,但实际上,错误的输入数据只是在正确地起作用。

关于go - 涂抹FBO颜色附件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60618437/

10-15 12:08