Metal 1

2022-07-20  本文已影响0人  f8d1cf28626a

Metal 1

MetalKit

Metal 渲染管道

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 两个必须实现的代理方法

-(void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
-(void)drawInMTKView:(nonnull MTKView *)view

Metal Command Objects

创建device

mtkview.device = MTLCreateSystemDefaultDevice();
_commandQueue = [_device newCommandQueue];
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"command_1";

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

【metal 1】

Metal 实践流程

案例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:(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:(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

上一篇 下一篇

猜你喜欢

热点阅读