【问题标题】:SKRenderer -- the mystery classSKRenderer——神秘类
【发布时间】:2018-11-28 19:15:41
【问题描述】:

在观看了 WWDC2017 的 session 609 视频后,我对从 SpriteKit 中提取屏幕外金属纹理感到非常兴奋。

这是一年多以前的事了!

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

我确实觉得这很奇怪。 这里有人对这个类、它的文档或示例代码有任何见解吗?

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

【问题讨论】:

  • 在声明它们的头文件中有这两个类的一些文档,这是值得的。始终检查标题。 :)

标签: sprite-kit scenekit metal skscene


【解决方案1】:

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];
}

如果您使用此技术,请记住将MTKViewframebufferOnly 属性设置为NO

如果您想将屏幕外渲染到您创建的纹理中,您需要做更多的手动工作,但所涉及的概念是相同的。您可以通过创建额外的渲染通道描述符/编码器来对渲染到相同纹理的单独通道进行编码;只需记住将原色附件的loadAction 设置为MTLLoadActionLoad 即可在各个通道中保留纹理的内容。

您还可以使用renderWithViewport:renderCommandEncoder:renderPassDescriptor:commandQueue: 将所有绘图合并到一个通道中。

一些注意事项:

  • 据我所知,viewport 参数被忽略。
  • 如果您希望SKScene 接收NSResponder 操作,您需要手动转发它们或将场景插入到响应者链中。这尤其适用于关键事件,其中场景(或负责向其转发的对象)需要成为第一响应者。
  • 当场景不是由SKView 呈现时,任何用于转换触摸或鼠标事件位置的便捷方法都不起作用;您需要进行一些人工翻译。

【讨论】:

  • 您是否能够以一种可以在 SKScene“后面”渲染纹理层的方式使 SKScene“透明”?编辑:实际上,正如您已经提到的,这只是通过使用 renderWithViewport:renderCommandEncoder:renderPassDescriptor:commandQueue: 来完成的。
  • @warrenm 你如何将场景插入到响应者链中?
  • 你有这个解决方案的工作示例代码项目吗?谢谢
【解决方案2】:

迅速

   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)


}

【讨论】:

    猜你喜欢
    • 2015-07-27
    • 1970-01-01
    • 2014-06-05
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 2010-11-12
    • 1970-01-01
    相关资源
    最近更新 更多