如何在Metal中离线渲染/导出帧?

6
我是一个新手,学习Metal技术。我已经能够制作一个简单的场景,让四边形在屏幕上旋转。但是我想要导出一个1分钟的视频/帧数,而不需要实时进行渲染。比如用户只需打开应用并点击“导出”按钮,然后CPU/GPU就可以全速输出一个Quad旋转的1分钟视频/帧数,无需预览。
我知道如何使用AVFoundation将帧转换为视频,但不知道如何在没有实时渲染的情况下将我的3D场景转换为帧。请问有人能指点一下我该去哪里找相关资料吗?
非常感谢!
1个回答

12
我改编了我的答案(在这里)和苹果金属游戏模板,创建了这个示例,演示了如何直接从由Metal渲染的一系列帧中记录视频文件。由于Metal中的所有渲染都绘制到纹理上,因此将普通的Metal代码适应于离线渲染到电影文件中并不太难。总之,核心录制过程如下:
  • 创建一个AVAssetWriter,以目标URL为目标
  • 创建一个AVAssetWriterInput类型为.video,以便您可以写入视频帧
  • 在输入周围包裹一个AVAssetWriterInputPixelBufferAdaptor,以便您可以将CVPixelBuffer作为帧附加到视频中
  • 开始录制后,每个帧将渲染帧纹理中的像素复制到从适配器的像素缓冲池中获取的像素缓冲区中。
  • 完成时,将输入标记为完成并完成对资产编写的操作。
至于驱动录制,由于您没有从MTKViewCADisplayLink获取委托回调,因此您需要自己完成。基本模式如下:
for t in stride(from: 0, through: duration, by: frameDelta) {
    draw(in: renderBuffer, depthTexture: depthBuffer, time: t) { (texture) in
        recorder.writeFrame(forTexture: texture, time: t)
    }
}

如果您的渲染和录制代码是异步且线程安全的,您可以将其放在后台队列中以保持界面的响应性。如果您的渲染需要很长时间,您还可以添加进度回调来更新您的UI。请注意,由于您不是实时运行,因此您需要确保任何动画都考虑到当前帧时间(或帧之间的时间步长),以便在回放时以正确的速率运行。在我的示例中,我直接让立方体的旋转取决于帧的呈现时间。

O_O 非常感谢!这将会很有趣!我到处寻找,但从未找到离线渲染的示例。谢谢:D - masaldana2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接