SKRenderer-神秘阶层

时间:2018-06-19 18:35:15

标签: sprite-kit scenekit metal skscene

在看完WWDC2017的609会议视频后,我在这里大肆宣传从SpriteKit中拉出屏幕外的Metal纹理。

这是一年多以前了!

但是SKRenderer上绝对没有概述文档,也没有示例代码。 https://developer.apple.com/documentation/spritekit/skrenderer

我确实发现这很奇怪。 这里的任何人对此类,其文档或示例代码有任何见解吗?

顺便说一句,SKTransformNode也是如此。

2 个答案:

答案 0 :(得分:11)

SKRenderer的基本用法非常简单,但是在实践中存在一些奇怪之处。

首先,基础知识。要实例化渲染器,请使用rendererWithDevice:方法。此方法采用id<MTLDevice>,例如系统默认设备。原谅Objective-C;这将轻松转换为Swift:

SKRenderer *renderer = [SKRenderer rendererWithDevice:mtlDevice];

要告诉渲染器要绘制的内容,我们将其与先前创建的场景相关联:

renderer.scene = (SKScene *)scene;

如果要运行操作,则需要手动取消暂停场景,这通常由SKView在呈现场景时完成:

scene.paused = NO;

要实际绘制场景,我们需要提供命令缓冲区和渲染过程描述符。假设您使用MTKView处理运行显示链接计时器并管理CAMetalLayer,则可以编写这样的委托方法,该方法通过渲染器更新场景的时间(和动作),然后绘制到MTKView的可绘制对象中:

- (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的{​​{1}}属性设置为framebufferOnly

如果要将屏幕外渲染到已创建的纹理中,则需要做更多的手动工作,但是所涉及的概念是相同的。您可以通过创建其他渲染过程描述符/编码器来编码渲染为相同纹理的单独过程;只需记住将原色附件的NO设置为loadAction,以保留遍历中纹理的内容。

您还可以使用MTLLoadActionLoad将所有图形合并为一个遍。

一些警告:

  • 据我所知,renderWithViewport:renderCommandEncoder:renderPassDescriptor:commandQueue:参数将被忽略。
  • 如果您希望viewport接收SKScene动作,则需要手动转发它们或将场景插入响应者链。这尤其适用于关键事件,其中场景(或负责转发给它的对象)必须是第一响应者。
  • NSResponder未呈现场景时,用于转换触摸或鼠标事件位置的便利方法均不起作用;您需要进行一些手动翻译。

答案 1 :(得分:0)

迅速

   func render(renderCommandEncoder: MTLRenderCommandEncoder){
    skScene.size = Engine.previewViewSize



        currentTime = 0//allows looping skaction


    //sprite kit render
    skrender.update(atTime: currentTime )

    let viewport = CGRect(x: 0, y: 0, width: (Engine.previewViewSize.width), height: (Engine.previewViewSize.height))

    skScene.isPaused = false

    skrender.scene = skScene

    skrender.render(withViewport: viewport, renderCommandEncoder: renderCommandEncoder, renderPassDescriptor: Engine.currentRenderPassDescriptor, commandQueue: Engine.CommandQueue)


}