Metal是苹果于2014年WWDC中发布的图像处理、通用计算的框架,而在今年的ios12中,OpenGL ES的API也被标记为废弃了,所以作为一个iOS开发者,有必要了解下这个框架。
这次还是和学习OpenGL的时候一样,先使用Metal画一个三角形。
在iOS下使用Metal
创建用于Metal显示内容的组件
在Metal中,可以选择使用CAMetalLayer或者MTKView,本文选择使用CAMetalLayer,需要注意的是,在项目的运行设备是模拟器的时候,会提示找不到CAMetalLayer这个类,这是因为Metal取消了模拟器的支持,只能使用64位处理器的真机进行开发和调试。
1 |
|
创建MTLDevice
1 |
|
设备是一个遵循了MTLDevice协议的类,是对GPU的抽象,许多Metal对象都需要通过设备对象来获取。这里创建了默认的设备,并且设置为CAMetalLayer的设备。
创建shader
和OpenGL一样,Metal渲染也需要顶点着色器程序和片段着色器程序,使用Metal着色语言编写。在Metal开发中,可以通过xcode创建一个.metal文件,用于编写相应的着色器程序。
1 |
|
这里定义了一个顶点着色器程序,vertex关键字用于标记这是一个顶点着色器程序。float4表示这个函数的返回值是一个四维向量,在这里四个值分别表示为x,y,z,w,其中w用于做一些旋转平移缩放时方便计算,一般为1。之后是两个函数的参数,constant修饰第一个参数为常量,是一个三维向量的数组,也就是传入的顶点坐标。中间的[[buffer(0)]]表明是缓存数据,0是索引,索引值用于区分一些时候传入的数据不全是顶点数据时,比如传入的数据包含顶点坐标,颜色和纹理坐标,用索引来获取到正确的数据。第二个参数用与获取当前处理的顶点。函数体中就是返回了一个表示坐标的四维向量。
1 |
|
这里定义了一个片段着色器程序,返回一个四维向量表示颜色的rgba,这里固定写为红色。
创建MTLLibrary
1 |
|
创建MTLFunction
1 |
|
创建一个的管道描述器
1 |
|
创建一个管道
1 |
|
这样就构建了一个完整的数据处理的管道,接下来需要将数据传入。
创建顶点坐标缓冲
1 |
|
这样就创建了一个顶点缓冲,其中MTLResourceCPUCacheModeDefaultCache表示它可以被GPU、CPU读写,同时也是操作也是有序的。
创建命令队列和命令缓冲
1 |
|
创建一个渲染路径描述器
1 |
|
先取得layer的drawable,它是一个用于显示的资源,可以被Metal渲染或改写。然后创建了渲染路径描述,描述了一个清屏为白色然后再渲染的操作。
创建一个命令编码器
1 |
|
创建一个编码器,并指定之前创建的pipeline和顶点,drawPrimitives:vertexStart:vertexCount,类似glDrawArray函数,不过它应该不是直接绘制,而是编码出一个绘制多边形的命令。
提交命令
1 |
|
这样就完成了一个三角形的绘制
<img src=”https://i.loli.net/2019/06/17/5d075fbe6222099023.jpg” alt=”Metal01.png” title=”Metal01.png” width= 36%/>
绘制矩形
1 |
|
和OpenGL一样,也可以使用4个顶点来绘制一个矩形,修改drawPrimitives:的参数为MTLPrimitiveTypeTriangleStrip,然后顶点顺序为z字形即可。
<img src=”https://i.loli.net/2019/06/17/5d0760983cf0b76962.jpg” alt=”Metal01.png” title=”Metal01.png” width= 36%/>
总结
Metal的主要逻辑和OpenGL类似,都是将顶点数据传给顶点着色器,计算出坐标后在传给片段着色器,由片段着色器计算出像素的颜色。但具体代码的实现上,Metal比OpenGL更符合iOS开发者的习惯,不过Metal感觉渲染的步骤较多,需要好好理解下。