使用纯Metal-API以及SceneKit或SpriteKit

时间:2015-11-16 12:42:31

标签: swift sprite-kit scenekit metal

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

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

在金属方面运行了大量计算和渲染的东西。 SKView应该为重型计算提供一个很好的ui,并且对纯金属部件进行最小但非常快速的渲染。

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

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

func renderer(renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: NSTimeInterval) {
    nodeArray.render()
}

在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()
}

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

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

1 个答案:

答案 0 :(得分:4)

Metal,SpriteKit& SceneKit

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

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

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

但如何整合金属?

使用带有SpriteKit的金属可以使用纹理完成。您在GPU上使用金属计算纹理,并通过modifyPixelDataWithBlock将图像数据传输到SKMutableTexture。这是有效的,但你必须复制不好的数据,SpriteKit在幕后使用OpenGL而不是金属。所以它必须创建一个非常昂贵的OpenGL-Texture,如你所见。

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

enter image description here

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