使用纯Metal-API以及SceneKit或SpriteKit

Oli*_*ver 11 scenekit sprite-kit swift metal

我在一个应用程序中运行了一个SKView和一个MTKView,到目前为止一切运行良好.

唯一的问题是,这两种观点在视觉上都很差.他们只是并排.但我想让SKView内部的纯金属渲染与内部的一些SKNode一起移动.它是SKView内部的一种快速显示.

在金属方面运行了相当多的计算和渲染的东西.SKView应该为重型计算提供了一个很好的用户界面,并且为纯金属部件提供了极小但非常快速的渲染.

我已经考虑过将SceneKit与SpriteKit场景叠加使用,因为SCNRenderer提供了使用renderAtTime渲染自己的MTLCommandBuffer和MTLRenderPassDescriptor的可能性.

我实现了以下SCNSceneRendererDelegate方法并调用了我自己的render函数,它正在准备commandBuffer.

func renderer(renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: NSTimeInterval) {
    nodeArray.render()
}
Run Code Online (Sandbox Code Playgroud)

在commandBuffer准备好之后,我调用了我的SCNRenderer的renderAtTime方法.试验和错误向我显示命令缓冲区必须在调用renderAtTime后提交.如果我在它崩溃应用之前这样做.如果我不这样做,它将冻结应用程序.

func bufferFinished(renderer:SCNRenderer, commandBuffer: MTLCommandBuffer, renderPassDescriptor: MTLRenderPassDescriptor){
    let current=CFAbsoluteTimeGetCurrent()
    renderer.renderAtTime(current, viewport: gameView.bounds, commandBuffer: commandBuffer, passDescriptor: renderPassDescriptor)
    commandBuffer.commit()
}
Run Code Online (Sandbox Code Playgroud)

如果我这样做,应用程序正在运行,但没有显示其他金属上下文.我认为因为金属部分所以整个事情都很复杂.

是否有任何简单的示例,其中纯金属在SceneKit视图中呈现或更好地在SpriteKit视图中呈现?

Oli*_*ver 4

金属、SpriteKit 和 SceneKit

SpriteKit 和 SceneKit 一起工作。您可以在 SpriteKit 中使用 SceneKit,反之亦然。

在 SpriteKit 中,您可以使用 SK3DNode 渲染 SceneKit 场景。这是一个示例:https://github.com/CloakedEddy/SK3DNode-example/tree/master/SKSCN%20Crossover

在SceneKit中,您可以使用SCNSceneRenderer的overlaySKScene属性,该属性由SCNView继承。您可以将 SpriteKit 场景与 SceneKit 场景并排渲染。

但如何整合金属呢?

将金属与 SpriteKit 结合使用可以通过纹理来完成。您可以在 GPU 上使用金属计算纹理,并通过修改PixelDataWithBlock 将图像数据传输到 SKMutableTexture。这是可行的,但你必须复制数据,这不太好,而且 SpriteKit 在幕后与 OpenGL 一起工作,而不是与金属一起工作。因此它必须创建一个 OpenGL 纹理,如您所见,这是非常昂贵的。

另一个问题是,如果您使用大型纹理在 CPU 内存中获取它们,则必须同步 GPU 数据。只有这样你才能将数据复制到SKMutableTexture。这是非常低效的,因为数据将再次进入 GPU,但现在使用 OpenGL。

在此输入图像描述

使用 SceneKit,您可以选择是否希望使用 OpenGL 或 Metal 作为 GPU 的底层框架。并且可以直接用金属修改材质属性中的纹理。只需设置 SCNMaterialProperty 的内容属性即可。或者,如果您想更改对象的几何形状,可以直接通过金属修改 SCNGeometrySource。