二、使用Metal绘制视图内容

本文Demo

环境:

mac os 10.14.5

xcode 10.3

此系列文章源自官方案例,详情至 此处

专用名词虽有汉字翻译,但会保留原有英文形式名词。

 

概览

本示例中,将学习用Metal渲染图形内容的基础知识。用 Metal Framework创建视图,用 Metal绘制视图内容。然后,为 渲染过程 编码命令,清除视图生成背景色。

 

1.准备绘制 MetalKit 视图

MetalKit提供 MTKView类,继承自 NSView(macOS)或者 UIView(iOS 或 tvOS)。MTKView 处理许多用Metal绘制的内容在屏幕上相关的细节  。

MTKView需要对 Metal device object(设备对象)引用,才能在内部创建资源。因此第一步设置视图的 device属性。

_view.device = MTLCreateSystemDefaultDevice();

通过 MTKView 的其他属性去控制它的行为。设置 clearColor属性,清除视图的内容生成纯背景色,用 MTLClearColorMake函数创建,指定 red、green、blue 和 alpha。

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

示例不会绘制动画内容,因此配置视图需要更新时才绘制,如形状改变:

_view.enableSetNeedsDisplay = YES;

 

2.委托绘制责任

MTKView 依赖应用向Metal发送命令生成可视内容。MTKView 需要绘制时使用委托模式通知应用。为了能够收到委托的回调,设置视图的 delegate属性为遵守 MTKView Delegate协议的对象。

_view.delegate = _renderer;

 

委托实现了两个方法:

a)当内容大小改变的时候,视图调用mtkView:drawbleSizeWillChange: 方法。当调整包含视图的窗口大小时或者设备的方向改变(在 iOS上)时发生。允许应用根据呈现的分辨率调整视图大小。

b)当更新视图内容的时候,调用 drawInMTKView: 方法。在此方法中,创建命令缓冲区,编码命令来告知GPU在屏幕上绘制何物以及何时显示,将命令缓冲区放入队列等待GPU执行。有时也称作绘制 frame(帧),可以把帧想象成生成一张图片的工作。像在游戏类的应用中,每秒绘制很多帧。

示例中,AAPLRenderer 类实现委托方法,并且承担绘制责任。控制器将其实例化设置成视图的delegate。

 

3.创建Render Pass Descriptor(渲染过程描述符)

绘制时,GPU 存储结果到 textures纹理),它是包含图片数据和可供GPU访问的内存块。MTKView创建了需要绘制视图的所有纹理。它创建了多个纹理,以便在渲染一个纹理时可以显示另一个纹理的内容。

为了要绘制,需要创建 render pass(渲染过程),它是一系列的渲染命令绘制成的一组纹理。当在 render pass上使用时,纹理也被叫做 render targets(渲染目标)。为了创建 render pass,需要 MTLRenderPassDescriptor实例。示例中,不要配置自己的渲染过程描述符,而是要 MetalKit 视图创建。

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

渲染过程描述符描述 render targets(渲染目标即纹理),以及如何在渲染过程开始和结束时处理它们。视图返回一个渲染过程描述符,其中包含指向纹理之一的单一颜色附件,否则根据视图的属性配置渲染过程。默认情况下,意味着在渲染过程的开始,纹理被清除成匹配视图的 clearColor属性的纯色,渲染过程结束时,所有的变化被存储到纹理中。

由于渲染过程描述符可能为空,在创建渲染过程之前,需要确保其不为空。

 

4.创建 render pass(渲染过程)

可以通过 MTLRender CommandEncoder 对象将其编码进命令缓冲区来创建渲染过程。调用命令缓冲区的 renderCommandEncoderWithDescriptor: 方法并传入 渲染过程描述符

id commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

此示例中,不需要编码任何绘制命令,因此渲染过程唯一要做的是清除纹理。调用 endEncoding 方法表明该过程完毕。

[commandEncoder endEncoding];

 

5.呈现可绘制对象到屏幕

对纹理的绘制不会自动显示在屏幕的新内容上。事实上,仅有一些纹理可以展现。在 Metal 中,呈现在屏幕上的纹理被 drawable对象管理,要显示内容,将呈现可绘制对象。

MTKView 自动创建 drawable 对象去管理纹理。通过 currentDrawable属性获取渲染过程目标拥有纹理的可绘制对象。视图返回一个和 Core Animation 关联的 CAMetalDrawable对象。

id drawable = view.currentDrawable;

在命令缓冲区调用 presentDrawable: 方法,并传递 drawable(可绘制对象)

[commandBuffer presentDrawable:drawable];

此方法旨在告诉Metal,当命令缓冲区计划执行时,应协调Core Animation在渲染完成后去显示纹理。当Core Animation呈现纹理时,它将成为视图的新内容。示例中,清除纹理成为视图的新背景色。此改变随着Core Animation为屏幕用户界面元素进行的其他可视化更新一起发生。

 

6.提交命令缓冲区

现在已经为 frame(帧)下发所有的命令,提交命令缓冲区。

[commandBuffer commit];

个人博客:https://blog.csdn.net/Crazy_SunShine

Github:https://github.com/cxymq

个人公众号:Flutter小同学

个人网站:http://chenhui.today/

你可能感兴趣的:(Metal)