Metal 2

作者: f8d1cf28626a | 来源:发表于2022-07-21 22:22 被阅读0次

Metal 2

绘制一个三角形

理解 :顶点函数,图元装配,光栅化,片元函数,逐片段操作

  • 步骤一 :创建一个bridge_shaders.h
#ifndef bridge_shaders_h
#define bridge_shaders_h

typedef enum RRVertexInputIndex
{
    //顶点
    RRVertexInputIndexVertices     = 0,
    
    // 纹理
    
    //视图大小
    RRVertexInputIndexViewportSize = 1,
} RRVertexInputIndex;


//结构体: 顶点/颜色值
typedef struct
{
    // 像素空间的位置
    // 像素中心点(100,100)
    vector_float4 position;

    // RGBA颜色
    vector_float4 color;
} RRVertex;



#endif
  • 步骤二:创建一个Shaders.metal
#include <metal_stdlib>
using namespace metal;

#import "bridge_shaders.h"

typedef struct{
    
    // 处理空间顶点信息 和 GLSL gl_Position 相通
    float4 clipSpacePosition [[position]];
    
    // 颜色
    float4 rrcolor;
    
}RasterizerData;

// 顶点坐标

vertex RasterizerData vertShader(// 函数参数
uint vertID [[vertex_id]],
constant RRVertex *verts [[buffer(RRVertexInputIndexVertices)]],
constant vector_uint2 *viewportSizePointer [[buffer(RRVertexInputIndexViewportSize)]]){
    
    RasterizerData out;
    out.clipSpacePosition = verts[vertID].position;
    out.rrcolor = verts[vertID].color;
    return out;
}

fragment float4 fragShader(RasterizerData data [[stage_in]]){
    float4 color = data.rrcolor;
    return color;
}

  • 步骤三:创建一个RCObject 并遵循代理 MTKViewDelegate

定义变量

@implementation RCObject{

    id <MTLDevice> _device;
    id <MTLCommandQueue> _commandQueue;
    vector_uint2 _viewPortsize; // 视口
    id<MTLRenderPipelineState> _pplineState;// 渲染管道
}

初始化 -(instancetype)initWithMTKView:(MTKView *)mtkView

-(instancetype)initWithMTKView:(MTKView *)mtkView{
    
    self = [super init];
    
    if (!self) return nil;
    
    NSError *error;
    
    _rrdevice = mtkView.device;
    
    // 拿到着色器文件
    id<MTLLibrary> rrlib = _rrdevice.newDefaultLibrary;
    
    // 从metal文件中加载两个函数 (顶点和片元)
    id<MTLFunction> vertFunction = [rrlib newFunctionWithName:@"vertShader"];
    id<MTLFunction> fragFunction = [rrlib newFunctionWithName:@"fragShader"];
    
    // render pipeline
    MTLRenderPipelineDescriptor *rrPipeline = [[MTLRenderPipelineDescriptor alloc] init];
    rrPipeline.label = @"current render pipeline solved simple";
    rrPipeline.vertexFunction = vertFunction;
    rrPipeline.fragmentFunction = fragFunction;
    rrPipeline.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat;
    
    // render pipeline state
    _rrPipelineState = [_rrdevice newRenderPipelineStateWithDescriptor:rrPipeline error:&error];
    if (error) return nil;
    
    // create queue
    _rrcommandQueue = [_rrdevice newCommandQueue];
    
    return self;
}
  • 步骤四:MTKViewDelegate
- (void)drawInMTKView:(nonnull MTKView *)view {
    
    // 三角形顶点数据
    static const RRVertex triangleVertices[] =
    {
        //顶点,    RGBA 颜色值
        { {  0.5, -0.25, 0.0, 1.0 }, { 1, 0, 0, 1 } },
        { { -0.5, -0.25, 0.0, 1.0 }, { 0, 1, 0, 1 } },
        { { -0.0f, 0.25, 0.0, 1.0 }, { 0, 0, 1, 1 } },
    };
    
    // command buffer
    id<MTLCommandBuffer> commandbuffer = [_rrcommandQueue commandBuffer];
    commandbuffer.label = @"current command buffer";
    
    // MTLRenderPassDescriptor
    MTLRenderPassDescriptor *renderPD = view.currentRenderPassDescriptor;
    
    if (!renderPD) return;
    
    // create command encoders
    id<MTLRenderCommandEncoder> commandEncoder = [commandbuffer renderCommandEncoderWithDescriptor:renderPD];
    commandEncoder.label = @"current encoders";
    
    MTLViewport vport = {0.0,0.0,_rrviewPortsize.x,_rrviewPortsize.y,-1.0,1.0};
    
    [commandEncoder setViewport:vport];
    
    // setup commandEncoder pipelinestate
    [commandEncoder setRenderPipelineState:_rrPipelineState];
    
    // transmit vertData
    [commandEncoder setVertexBytes:triangleVertices length:sizeof(triangleVertices) atIndex:RRVertexInputIndexVertices];
    
    // transmit fragData (not)
    
    // transmit viewport size
    // [commandEncoder setViewports:&vport count:RRVertexInputIndexViewportSize];
    [commandEncoder setVertexBytes:&_rrviewPortsize length:sizeof(_rrviewPortsize) atIndex:RRVertexInputIndexViewportSize];
    
    // primitives
    [commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
    
    [commandEncoder endEncoding];
    [commandbuffer presentDrawable:view.currentDrawable];
    [commandbuffer commit];
    
}
  • 步骤五:- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
    
    _rrviewPortsize.x = size.width;
    _rrviewPortsize.y = size.height;
    NSLog(@"%f",size.width);
    NSLog(@"%f",size.height);
}
  • 步骤六:viewcontroller
@interface ViewController ()
{
    MTKView *_mtkView;
    
    RCObject *_rcObjc;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _mtkView = (MTKView *)self.view;
    _mtkView.device = MTLCreateSystemDefaultDevice();
    _rcObjc = [[RCObject alloc] initWithMTKView:_mtkView];
    [_rcObjc mtkView:_mtkView drawableSizeWillChange:_mtkView.drawableSize];
    _mtkView.delegate = _rcObjc;
    
    _mtkView.preferredFramesPerSecond = 60;
}
  • 提示:metal 只能使用真机运行

Metal文件的基本使用步骤 要注意细节哦

相关文章

网友评论

      本文标题:Metal 2

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