Go Blitting FBO颜色附件

Go Blitting FBO颜色附件,go,opengl,gpu,Go,Opengl,Gpu,我有2个FBO+MRT,它们有相同的附件(每个有4个彩色附件)。使用glBlitFrameBuffer与深度缓冲区和onecolor\u附件的预期效果一样。然而,当我点击多个颜色附件时,事情就糟了。我做了很多研究,尝试了很多不同的方法,但没有一种有效。我没有使用renderBufferStorage,因为我的纹理具有不同的内部格式(RGBA和RGB16F)。听起来像是一个类似的问题,除了我没有使用多采样,只有MRT OpenGL 4.3版 原因:我想创建一个地形预照明计算的状态,这样我只需要在有

我有2个FBO+MRT,它们有相同的附件(每个有4个彩色附件)。使用glBlitFrameBuffer与深度缓冲区和onecolor\u附件的预期效果一样。然而,当我点击多个颜色附件时,事情就糟了。我做了很多研究,尝试了很多不同的方法,但没有一种有效。我没有使用renderBufferStorage,因为我的纹理具有不同的内部格式(RGBA和RGB16F)。听起来像是一个类似的问题,除了我没有使用多采样,只有MRT

OpenGL 4.3版

原因:我想创建一个地形预照明计算的状态,这样我只需要在有变化(即相机移动)时渲染地形,然后将这些颜色附件复制到下一个FBO。这是用于延迟着色,FBO与gBuffer非常相似

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

原代码在Golang编写,应易于移植到C++(如果需要,将翻译)。 更新/解决:适用于遇到此问题的任何人。使用glDrawBuffers()并调用glDrawBuffers()时,将覆盖glDrawBuffers()状态。需要将其重置为原始glDrawBuffers()状态

更新2:对于那些对这种方法感兴趣的人,我可以确认,如果你有一个非动画的世界,并且相机不经常移动,它会有令人难以置信的性能结果。就我而言,这是一款很棒的游戏(RTS),但对于像CS这样的FPS游戏来说,这将是一种非常糟糕的方法

在布点后添加以下内容(具体情况):

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)
在概念上等同于调用
glenumbufs[1]={x};glDrawBuffers(1,bufs)
。由于“绘制缓冲区”状态是FBO状态的一部分,因此blitting代码将覆盖这些状态,如果未手动恢复这些状态,则随后的渲染将无法按预期工作。如果您将其称为循环,这可能会导致错误的结论,即blitting是问题所在,但实际上,blitting工作正常,只是输入了错误的数据。

请编辑您的问题,以便更清楚地描述问题。你所说的只是“当我点击多个彩色附件时,事情会变糟”,
“没有错误,但会产生一些奇怪的现象”
,这并没有真正的帮助。查看片段着色器也可能很有用。它肯定会写入所有的彩色附件吗?在给定的代码片段中,我没有看到任何明显的工作。我在这里唯一能做的猜测是,也许你在下一帧中把drawbuffer状态搞砸了(如果这是在循环中运行的,你可能不会立即注意到这一点)
glDrawBuffer()
基本上撤消您在FBO设置部分中使用
glDrawBuffers()
设置的内容。draw buffer(s)状态存储在每个FBO中,您可以为blitting修改它,而无需还原它(至少不在目前发布的代码片段中)。@derhass您完全正确!我在你写这篇文章的5分钟前就知道了:)我不知道drawBuffer()调用会覆盖drawBuffers()init设置,现在这很有意义。我只是假设它会返回到原来的FBO状态drawBuffers()状态。我认为在初始化过程中设置glDrawBuffers()会与帧缓冲区绑定保持一致,然后在绑定时激活,就像VAO中的VBO一样。2.另外,我认为glDrawBuffer()和glDrawBuffers()是两个不同的函数,因此它不是“解除绑定”FBOs绘制状态。当你这样解释它的时候,是的,这是有道理的,布莱特正在做它应该做的和ofc。之后不应该恢复绑定,这可能会引入很多不必要的OpenGL调用。
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)