使用metal做一个最简单的demo,目的是了解一下metal的渲染流程
效果图
整体绘制流程:
绘制流程.png
具体代码实现:
1, MTKView配置
//1.获取拿到`MTKView`设备
_view = (MTKView *)self.view;
//2.为_view 设置MTLDevice(必须)
//一个MTLDevice 对象代表获取GPU的使用权限
//通常我们可以调用方法MTLCreateSystemDefaultDevice()来获取单个的GPU对象.
_view.device = MTLCreateSystemDefaultDevice();
//3.HNRender该类是听从apple的建议,单独创建一个类来完成metal的渲染和代理的管理
_render = [[HNRender alloc] initWithMetalKitView:_view];
_view.delegate = _render;
//4.视图可以根据该属性设置帧速率(该代理drawInMTKView方法的调用频率)
_view.preferredFramesPerSecond = 1;
- 当然除了上述方式获取MTKView,也可以使用代码初始化
[[MTKView alloc] initWithFrame:CGRectMake(0, 0, width,height) device:MTLCreateSystemDefaultDevice()];
- 在iPhone6以下的设备是无法支持Metal的,所以有可能无法获取设备
-
HNRender
是自定义类,通过这种方式来解耦渲染流程.这也是Apple建议的方式
2,HNRender的初始化
-(id)initWithMetalKitView:(MTKView *)mtkView{
self = [super init];
if(self){
//1.从mtkview中获取device,用于MTLCommandQueue的创建
_device = mtkView.device;
//2.MTLCommandQueue是程序与GPU交互的第一个对象,也是一个串行队列,保证CommandBuffer的顺序执行
_commandQueue = [_device newCommandQueue];
}
return self;
}
-
MTLDevice、MTLCommandQueue
需要全局持有,因为后续会继续使用
3,实现MTKViewDelegate
数据准备
//获取一个随机色
//color为自定义结构体
Color color;
color.red = (float)(random() % 255) / 255;
color.green = (float)(random() % 255) / 255;
color.blue = (float)(random() % 255) / 255;
color.alpha = 1;
开始绘制
- (void)drawInMTKView:(MTKView *)view{
//1. 设置view的clearColor,相当于背景色
view.clearColor = MTLClearColorMake(color.red, color.green, color.blue, color.alpha);
//2. 每次渲染创建一个新的commandBuffer命令渲染编辑器
//使用MTLCommandQueue创建MTCommandBuffer新对象,并且将MTLCommandQueue加入到MTCommandBuffer对象中去.
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"HNBuffer";
//3. 通过当前MTKView获得渲染描述符
//在渲染过程中使用的渲染配置状态,包括光栅化(例如多重采样),可见性,混合,镶嵌和图形功能状态,主要是渲染管道描述符中指定顶点或片段函数。
MTLRenderPassDescriptor *descriptor = view.currentRenderPassDescriptor;
if (descriptor) {
//4.MTLCommandEncoder(命令渲染编辑器)通过MTLRenderPassDescriptor来创建
id<MTLCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:descriptor];
encoder.label = @"HNRenderEncoder";
//5. 此处做绘制操作
//6. 完成encoder操作
[encoder endEncoding];
}
/*
因为GPU是不会直接绘制到屏幕上,因此你不给出去指令.是不会有任何内容渲染到屏幕上.
*/
//7. 添加一个命令将帧缓存区的内容绘制到屏幕上
[commandBuffer presentDrawable:view.currentDrawable];
//8.
//提交绘制
[commandBuffer commit];
}
-
MTKViewDelegate
中还有一个方法为drawableSizeWillChange
本列中未使用到 -
MTLCommandEncoder
命令渲染编辑器,可以类比OpenGL ES中的上下文
来看待,主要用途是用于绘制对象,但在这个案例中并没有需要绘制的东西 -
commit
和enqueue
都可用于提交绘制;commit
是立即提交绘制;enqueue
等待下个可绘制周期
网友评论