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文件的基本使用步骤 要注意细节哦
网友评论