前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Metal(二)- 案例01:HelloWorldMetal(二)- 案例01:HelloWorld

Metal(二)- 案例01:HelloWorldMetal(二)- 案例01:HelloWorld

作者头像
用户8893176
发布2021-08-09 11:22:36
3620
发布2021-08-09 11:22:36
举报
文章被收录于专栏:小黑娃Henry

使用metal做一个最简单的demo,目的是了解一下metal的渲染流程

效果图

整体绘制流程:

绘制流程.png

具体代码实现:

1, MTKView配置
代码语言:javascript
复制
    //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的初始化
代码语言:javascript
复制
-(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

数据准备

代码语言:javascript
复制
//获取一个随机色
//color为自定义结构体
    Color color;
    color.red = (float)(random() % 255) / 255;
    color.green = (float)(random() % 255) / 255;
    color.blue = (float)(random() % 255) / 255;
    color.alpha = 1;

开始绘制

代码语言:javascript
复制
- (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中的上下文来看待,主要用途是用于绘制对象,但在这个案例中并没有需要绘制的东西
  • commitenqueue都可用于提交绘制;commit是立即提交绘制;enqueue等待下个可绘制周期
demo的GitHub地址
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/8/31 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 具体代码实现:
    • 1, MTKView配置
      • 2,HNRender的初始化
        • 3,实现MTKViewDelegate
          • demo的GitHub地址
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档