在之前OpenGL系列基礎(chǔ)之上,我們又對(duì)iOS原生Metal做了一些探索嫁审,這里主要是記錄一下學(xué)習(xí)的過程。
1.MTKView
在學(xué)習(xí)metal之前我們需要了解一下什么是MTKView
失驶,它是蘋果基于自家的Metal
渲染架構(gòu)上構(gòu)建的一個(gè)渲染視圖載體土居,類似于前面提到過的GLKView
。它能夠?yàn)槲覀兲峁┰?code>OpenGL ES的類似效果嬉探。下面介紹下MTKView
的初始化代碼:
- (void)createMTKView {
// 創(chuàng)建GPU設(shè)備
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
_device = device;
// 創(chuàng)建MTKView
self.mtkView = [[MTKView alloc] initWithFrame:self.view.bounds device:device];
self.mtkView.delegate = self;
self.mtkView.backgroundColor = UIColor.clearColor;
[self.view addSubview:self.mtkView];
// 記錄mtkView視口的大小
self.viewportSize = (vector_uint2){self.mtkView.drawableSize.width, self.mtkView.drawableSize.height};
// 創(chuàng)建命令隊(duì)列
id<MTLCommandQueue> commandQueue = [self.device newCommandQueue];
_commandQueue = commandQueue;
}
2.創(chuàng)建渲染管道
這里解釋下MTLRenderPipelineDescriptor
對(duì)象擦耀,為了我們能操控渲染管道,蘋果提供了這個(gè)對(duì)象涩堤。它可以關(guān)聯(lián)自定義著色器等操作眷蜓。
- (void)createRenderPipelineState {
NSError *error;
id<MTLLibrary> library = [self.device newDefaultLibrary];
if (error) {
NSLog(@"error:%@",error);
}
// 創(chuàng)建頂點(diǎn)著色器
id<MTLFunction> vertextFunction = [library newFunctionWithName:@"vertextShader"];
// 創(chuàng)建片段著色器
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"fragmentShader"];
MTLRenderPipelineDescriptor *renderPipelineDescritior = [[MTLRenderPipelineDescriptor alloc] init];
renderPipelineDescritior.colorAttachments[0].pixelFormat = self.mtkView.colorPixelFormat;
renderPipelineDescritior.vertexFunction = vertextFunction;
renderPipelineDescritior.fragmentFunction = fragmentFunction;
// 創(chuàng)建渲染管道 id<MTLRenderPipelineState>
id<MTLRenderPipelineState> renderPipelineState = [self.device newRenderPipelineStateWithDescriptor:renderPipelineDescritior error:nil];
_renderPipelineState = renderPipelineState;
}
3.初始化頂點(diǎn)緩存
在前面的準(zhǔn)備工作都做好之前,我們需要設(shè)置一些頂點(diǎn)數(shù)據(jù)來告訴MTKView
胎围,我們需要繪制的內(nèi)容的頂點(diǎn)數(shù)據(jù)吁系。
- (void)createVertextBuffer {
// 頂點(diǎn)數(shù)據(jù) (頂點(diǎn)坐標(biāo) + 頂點(diǎn)顏色)
BBVertex vertext[] = {
{ {-1, -0.5, 0, 1}, {1, 0, 0, 1} },
{ {0, 0.5, 0, 1}, {0, 1, 0, 1} },
{ {1, -0.5, 0, 1}, {0, 0, 1, 1} },
};
// 頂點(diǎn)數(shù)目
_vertextCount = sizeof(vertext) / sizeof(BBVertex);
// 構(gòu)建頂點(diǎn)緩存,這里options需要設(shè)置MTLResourceStorageModeShared,方便頂點(diǎn)數(shù)據(jù)在CPU與GPU之間快速存取
id<MTLBuffer> vertextBuffer = [self.device newBufferWithBytes:vertext length:sizeof(vertext) options:MTLResourceStorageModeShared];
_vertextBuffer = vertextBuffer;
}
4.渲染方法
在開始渲染之前白魂,我們必須實(shí)現(xiàn)MTKView
的兩個(gè)代理方法:
/**
MTKView視口大小發(fā)生變化時(shí)候回調(diào)
*/
- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
self.viewportSize = (vector_uint2){size.width, size.height};
}
/*!
這個(gè)方法執(zhí)行的頻率和MTKView默認(rèn)刷新頻率一致汽纤,默認(rèn)60幀。
可以通過設(shè)置MTKView的屬性preferredFramesPerSecond來調(diào)整回調(diào)頻率
*/
- (void)drawInMTKView:(nonnull MTKView *)view {
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
commandBuffer.label = @"commandBuffer";
// 獲取渲染描述對(duì)象福荸,可以理解為拿到真正的渲染對(duì)象
MTLRenderPassDescriptor *renderPassPipeline = view.currentRenderPassDescriptor;
if (commandBuffer && renderPassPipeline) {
// 設(shè)置背景色
renderPassPipeline.colorAttachments[0].clearColor = MTLClearColorMake(1, 1, 1, 1);
// 1.創(chuàng)建渲染編碼器
id<MTLRenderCommandEncoder> renderCommandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassPipeline];
// 2.設(shè)置視口大小
[renderCommandEncoder setViewport:(MTLViewport){0,0, self.viewportSize.x, self.viewportSize.y,-1,1}];
// 3.設(shè)置渲染管道狀態(tài)
[renderCommandEncoder setRenderPipelineState:self.renderPipelineState];
// 4.設(shè)置頂點(diǎn)緩存區(qū)
[renderCommandEncoder setVertexBuffer:self.vertextBuffer offset:0 atIndex:BBVertexInputIndexVertexes];
// 5.設(shè)置圖元連接方式
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:self.vertextCount];
// 6.結(jié)束命令編碼
[renderCommandEncoder endEncoding];
// 7.開始繪制
[commandBuffer presentDrawable:view.currentDrawable];
}
// 提交命令緩存
[commandBuffer commit];
}
5.渲染結(jié)果
三角形.png