使用纯Metal-API与SceneKit或SpriteKit一同使用

12

我有一个SKView和MTKView在同一个应用程序中运行,到目前为止一切都很顺利。

唯一的问题是这两个视图的视觉整合很差。它们只是并排放置。但我想在SKView内部使用纯Metal渲染,并与其中的一些SKNode一起移动。这是SKView内部快速显示的一种方式。

在Metal方面,运行了相当多的计算和渲染工作。SKView应该为重型计算提供良好的UI和极简但非常快速的纯金属部分渲染。

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

我实现了以下SCNSceneRendererDelegate方法并调用了我的自定义渲染函数,该函数正在准备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视图中呈现纯金属?


2
SceneKit和SpriteKit在“幕后”使用Metal渲染您的内容。如果您想使用纯Metal,则不能同时使用SpriteKit和Metal。它们是两种不同用途的技术。 - Epic Byte
1
不像 UIKit 那样,Sprite Kit 和 Scene Kit 的目的都部分地是 Metal 目的的子集。Sprite Kit 和 Scene Kit 作为基于 Metal 的库更有意义,但目前它们更像游戏引擎,除非它们旨在跨平台使用,否则这并没有太多意义。 - user652038
有几种方法可以做到这一点。例如使用SCNRender:https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNRenderer_Class/index.html#//apple_ref/doc/uid/TP40012014-CLSCHSCNRenderer-DontLinkElementID_4 或者使用SCNSceneRenderer: https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNSceneRenderer_Protocol/#//apple_ref/doc/uid/TP40012016-CLSCHSCNSceneRenderer-DontLinkElementID_11 - Oliver
1个回答

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上的金属计算纹理,并通过modifyPixelDataWithBlock将图像数据传输到SKMutableTexture中。这是可行的,但您必须复制数据,这不太好,而且SpriteKit在幕后使用OpenGL而不是金属。因此,它必须创建一个OpenGL纹理,这非常昂贵,正如您所看到的。

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

enter image description here

使用SceneKit,您可以选择OpenGL或Metal作为GPU的基础框架。并且您可以直接使用metal在材质属性中修改纹理。只需设置SCNMaterialProperty的内容属性即可。或者,如果要更改对象的几何形状,则可以直接通过metal修改SCNGeometrySource。


根据这份文档,SpriteKit 默认使用 Metal:https://developer.apple.com/library/content/qa/qa1904/_index.html - average Joe

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