創(chuàng)建MetalView
self.mtkView.device = MTLCreateSystemDefaultDevice(); // 獲取默認(rèn)的device
self.view = self.mtkView;
self.mtkView.delegate = self;
self.viewportSize = (vector_uint2){self.mtkView.drawableSize.width, self.mtkView.drawableSize.height};
創(chuàng)建pipeline
id<MTLLibrary> defaultLibrary = [self.mtkView.device newDefaultLibrary]; // .metal
id<MTLFunction> vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"]; // 頂點shader甘萧,vertexShader是函數(shù)名
id<MTLFunction> fragmentFunction = [defaultLibrary newFunctionWithName:@"samplingShader"]; // 片元shader,samplingShader是函數(shù)名
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.vertexFunction = vertexFunction;
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
pipelineStateDescriptor.colorAttachments[0].pixelFormat = self.mtkView.colorPixelFormat;
self.pipelineState = [self.mtkView.device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
error:NULL]; // 創(chuàng)建圖形渲染管道,耗性能操作不宜頻繁調(diào)用
self.commandQueue = [self.mtkView.device newCommandQueue]; // CommandQueue是渲染指令隊列躯护,保證渲染指令有序地提交到GPU
創(chuàng)建頂點矩陣
static const LYVertex quadVertices[] =
{ // 頂點坐標(biāo),分別是x母市、y够坐、z、w檩帐; 紋理坐標(biāo)术幔,x、y湃密;
{ { 0.5, -0.5, 0.0, 1.0 }, { 1.f, 1.f } },
{ { -0.5, -0.5, 0.0, 1.0 }, { 0.f, 1.f } },
{ { -0.5, 0.5, 0.0, 1.0 }, { 0.f, 0.f } },
{ { 0.5, -0.5, 0.0, 1.0 }, { 1.f, 1.f } },
{ { -0.5, 0.5, 0.0, 1.0 }, { 0.f, 0.f } },
{ { 0.5, 0.5, 0.0, 1.0 }, { 1.f, 0.f } },
};
self.vertices = [self.mtkView.device newBufferWithBytes:quadVertices
length:sizeof(quadVertices)
options:MTLResourceStorageModeShared]; // 創(chuàng)建頂點緩存
self.numVertices = sizeof(quadVertices) / sizeof(LYVertex); // 頂點個數(shù)
創(chuàng)建紋理
- (void)setupTexture {
UIImage *image = [UIImage imageNamed:@"abc"];
// 紋理描述符
MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
textureDescriptor.pixelFormat = MTLPixelFormatRGBA8Unorm;
textureDescriptor.width = image.size.width;
textureDescriptor.height = image.size.height;
self.texture = [self.mtkView.device newTextureWithDescriptor:textureDescriptor]; // 創(chuàng)建紋理
MTLRegion region = {{ 0, 0, 0 }, {image.size.width, image.size.height, 1}}; // 紋理上傳的范圍
Byte *imageBytes = [self loadImage:image];
if (imageBytes) { // UIImage的數(shù)據(jù)需要轉(zhuǎn)成二進制才能上傳诅挑,且不用jpg、png的NSData
[self.texture replaceRegion:region
mipmapLevel:0
withBytes:imageBytes
bytesPerRow:4 * image.size.width];
free(imageBytes); // 需要釋放資源
imageBytes = NULL;
}
}
- (Byte *)loadImage:(UIImage *)image {
// 1獲取圖片的CGImageRef
CGImageRef spriteImage = image.CGImage;
// 2 讀取圖片的大小
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
Byte * spriteData = (Byte *) calloc(width * height * 4, sizeof(Byte)); //rgba共4個byte
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,
CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
// 3在CGContextRef上繪圖
CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
CGContextRelease(spriteContext);
return spriteData;
}
渲染
// 每次渲染都要單獨創(chuàng)建一個CommandBuffer
id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
// MTLRenderPassDescriptor描述一系列attachments的值泛源,類似GL的FrameBuffer拔妥;同時也用來創(chuàng)建MTLRenderCommandEncoder
if(renderPassDescriptor != nil)
{
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.5, 0.5, 1.0f); // 設(shè)置默認(rèn)顏色
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; //編碼繪制指令的Encoder
[renderEncoder setViewport:(MTLViewport){0.0, 0.0, self.viewportSize.x, self.viewportSize.y, -1.0, 1.0 }]; // 設(shè)置顯示區(qū)域
[renderEncoder setRenderPipelineState:self.pipelineState]; // 設(shè)置渲染管道,以保證頂點和片元兩個shader會被調(diào)用
[renderEncoder setVertexBuffer:self.vertices
offset:0
atIndex:0]; // 設(shè)置頂點緩存
[renderEncoder setFragmentTexture:self.texture
atIndex:0]; // 設(shè)置紋理
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
vertexStart:0
vertexCount:self.numVertices]; // 繪制
[renderEncoder endEncoding]; // 結(jié)束
[commandBuffer presentDrawable:view.currentDrawable]; // 顯示
}
[commandBuffer commit]; // 提交俩由;
名詞解釋
- vertex:頂點函數(shù)
- fragment: 片元函數(shù)
- buffer: vertex參數(shù),小括號模具代表了encoder設(shè)置VertexBuffer的index毒嫡,
- texture: 輸入紋理,小括號枚舉代表了encoder設(shè)置的texture的index
疑問點
- sharder是怎么綁定的