渲染
顶点 (vertice, vertex)
一个顶点就是两个或多个的线, 曲线, 集合图形的焦点.
一个 3D 渲染器将会通过 model loader
代码去阅读这些顶点, 这些代码解析了顶点的列表. 然后渲染器会传递这些顶点到 GPU, shader (着色器, 流处理器)
方法会去处理这些顶点, 去创建最终的图片或者纹理, 然后会重新传递到 CPU, 以便在屏幕上展示.
渲染通道 (Rendering Pipeline) 是一个传送到 CPU 的命令表. 渲染通道包含了可编程和不可编程的方法, 前者, 一般被认为是顶点方法 (vertex functions) 和碎片方法 (fragment functions), 是你可以手动影响你最终你看见的渲染的模型的方法.
帧
每个静态图像都被认为是一个 frame (帧)
, 图片出现的速率叫做帧率.
Metal 处理序列
MetalKit
MetalKit 有一个自己的视图 — MTKView
。
MTKView 在 MacOS 上是 NSView
的子类,在 iOS 上是 UIView
的子类。
检测是否有合适的 GPU:
1 | guard let device = device else { |
创建一个 MTKView:
1 | let frame = CGRect(x: 75/2.0, y: 96, width: 300, height: 300) |
MTKClearColor
代表了一个 RGBA 色值。色值被存储在 clearColor
中, 用这个值设置 MTKView。
创建一个 MTLCommandQueue
对象:
1 | guard let commandQueue = device.makeCommandQueue() else { |
Device
和 Command
需要在一开始就设置, 设置一次, 各处使用.
The Model - Load a model
Model I/O
是一个整合 Metal 和 SceneKit 的框架. 它的主要目的是加载 3D 模型, 设置 data buffer
以便渲染.
1 | // 1. 创建一个网格数据内存管理器 |
Shader Functions
Shader Functions
是跑在 GPU 上的一小段代码, 用 Metal Shading Language (着色语言) 来写它们, 是一段 C++ 的代码子集.
通常情况下, 你会为 shader functions 创建一个独立的文件, 后缀为 .metal
The vertex function is where you usually manipulate vertex positions and the fragment function is where you specify the pixel color.
1 | let shader = """ |
The compiler will check that these functions exist and make them available to a pipeline descriptor (描述符号).
The Pipeline State - Setup the pipeline
在 Metal 中, 你为 GPU 设置一个通道状态, 通过这是这种状态, 你告诉 GPU, 除非状态改变, 什么都不会改变, 并且 GPU 可以运行更高效。通道状态包含了所有 CPU 需要的信息, 例如, 它需要用到的像素格式化和它是否需要渲染深度, 此外, 它也持有你创建的顶点和碎片方法。
然而, 你不直接创建通道状态, 而是通过创建一个 descriptor 来创建它。descriptor 持有了所有通道需要知道的东西, 并且, 为了那些特殊的渲染场景, 你仅仅是改变那些必要的属性即可:
1 | // 创建一个 pipeline descriptor |
vertex descriptor 描述了那些顶点如何在 Metal buffer 中被布局的。
当 Model I/O 加载球体网格的时候, 会自动创建顶点描述符号。
通过 descriptor 创建 pipeline state:
1 | let pipelineState = try device.makeRenderPipelineState(descriptor: descriptor) |
Creating a pipeline state takes valuable processing time, so all of the above should be a one-time setup. In a real app, you might create several pipeline states to call different shading functions or use different vertex layouts.
Rendering
MTKView 有一个代理方法, 可以运行每一帧。
MTKView provides a render pass descriptor and a drawable.
1 |
|