Metal 框架之 MTKView
概述
MTKView 封装了 Metal 的基本功能,隐藏了配置 Metal 的一些操作,省去了开发者配置的麻烦,开发者只需要将精力花费在图形渲染即数据准备上就可以。
在 iOS, iPadOS, Mac Catalyst, tvOS中,代码定义如下:
```
class MTKView : UIView
```
在 macOS 中定义如下:
```
class MTKView : NSView
```
MTKView 使用 CAMetalLayer 来管理 Metal 可绘制对象,通过 MTLRenderPassDescriptor 对象可以将内容渲染到一个纹理中。
此外,通过 MTKView 可以创建深度和模板纹理以及抗锯齿所需的任何中间纹理。该视图使用 CAMetalLayer 来管理 Metal 可绘制对象。
指定绘制模式
MTKView 支持三种绘制模式:
定时更新:视图根据内部计时器重绘其内容。默认情况下使用这个绘制方式,初始化时需要将 isPaused 和 enableSetNeedsDisplay 都设置为 false。游戏和更新的动画内容常用这种模式。
绘制通知:当调用 setNeedsDisplay() 或者 当某些内容使其内容无效时,视图会重绘自身。在这种情况下,将 isPaused 和 enableSetNeedsDisplay 设置为 true。这种模式适用于具有更传统工作流程的应用程序,更新只会在数据更改时发生,而不会定期更新。
显式绘制:当显式调用 draw() 方法时,视图才会重绘其内容。这种模式下,需要将 isPaused 设置为 true 并将 enableSetNeedsDisplay 设置为 false。一般使用此模式来创建自定义工作流程。
绘制
无论使用哪一种绘图模式,当视图需要更新其内容时,在子类重写 draw(:) 方法时,它会调用 draw(:) 方法,否则在视图的委托上调用 draw(in:) 方法。
在绘图方法中,从视图中获取渲染通道描述符,此后的渲染结果都会存在渲染通道描述符中,最后渲染结果呈现在其关联的可绘制对象上。
从 MetalKit 视图中获取可绘制对象
CAMetalLayer 提供 MTKView 视图的绘图能力。在渲染器过程中,需要实现 MTKViewDelegate 协议来实现与 MetalKit 视图交互。调用 MetalKit 视图的 currentRenderPassDescriptor 属性可以获取当前帧的渲染通道描述符:
```
// BEGIN encoding your onscreen render pass.
// Obtain a render pass descriptor generated from the drawable's texture.
// (currentRenderPassDescriptor
implicitly obtains the current drawable.)
// If there's a valid render pass descriptor, use it to render to the current drawable.
if let onscreenDescriptor = view.currentRenderPassDescriptor
```
当读取currentRenderPassDescriptor属性时,Core Animation 会隐式获取当前帧的可绘制对象并将其存储在 currentDrawable 属性中。后续深度、模板和抗锯齿纹理会被绘制到 currentDrawable 对象中。视图使用默认的存储和加载操作配置此渲染通道,在创建 MTLRenderCommandEncoder 之前,可以调整描述符。为了提升渲染性能,应该尽可能晚地获取可绘制对象,最好是在编码屏幕渲染通道之前。
关联可绘制对象
在渲染内容后,需要将可绘制对象的结果更新到视图中来显示。展示内容最方便的方法是调用命令缓冲区上的 present(:) 方法将视图与命令缓冲区关联起来,然后调用 commit() 方法将命令缓冲区提交给 GPU:
``` if let onscreenDescriptor = view.currentRenderPassDescriptor,
let onscreenCommandEncoder = onscreenCommandBuffer.makeRenderCommandEncoder(descriptor: onscreenDescriptor) {
/* Set render state and resources.
...
*/
/* Issue draw calls.
...
*/
onscreenCommandEncoder.endEncoding()
// END encoding your onscreen render pass.
// Register the drawable's presentation.
if let currentDrawable = view.currentDrawable {
onscreenCommandBuffer.present(currentDrawable)
}
}
// Finalize your onscreen CPU work and commit the command buffer to a GPU.
onscreenCommandBuffer.commit()
```
当命令队列调度可执行的命令缓冲区时,可绘制对象会在该命令缓冲区中遍历其自身的所有渲染或写入请求。在命令完成执行之前,操作系统不会在屏幕上显示可绘制对象。通过这种调度方式,保证了命令队列调度此命令缓冲区之后才显示渲染结果。
总结
本文介绍了如何使用 MTKView 来创建、配置和展示 Metal 对象。讲解了 MTKView 使用的每个步骤,阅读完本文可以对 MTKView 绘制流程有个基本了解。
Metal 框架之 MTKView相关推荐
- Metal 框架之自定义设置渲染通道
概述 渲染通道是一系列渲染命令,用于绘制一组纹理.本示例执行一对渲染通道来渲染视图的内容.对于第一个通道,示例创建了一个自定义渲染,将图像渲染成纹理.这个通道是一个离屏渲染通道,因为样本渲染为普通纹理 ...
- Metal 框架之渲染管线渲染图元
概述 在 < Metal 框架之使用 Metal 来绘制视图内容 >中,介绍了如何设置 MTKView 对象并使用渲染通道更改视图的内容,实现了将背景色渲染为视图的内容.本示例将介绍如何配 ...
- Metal 框架之使用 Metal Debugger 查看 GPU 工作负载
概述 为了了解计算机是如何运行 App 或调试问题,通常要使用调试器.传统的调试器通过暂停一个线程来工作,但对基于 Metal 的 App 效果不佳. Xcode 通过帧捕获工作流专门为 Metal ...
- Metal 框架之创建纹理及纹理采样
概述 Metal 中使用纹理来绘制和处理图像,它是由像素组成的.使用2维数组的纹理来保存图像,每个元素都包含颜色数据.通过纹理映射技术将纹理绘制到几何图元上. 在片段着色器中,使用片段函数对纹理采样来 ...
- 基于 Metal 框架的 GPU 计算
概述 GPU 的优势在于并发计算能力,在本示例中,你将学习如何使用 Apple 的新框架 Metal 来实现并发计算. 你将学会如何将用C编写的简单函数转换为 Metal Shading Langua ...
- Metal 框架之从可绘制纹理中读取像素数据
概述 Metal 优化了纹理以供 GPU 快速访问,但不允许直接从 CPU 访问纹理的内容.当 App 需要更改或读取纹理的内容时,需要 Metal 在纹理和可访问的 CPU 内存(系统内存或使用共享 ...
- Metal 框架之资源存储模式
概述 Metal 中使用 MTLStorageMode 来指定资源的内存位置和访问权限. MTLStorageMode 是个枚举类型,定义如下: public enum MTLStorageMode ...
- Metal 框架之渲染到多个视口
概述 视口定义了渲染目标的一部分,绘图命令会渲染到该区域内.使用视口选择,可以为绘图命令提供多个视口,并且可以为绘图命令渲染的每个图元动态选择其中的一个视口.通过视口选择,使用更少的绘图命令,可以更轻 ...
- Metal 框架之渲染到多个纹理切片
概述 使用图层选择为顶点着色器中的每个图元选择目标切片,可以将图元渲染到纹理数组.立方体纹理或 3D 纹理的多个层(切片)中.层是单个 1D.2D 或 3D 像素块,由目标纹理中的切片和 mipmap ...
最新文章
- vba 字体颜色_多掌握一些VBA语句,让自己书写代码更加顺畅
- 无人驾驶系列】光学雷达(LiDAR)在无人驾驶技术中的应用
- 16-python基础5-文件读写操作
- 网和aoe网的区别_运动内衣与普通内衣有什么区别?运动内衣里面还需要穿文胸吗? 小家生活网20201002 11:03:04...
- 存储过程/函数权限的问题解决(The user specified as a definer ('root'@'%') does not exist)...
- (转)KeyDown、KeyUp、KeyPress区别
- 产品小姐姐收到这个黑科技后,开心了一整天...
- mysql数据库的笔试题_MySQL数据库常见面试题
- java正则表达式爬图片_Java正则表达式爬取网页,贴出完整代码
- MVC5+EF6简单实例---以原有SQLServer数据库两表联合查询为例
- WPF中如何选择合适的元数据标记?(英文)
- Java下载base64图片
- Java内存模型—JMM详解
- 【LSTM时间序列预测】基于matlab贝叶斯网络优化LSTM时间序列预测【含Matlab源码 1329期】
- ESP32笔记(2) flash使用
- win10下出现.net framework 3.5错误代码0x800F081F的问题
- 大数据为我们的生活带来了什么?
- linux who 时间,linux命令之who、w、whoami
- 协同过滤推荐算法及应用
- Libgdx之国际化 中英文菜单切换