Metal
metal是iOS设备的一个底层图形API,功能类似OpenGL,支持图形渲染和GPU通用计算.
metal解决了图形开发中的图片纹理加载和三维模型加载
Metal框架提供了3种我们可以写入的附件类型:
-
colorAttachments
颜色纹理,用于保存绘图结果并将其显示在屏幕上. depthAttachmentPixelFormat
stencilAttachmentPixelFormat
vertexFunction:顶点着色器函数
fragmentFunction:片段着色器函数
pixeFormat: 配置像素格式
Metal shading language
:Metal着色语言基于C ++
构建Metal
应用程序分两个阶段
第一阶段Initialization
(初始化):
-
Get the Device 获取device设备,设备是与
GPU
驱动程序和硬件的直接连接 -
Create a CommandQueue 创建一个
command queue
命令队列,这个我们向GPU提交工作的渠道 -
Create Resource(Buffers and Textures) 创建缓冲区,纹理和其他资源,
makeBuffer
函数将将分配一个新的共享内存块,将提供的指针复制到其中,并将句柄返回给该缓冲区. -
Create RenderPipelines 创建
render pipeline
(渲染管线),这是一连串的步骤,从一端去顶点数据开始,另一端产生光栅化图像.流水线包含两个元素:保存shader
(着色器)信息和像素格式的描述符,以及从描述符构建并包含编译着色器的state
(状态). - Create a View 创建一个视图.对我们而言,从MTKView继承更容易,而不是创建担心的CAMetalLayer并将其添加为子视图.
第二阶段: Drawing
(绘制)
-
Get a command buffer 获取初始阶段创建好的
command buffer
-
Start a Render Pass 设置
render pass
.渲染管道描述符告诉Metal
渲染图像时要执行的操作.配置它需要我们指定我们渲染的颜色纹理(currentDrawable
纹理).在绘制任何几何体之前,我们还需要选择屏幕将被清除的颜色 - Draw 绘制.我们指定存储顶点的缓冲区,然后指定我们需要绘制的基元.
-
Commit the command buffer 提交命令缓冲区给
GPU
. 调用commit
时,command buffer
(命令缓冲区)会被编码,发送到命令队列的末尾,并在GPU运行时执行.
补充一下矩阵:
translation matrix
(平移矩阵)
| 1 0 0 Dx |
| 0 1 0 Dy |
| 0 0 1 Dz |
| 0 0 0 1 |
scaling matrix
(缩放矩阵)
| Sx 0 0 0 |
| 0 Sy 0 0 |
| 0 0 Sz 0 |
| 0 0 0 1 |
rotation matrix
(旋转矩阵)
绕x轴
| 1 0 0 0 |
| 0 cos -sin 0 |
| 0 sin cos 0 |
| 0 0 0 1 |
绕y轴
| cos 0 sin 0 |
| 0 1 0 0 |
| -sin 0 cos 0 |
| 0 0 0 1 |
绕z轴
| cos -sin 0 0 |
| sin cos 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
对应👆的转换:
struct Matrix {
var m: [Float]
init() {
m = [1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
]
}
func translationMatrix(var matrix: Matrix, _ position: float3) -> Matrix {
matrix.m[12] = position.x
matrix.m[13] = position.y
matrix.m[14] = position.z
return matrix
}
func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix {
matrix.m[0] = scale
matrix.m[5] = scale
matrix.m[10] = scale
matrix.m[15] = 1.0
return matrix
}
func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix {
matrix.m[0] = cos(rot.y) * cos(rot.z)
matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z)
matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z)
matrix.m[1] = cos(rot.y) * sin(rot.z)
matrix.m[5] = cos(rot.x) * cos(rot.z) + sin(rot.x) * sin(rot.y) * sin(rot.z)
matrix.m[9] = -cos(rot.z) * sin(rot.x) + cos(rot.x) * sin(rot.y) * sin(rot.z)
matrix.m[2] = -sin(rot.y)
matrix.m[6] = cos(rot.y) * sin(rot.x)
matrix.m[10] = cos(rot.x) * cos(rot.y)
matrix.m[15] = 1.0
return matrix
}
func modelMatrix(var matrix: Matrix) -> Matrix {
return matrix
}
}