本文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/