创立一个 MetalKit View 并运用 render pass 来制作视图的内容。

概述

作为 Metal 初见系列的第二篇,咱们主要探索运用 Metal 烘托图形内容的基础知识。运用 MetalKit 框架创立一个视图,该视图的内容运用 Metal 制作。咱们将经过 render pass 进程中的 encode commands 将视图擦除为指定的布景色彩。

预备一个 MetalKit View 来制作

MetalKit 供给了一个名为 MTKView 的类,它是 NSView (在macOS中) 或 UIView (在 iOS 和 tvOS 中) 的子类。MTKView 内部完成了运用 Metal 制作的内容显现到屏幕上相关的诸多细节。

MTKView 创立内部资源需求运用 MetalDevice 方针,因而咱们第一步是将视图的 device 特点设置为现有的 MTKView。

_view.device = MTLCreateSystemDefaultDevice();

MTKView 供给了一些特点让咱们来控制他的行为。想要将视图布景擦除到指定的色彩。咱们能够运用 MTLClearColorMake(::::) 函数,需求指定红、绿、蓝、和 值。

_view.clearColor = MTLClearColorMake(0.0, 0.5, 1.0, 1.0);

因为本次咱们没有烘托没有动画,咱们只需求配置视图在需求更新的时分更新。例如:视图形状改变。

_view.enableSetNeedsDisplay = YES;

托付署理职责

MTKView 的烘托内容由咱们的 App 供给。MTKView 烘托时运用署理形式通知咱们的 App,为了保证收到署理的回调,咱们需求给 MTKView 的 delegate 特点设置一个方针,完成 MTKDelegate 协议。

_view.delegate = _renderer;

署理需求完成两个办法:

  • 当视图巨细发生改变时或当设备方向改变 (iOS),咱们的应用程序会习惯分辨率显现视图的巨细。此刻调用 mtkView (_: drawableSizeWillChange) 办法,仅当内容的巨细发生改变时。
  • 当需求更新视图的内容时,视图调用 draw(in:) 办法。在这个办法中,咱们将创立一个命令缓冲区,经过 command buffer 告知 GPU 咱们要在屏幕上显现什么。这个有时分也叫烘托一帧。咱们能够认为一帧,一切的工作都是为了产生一个能够显现在屏幕上图画。在可交互式应用程序中,比如游戏,咱们可能会需求很多帧。

在本示例中,咱们创立一个名为 AAPLRenderer 类,完成托付办法和绘图的职责。视图控制器会创立这个类的一个实例,并设置它作为视图的托付。

创立一个 Render Pass Descriptor

制作时,GPU 将结果存储到纹路中,纹路是包括图画数据且可供 GPU 拜访的内存块。在本示例中,MTKView 创立了咱们需求制作到视图中的一切纹路。咱们能够创立多个纹路,在显现一个纹路的时分烘托到另一个纹路以供显现。

要进行制作,咱们需求创立一个 render pass,它是制作到一组纹路中的一系列烘托命令。在 render pass 中,纹路也称为烘托方针。要创立 render pass,咱们需求创立一个

MTLRenderPassDescriptor 方针,在此示例中,咱们不需求配置自己的烘托 MTLRenderPassDescriptor,MetalKit 视图会帮咱们创立一个。

MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
if (renderPassDescriptor == nil)
{
    return;
}

RenderPassDescriptor 描绘烘托方针集合,以及在烘托进程开始和结束时应怎么处理它们。RenderPass 还定义了烘托的其他一些方面,这些方面不属于本示例。视图不仅会回来带有指向视图纹路之一的单一色彩附件的 RenderPassDescriptor,还会依据视图的特点配置 RenderPass。这意味着默认情况下,在烘托开始时,烘托方针被擦除为与视图特点匹配的纯色,并且在烘托通道结束时,一切更改都存储到纹路。

注意视图 RenderPassDescriptor 可能是 nil ,调用之前需求做判空处理。

创立一个 Render Pass

咱们能够运用 MTLRenderCommandEncoder 方针创立 RenderPassDescriptor 。调用 Command Buffer 的 MTLRenderCommandEncodermakeRenderCommandEncoder(descriptor:) 办法,传入 RenderPassDescriptor 方针。

id<MTLRenderCommandEncoder> commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

在本示例中,咱们不需求对任何绘图命令进行编码,因而 RenderPass 所做的唯一事情便是擦除纹路。调用编码器的 endEncoding办法以指示传递完成。

[commandEncoder endEncoding];

将制作方针显现在屏幕上

事实上不是一切的纹路都能展现,一个烘托好的纹路也不能自动展现在屏幕上。在 Metal 中,能被显现在屏幕上的纹路都被 drawable objects,方针管理,包括显式内容展现。

MTKView 自动创立 drawable objects 来管理纹路,经过 currentDrawable 特点能够获取到可制作的 drawable 方针,包括当时 RenderPass 的方针纹路。视图会回来一个关联 Core AnimationCAMetalDrawable 方针。

id<MTLDrawable> drawable = view.currentDrawable;

调用 command buffer 的 present(_:) 办法,传入 drawable 方针。

[commandBuffer presentDrawable:drawable];

这个办法告知 Metal,当命令缓冲区被执行时,Metal 应该合作 Core Animation 在烘托完成后显现纹路。当 Core Animation 呈现纹路时,它成为视图的新内容。在本示例中,这意味着擦除的纹路成为视图的新布景。这一改变与 Core Animation 为屏幕上的用户界面元素所做的任何其他视觉一同更新。

提交到命令缓冲区

到此处咱们已经完成了当时帧的全部工作,最终咱们要提交 command buffer。

[commandBuffer commit];

Demo 示例

UsingMetalToDrawAViewContentsents.zip

参考

Using Metal to Draw a View’s Contents