SKRenderer 的基本用法非常简单,但在实践中有些奇怪之处使其有些古怪。
首先,基本面。要实例化渲染器,请使用rendererWithDevice: 方法。该方法采用id<MTLDevice>,如系统默认设备。请原谅 Objective-C;这将很容易转换为 Swift:
SKRenderer *renderer = [SKRenderer rendererWithDevice:mtlDevice];
为了告诉渲染器要绘制什么,我们将它与之前创建的场景相关联:
renderer.scene = (SKScene *)scene;
如果要运行动作,则需要手动取消暂停场景,这通常由 SKView 在呈现场景时完成:
scene.paused = NO;
要实际绘制场景,我们需要提供命令缓冲区和渲染通道描述符。假设您使用MTKView 来处理运行显示链接计时器并管理CAMetalLayer,您可以编写这样的委托方法,它通过渲染器更新场景的时间(和动作),然后绘制到@ 987654330@的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: 将所有绘图合并到一个通道中。
一些注意事项:
- 据我所知,
viewport 参数被忽略。
- 如果您希望
SKScene 接收NSResponder 操作,您需要手动转发它们或将场景插入到响应者链中。这尤其适用于关键事件,其中场景(或负责向其转发的对象)需要成为第一响应者。
- 当场景不是由
SKView 呈现时,任何用于转换触摸或鼠标事件位置的便捷方法都不起作用;您需要进行一些人工翻译。