go - Blitting FBO 颜色附件

标签 go opengl gpu

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

OpenGL 版本 4.3

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

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

原始代码是用 Golang 编写的,应该可以轻松转换为 C++(如果需要,将进行翻译)。

更新/已解决:对于遇到此问题的任何人。当您使用 glDrawBuffers() 并调用 glDrawBuffer() 时,您将覆盖 glDrawBuffers() 状态。它需要重置为原来的 glDrawBuffers() 状态。

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

在 blitting 之后添加以下内容(具体情况):

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)

现在是 blitting 部分。

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, 缓冲区)。由于绘图缓冲区状态是 FBO 状态的一部分,您的 blitting 代码会覆盖这些状态,如果不手动恢复这些状态,之后的渲染 将无法按预期工作。如果您在循环中调用它,这可能会导致错误的结论,即 blitting 是问题所在,但实际上,blitting 工作正常,只是输入数据错误。

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

相关文章:

go - 运算符 = 和 := in struct in Golang

mongodb - 使用 struct & mongodb/mongo-go-driver 更新/替换 mongodb 文档

go - 进程花费了太长时间程序退出:Golang错误

c++ - 读取 BMP BGR 值,传递给 glTexImage2D

opengl - GPU上的纹理图像处理?

c - OpenCL 内核中存在问题的 while 循环 : Execution hangs

oracle - 使用 Oracle 调用接口(interface) (OCI) 设置操作系统用户

opengl - GLSL 1.5 简单几何着色器

opengl - 只执行一次 GLSL 函数

c - 2DRange 中每个工作组的 OpenCL 工作项