在观看WWDC2017的第609节视频后,我在这里大肆宣传从SpriteKit中提取屏幕外的Metal纹理。
这是一年多以前!
但是,绝对没有关于SKRenderer
的概述文档,也没有示例代码。
https://developer.apple.com/documentation/spritekit/skrenderer
我发现这确实很奇怪。 这里有人对此类,其文档或示例代码有任何见解吗?
顺便说一句,SKTransformNode
也是如此。
最佳答案
SKRenderer
的基本用法非常简单,但是在实践中有些奇怪之处使其变得有些古怪。
首先,基本原则。要实例化渲染器,请使用rendererWithDevice:
方法。此方法采用id<MTLDevice>
,例如系统默认设备。原谅Objective-C;这将很容易转换为Swift:
SKRenderer *renderer = [SKRenderer rendererWithDevice:mtlDevice];
为了告诉渲染器要绘制什么,我们将其与先前创建的场景相关联:
renderer.scene = (SKScene *)scene;
如果要运行操作,则需要手动取消暂停场景,这通常是在呈现场景时由
SKView
完成的:scene.paused = NO;
要实际绘制场景,我们需要提供命令缓冲区和渲染过程描述符。假设您使用
MTKView
处理运行显示链接计时器并管理CAMetalLayer
,则可以编写这样的委托(delegate)方法,该方法通过渲染器更新场景的时间(和 Action ),然后绘制到MTKView
的drawable中:- (void)drawInMTKView:(nonnull MTKView *)view {
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor == nil) {
return;
}
[self.renderer updateAtTime:CACurrentMediaTime()];
id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
CGRect viewport = CGRectMake(0, 0, view.drawableSize.width, view.drawableSize.height);
[self.renderer renderWithViewport:viewport
commandBuffer:commandBuffer
renderPassDescriptor:renderPassDescriptor];
// TODO: Add any additional Metal rendering here
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer commit];
}
如果使用此技术,请记住将
MTKView
的framebufferOnly
属性设置为NO
。如果要将屏幕外渲染到已创建的纹理中,则需要做更多的手动工作,但是所涉及的概念是相同的。您可以通过创建其他渲染过程描述符/编码器来编码渲染为相同纹理的单独过程;只要记住将原色附件的
loadAction
设置为MTLLoadActionLoad
即可保留遍历中纹理的内容。您还可以使用
renderWithViewport:renderCommandEncoder:renderPassDescriptor:commandQueue:
将所有图形合并到一个 channel 中。一些警告:
viewport
参数被忽略。 SKScene
接收NSResponder
操作,则需要手动转发它们或将场景插入响应者链。这尤其适用于关键事件,其中场景(或负责转发给它的对象)需要成为第一响应者。 SKView
未呈现场景时,转换触摸或鼠标事件位置的便利方法都将不起作用;您需要进行一些手动翻译。