gpt4 book ai didi

ios - 将多个渲染目标 (MRT) 与多重采样相结合在 iOS 设备上失败,而不是在模拟器上

转载 作者:行者123 更新时间:2023-11-28 16:16:26 25 4
gpt4 key购买 nike

我正在尝试在 iOS (>= 8.0) 上编写一个使用多渲染目标 (MRT) 的 OpenGLES-3.0 Swift 应用程序。为了获得适当的抗锯齿效果,我启用了多重采样。

详细来说,我的渲染架构是这样的:

  • 显示帧缓冲区附有一个渲染缓冲区:

    • 显示渲染缓冲区:由 iOS 通过 EAGLContext.renderbufferStorage() 控制,附加为 GL_COLOR_ATTACHMENT0
  • 示例帧缓冲区 附加了两个渲染缓冲区:

    • 颜色渲染缓冲区 I:GL_RGBA8,多重采样,附加为 GL_COLOR_ATTACHMENT0
    • Color renderbuffer II:GL_RGBA8,多重采样,附加为 GL_COLOR_ATTACHMENT1

每当我的图层更改其边界时,我都会像 Apple 在 GLPaint 示例中那样调整所有渲染缓冲区的大小。

我为您创建了一个最小示例。渲染本身看起来像这样:

//Set the GL context, bind the sample framebuffer and specify the viewport:
EAGLContext.setCurrentContext(context)
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), self.sampleFramebuffer)
glViewport(0, 0, self.layerWidth, self.layerHeight)

//Clear both render targets:
glClearBufferfv(GLenum(GL_COLOR), 0, self.colorRenderbufferIClearColor)
glClearBufferfv(GLenum(GL_COLOR), 1, self.colorRenderbufferIIClearColor)

//Specify the vertex attribute (only position, 6 floats for a triangle):
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(2 * sizeof(GLfloat)), nil)

//Use the shader program and render a single triangle:
glUseProgram(self.program)
glDrawArrays(GLenum(GL_TRIANGLES), 0, 3)

//Prepare both framebuffers as source and destination to do multisampling:
glBindFramebuffer(GLenum(GL_READ_FRAMEBUFFER), self.sampleFramebuffer)
glBindFramebuffer(GLenum(GL_DRAW_FRAMEBUFFER), self.displayFramebuffer)

//Specify from which of the attachments we do the multisampling.
//This is GL_COLOR_ATTACHMENT0 or GL_COLOR_ATTACHMENT1.
glReadBuffer(self.blitAttachment)

//Transfer data between framebuffers and do multisampling:
glBlitFramebuffer(0, 0, self.layerWidth, self.layerHeight, 0, 0, self.layerWidth, self.layerHeight, GLbitfield(GL_COLOR_BUFFER_BIT), GLenum(GL_LINEAR))

//Invalidate the sample framebuffer for this pass:
glInvalidateFramebuffer(GLenum(GL_READ_FRAMEBUFFER), 2, [GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_COLOR_ATTACHMENT1)])

//Bind the display renderbuffer and present it:
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), self.displayRenderbuffer)
self.eaglContext.presentRenderbuffer(Int(GL_RENDERBUFFER))

现在问题来了:我的示例项目将红色背景上的蓝色三角形绘制到第一个渲染目标(彩色渲染缓冲区 I)中,并将绿色背景上的紫色三角形绘制到第二个渲染目标(彩色渲染缓冲区 II)中。通过在代码中设置 blitAttachment,您可以选择将两个附件中的哪一个解析到显示帧缓冲区中。

  • iOS 模拟器(所有设备,所有 iOS 版本)上的一切都按预期运行。
  • 目前我只能使用 iPad Air(型号 A1475,iOS 9.3.4)。但是在设备上,存在问题:
    • 如果我禁用多重采样(glRenderbufferStorageMultisample() 中的级别 = 0),一切正常。
    • 如果我启用多重采样(级别 = 4),我只能从 GL_COLOR_ATTACHMENT0(这是颜色渲染缓冲区 I)进行 blit。
    • 来自 GL_COLOR_ATTACHMENT1 的 Blitting 产生相同的结果(红色蓝色三角形),但应该会导致另一个结果(绿色紫色三角形)。

您可以使用我的附件重现问题 sample code (DropBox) .所以有两个问题:

  1. 有人可以确认这在模拟器上有效,但在真实设备上无效吗?
  2. 有人知道我代码中的错误吗?或者这是一个已知错误?

提前致谢!

最佳答案

此 API 中似乎有一些奇怪的行为。您链接的代码确实可以在模拟器上运行,但模拟器与实际设备有很大不同,因此我建议您不要将其用作引用。

所以似乎发生的是渲染缓冲区被丢弃得太快了。为什么以及如何发生这种情况我不知道。您 blit 缓冲区然后使它们无效,因此只需删除缓冲区无效即可解决问题。但是不建议删除缓冲区失效,因此在使它们失效之前确保所有任务都已由 GPU 执行。这意味着只需调用 flush

在调用 glInvalidateFramebuffer(GLenum(GL_READ_FRAMEBUFFER), 2, [GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_COLOR_ATTACHMENT1)]) 之前,只需调用 glFlush():

//Resolve from source to destination while applying multisampling:
glBlitFramebuffer(0, 0, self.layerWidth, self.layerHeight, 0, 0, self.layerWidth, self.layerHeight, GLbitfield(GL_COLOR_BUFFER_BIT), GLenum(GL_LINEAR))
OpenGLESView.checkError(dbgDomain, andDbgText: "Failed to blit between framebuffers")

glFlush()

//Invalidate the whole sample framebuffer:
glInvalidateFramebuffer(GLenum(GL_READ_FRAMEBUFFER), 2, [GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_COLOR_ATTACHMENT1)])
OpenGLESView.checkError(dbgDomain, andDbgText: "Failed to invalidate sample framebuffer")

关于ios - 将多个渲染目标 (MRT) 与多重采样相结合在 iOS 设备上失败,而不是在模拟器上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39017450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com