Metal 1

作者: f8d1cf28626a | 来源:发表于2022-07-20 05:18 被阅读0次

Metal 1

MetalKit

  • MTKView

Metal 渲染管道

  • 1.VertexData 通过CPU也就是我们的程序提供顶点数据
    1. VertexProcessing(VertexShader) -> PrimitiveAssembly -> Rasterization -> FragmentProcessing(FragmentShader) -> Framebuffer
VertexData(CPU)
Vertex Processing(VertexShader)
Primitive Assembly [triangles,quads,lines,points]
Rasterization
Fragment Processing(FragmentShader) [textures,stencil,alpha,depth]
Framebuffer (Screen Pixels)

MTKView 内部有一个定时器,去执行重绘的动作(可以自定义关闭或暂停)

苹果官方建议:Saparate Your Rendering Loop (分离或者抽离你的渲染模块,这样的解释大家比较容易理解)

MTKViewDelegate 两个必须实现的代理方法

  • 1.当窗口发生改变的时候会调用一个代理方法
-(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
  • 2.当帧率确定之后,比方帧率为60,每个60帧会调用一次代理方法
-(void)drawInMTKView:(nonnull MTKView *)view

Metal Command Objects

  • MTLDevice ->GPU

创建device

mtkview.device = MTLCreateSystemDefaultDevice();
  • MTLCommandQueue 所有应用程序需要与GPU交互的第一对象(也就是它先睡,睡完之后其他人才能睡)
_commandQueue = [_device newCommandQueue];
  • MTLCommandBuffer 为当前的每一个渲染传递创建一个新的命令缓冲区
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"command_1";
  • 命令缓冲区(commandBuffer)是由命令队列(_commandQueue)创建的
  • 命令编码器(commoand encoders)将命令编码到命令缓冲区中
  • commit命令缓存区并将其提交到GPU
  • GPU执行命令并将结果呈现为可绘制

理解:
1.命令时通过 command encoders 编译之后(编译这个字眼在OpenGLES就很熟悉了,方便理解)存储在 命令缓冲区中(commandBuffer)
2.然后通过命令缓冲区 驱动GPU完成绘制和显示的动作
3.Metal 不需要像OpenGLES一样需要自己编译和链接(毕竟是苹果爸爸的亲儿子,所以需要有神秘感)

【metal 1】

Metal 实践流程

  • 1.如何向GPU 发送渲染命令
  • 2.如何获取Metal设备
  • 3.如何配置MetalKit
  • 4.如何创建执行GPU指令
  • 5.如何显示渲染内容

案例1:实现背景颜色的更迭

步骤一 创建RCRendering类继承自NSObject 并添加MTKViewDelegate

#import <Foundation/Foundation.h>
@import MetalKit;

NS_ASSUME_NONNULL_BEGIN

@interface RCRendering : NSObject<MTKViewDelegate>

-(id)initWithMetalkitview:(MTKView *)mtkview;

@end

NS_ASSUME_NONNULL_END

步骤二 RCRendering 的完整步骤(当然了作为一个完美的男人,关键的时刻是隐藏)

1.定义私有变量

@implementation RCRendering
{
    id<MTLDevice> _device;
    id<MTLCommandQueue> _commandQueue;
}

2.定义一个颜色结构体

typedef struct {
    float r,g,b,a;
}CustomColor;

3.设置想要的颜色

-(CustomColor)makeFancycolor{
    // 用来判断是否增加颜色
    static BOOL growing = YES;
    // 创建一个颜色通道
    static NSUInteger primaryChannel = 0;
    static float colorChannels[] = {1.0,0.2,0.0,1.0};
    const float dynamicColorrate = 0.015;
    
    if (growing){
        NSUInteger dynamicChannelIndex = (primaryChannel +1)%3;
        colorChannels[dynamicChannelIndex] += dynamicColorrate;
        
        if (colorChannels[dynamicChannelIndex]>=1.0){
            growing = NO;
            primaryChannel = dynamicChannelIndex;
        }
    }
    else{
        NSUInteger dynamicChannelIndex = (primaryChannel + 2)%3;
        colorChannels[dynamicChannelIndex] -= dynamicColorrate;
        
        if (colorChannels[dynamicChannelIndex]<=0.0){
            growing = NO;
        }
    }
    CustomColor color;
    color.r = *colorChannels + 0;
    color.g = *colorChannels + 1;
    color.b = *colorChannels + 2;
    color.a = *colorChannels + 3;
    return color;
}

4.初始化方法

-(id)initWithMetalkitview:(MTKView *)mtkview{
    self = [super init];
    if (self){
        _device = mtkview.device;
        _commandQueue = [_device newCommandQueue];
    }
    return self;
}

5.MTKViewDelegate 方法

  • -(void)drawInMTKView
-(void)drawInMTKView:(nonnull MTKView *)view {
    // 拿到颜色值
    CustomColor color = [self makeFancycolor];
    
    // 清理背景颜色
    view.clearColor = MTLClearColorMake(color.r, color.g, color.b, color.a);
    
    // 创建commandbuffer
    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    commandBuffer.label = @"buffer_1";
    
    // 创建渲染描述对象(会自动打印描述信息)
    MTLRenderPassDescriptor *renderPD = view.currentRenderPassDescriptor;
    
    if (!renderPD) return;
    
    // 创建 command encoders
    id<MTLCommandEncoder> commandEncoders = [commandBuffer parallelRenderCommandEncoderWithDescriptor:renderPD];
    commandEncoders.label= @"command encoders";
    
    /** 省略一些内容 主要是桥接metal文件的内容,关键部分隐藏就不告诉你*/
    
    [commandEncoders endEncoding];
    
    // 把帧缓冲区的内容渲染到屏幕上
    [commandBuffer presentDrawable:view.currentDrawable];
    
    // 提交GPU
    [commandBuffer commit];
}
  • -(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange
-(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
    NSLog(@"%ld",(long)view.preferredFramesPerSecond);
    NSLog(@"%ld",(long)view.currentRenderPassDescriptor);
}

6.viewcontroller 里面的实现

// MTL MTK
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _mtkView = (MTKView*)self.view;
    
    _mtkView.device = MTLCreateSystemDefaultDevice();
    
    if (!_mtkView.device) return;
    
    _rcrender = [[RCRendering alloc] initWithMetalkitview:_mtkView];
    
    if (!_rcrender) return;
    
    _mtkView.delegate = _rcrender;
    
    // 设置帧率
    _mtkView.preferredFramesPerSecond = 60;
    
}

总结:MTL MTK

相关文章

  • 19-Metal的一些相关资料

    1、Metal Framework基础使用教程 2、iOS Metal图形API 3、Metal Shading ...

  • Metal 1

    Metal 1 MetalKit MTKView Metal 渲染管道 1.VertexData 通过CPU也就是...

  • Metal初探

    1.Metal简介 Metal是苹果为了减少对OpenGLES的依赖所封装的框架,在iOS系统中,Metal可以发...

  • 02-iOS 平台下 Metal 框架

    什么是Metal?Metal 与 OpenGL ES 区别?CPU/GPU 迭代 Metal 的表现 Metal ...

  • MTKView & MTLCommandBuffer

    1.库名: MetalKit MetalKit 基于metal 封装,极少代码可以完成Metal需求; 2. MT...

  • Metal(1)- 初探

    Metal介绍 Metal是苹果在2018年推出用于取代在苹果端的业务的图形编程接口,在2018年之前使用的是基于...

  • Metal Camera开发4:渲染到CVPixelBuffer

    Metal Camera开发1:读取渲染结果生成UIImage第5节:读取Metal渲染结果并生成UIImage介...

  • Metal学习(二) - 视频播放

    最近学习Metal在想,想着使用Metal渲染视频。于是有了想法 1. 使用AVAssetReader读取数据 在...

  • Metal入门002-Metal相关API

    Metal入门001-初识Metal 1. MTKView MTKView官方文档 在MetalKit中提供了一个...

  • 四:Metal示例

    Metal示例demo Metal加载多顶点文件 主要代码: Metal加载多tga文件 主要代码: Metal加...

网友评论

      本文标题:Metal 1

      本文链接:https://www.haomeiwen.com/subject/rdheirtx.html