Metal 2:MetalKit (MTKView) 和 SceneKit 互操作性

Posted

技术标签:

【中文标题】Metal 2:MetalKit (MTKView) 和 SceneKit 互操作性【英文标题】:Metal 2: MetalKit (MTKView) and SceneKit interoperability 【发布时间】:2018-10-26 13:04:08 【问题描述】:

我正在使用 MetalKit 并且有一个复杂的渲染管道。结果被渲染到 MTKView 中。

现在我想将 MTKView 的内容提供给 SCNScene 并使用 SCNCamera 执行 HDR 等后期处理效果。

这怎么可能?

我不想要大致的方向。如果可能的话,我想要特定的电话。

【问题讨论】:

我假设“HDR 等后处理效果”是指仅适用于 HDR 工作流程的后处理效果,例如色调映射。这意味着在 MTKView 中呈现场景之前,您已经在渲染到 HDR 目标;正确的?通常,您无法访问 SceneKit 管理的渲染目标,因此这里的主要问题是如何以高性能的方式将您的 HDR 目标放入“SceneKit 世界”。您想达到哪些具体效果? @warrenm 是的,我有一个 MTLPixelFormatRGBA16Float 格式的输出,可以由 HDR 流处理。我想应用 HDR。所以,我的想法是在 MTKView 或纹理中执行渲染,然后将该纹理传递给 SCNScene,该 SCNScene 有一个平面节点,其中应用了我的管道形式的纹理,还有一个 SCNCamera 节点正在查看将应用 HDR 效果的平面。 【参考方案1】:

理想情况下,您应该将后期处理作为 Metal 渲染管道的一部分。您建议的过程需要不必要的资源,因为您将在 SceneKit 中以 3D 形式渲染 2D 平面,只是为了应用一些 HDR 效果。

不过,您可以通过将 Metal 管道输出渲染到纹理然后简单地将其应用到 SceneKit 中的平面来实现您想要的。

首先分配你的纹理:

plane.materials.first?.diffuse.contents = offscreenTexture

然后将 SceneKit 渲染覆盖到 Metal 渲染循环:

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) 
    doRender()

然后以纹理为目标执行 Metal 渲染,完成后渲染 SceneKit 场景:

func doRender() 
    //rendering to a MTLTexture, so the viewport is the size of this texture
    let viewport = CGRect(x: 0, y: 0, width: CGFloat(textureSizeX), height: CGFloat(textureSizeY))

    //write to offscreenTexture, clear the texture before rendering using green, store the result
    let renderPassDescriptor = MTLRenderPassDescriptor()
    renderPassDescriptor.colorAttachments[0].texture = offscreenTexture
    renderPassDescriptor.colorAttachments[0].loadAction = .clear
    renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 1, 0, 1.0); //green
    renderPassDescriptor.colorAttachments[0].storeAction = .store

    let commandBuffer = commandQueue.makeCommandBuffer()

    // reuse scene1 and the current point of view
    renderer.scene = scene1
    renderer.pointOfView = scnView1.pointOfView
    renderer.render(atTime: 0, viewport: viewport, commandBuffer: commandBuffer, passDescriptor: renderPassDescriptor)

    commandBuffer.commit()
`

完整示例项目:

https://github.com/lachlanhurst/SceneKitOffscreenRendering

【讨论】:

非常感谢!我赞成你的回答,但为了接受我必须理解和实施:)。所以我很快就会回来,我希望。 这对我帮助很大。感谢演示应用程序。史诗!

以上是关于Metal 2:MetalKit (MTKView) 和 SceneKit 互操作性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中从 MTKView 制作屏幕截图?

MTKView 显示广色域 P3 色彩空间

MTKView 绘图性能

如何在 macOS 上渲染半透明的 MTKView?

如何检测 MTKView 中鼠标按下事件发生的位置?

Metal官方文档-Using Metal to Draw a View’s Contents