Skip to content

Instantly share code, notes, and snippets.

@edom18
Last active March 27, 2018 05:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edom18/0944186d0484e1a5271a to your computer and use it in GitHub Desktop.
Save edom18/0944186d0484e1a5271a to your computer and use it in GitHub Desktop.
iOSの新グラフィックAPI - Metal入門してみる ref: https://qiita.com/edo_m18/items/0fd6971c98c27a125d6e
import QuartzCore;
// CAMetalLayerの生成
CAMetalLayer *metalLayer = [CAMetalLayer layer];
metalLayer.device = device;
metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
metalLayer.framebufferOnly = YES;
metalLayer.frame = self.view.layer.frame;
[self.view.layer addSublayer:metalLayer];
id <MTLCommandQueue> commandQueue = [device newCommandQueue];
fragment half4 basic_fragment() {
return half4(1.0);
}
// MTLDeivceの生成
id <MTLDevice> device = MTLCreateSystemDefaultDevice();
// Render Command Encoderの生成
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
if (renderEncoder) {
[renderEncoder setRenderPipelineState:self.pipelineState];
[renderEncoder setVertexBuffer:self.vertexBuffer offset:0 atIndex:0];
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3 instanceCount:1];
[renderEncoder endEncoding];
}
id <MTLRenderPipelineState> pipelineState;
id <MTLLibrary> defaultLibrary = [device newDefaultLibrary];
id <MTLFunction> fragmentProgram = [defaultLibrary newFunctionWithName:@"basic_fragment"];
id <MTLFunction> vertexProgram = [defaultLibrary newFunctionWithName:@"basic_vertex"];
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.vertexFunction = vertexProgram;
pipelineStateDescriptor.fragmentFunction = fragmentProgram;
[pipelineStateDescriptor.colorAttachments objectAtIndexedSubscript:0].pixelFormat = MTLPixelFormatBGRA8Unorm;
NSError *pipelineError = nil;
pipelineState = [device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&pipelineError];
if (!pipelineState) {
NSLog(@"Failed to create pipeline state, error %@", pipelineError);
}
// 頂点情報
CGFloat vertexData[] = {
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
};
NSInteger dataSize = sizeof(vertexData);
id <MTLBuffer> vertexBuffer = [device newBufferWithBytes:vertexData length:dataSize options:MTLResourceOptionCPUCacheModeDefault];
vertex float4 basic_vertex(
const device packed_float3 *vertex_array [[buffer(0)]],
unsigned int vid [[vertex_id]]) {
return float4(vertex_array[vid], 1.0);
}
CADisplayLink *timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameloop)];
[timer addToRunLoop:NSRunLoop.mainRunLoop forMode:NSDefaultRunLoopMode];
/////////////////////////////////////////////////////////////////////////////
- (void)gameloop
{
@autoreleasepool {
[self render];
}
}
// Render Pass Descriptorの生成。
MTLRenderPassDescriptor *renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init];
renderPassDescriptor.colorAttachments[0].texture = texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 104.0/255.0, 5.0/255.0, 1.0);
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
// create a new command queue
_commandQueue = [_device newCommandQueue];
/////////////////////////////////////////////////////////////////////////////
id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
// 頂点データを定義する
static const float vertexData[] = {
0.0, -1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, 1.0, 0.0
};
id <MTLBuffer> buffer = [device newBufferWithBytes:vertexData length:sizeof(vertexData) options:MTLResourceOptionCPUCacheModelDefault];
static const float uniformData[] {
1.0, 1.0, 1.0, 1.0,
};
id <MTLBuffer> uniformBuffer = [device newBufferWithLength:sizeof(uniformData) options:MTLResourceOptionCPUCacheModelDefault];
void *buf = [uniformBuffer contents];
memcpy(buf, uniformData, sizeof(uniformData));
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer commit];
// 構造体の宣言
struct VertexIn {
packed_float3 position;
packed_float4 color;
};
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_shader_function(const device VertexIn *vertex_array [[buffer(0)]], unsigned int vid [[vertex_id]]) {
// do something.
}
fragment half4 fragment_shader_function(VertexOut input [[stage_in]]) {
// do something.
}
vertex float4 vertex_function(const device packed_float3 *vertex_array [[buffer(0)]],
const device Uniforms &uniforms [[buffer(1)]],
unsigned int vid [[vertex_id]]) {
// ...
}
id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
[renderEncoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
CGFloat data[] = {
1, 2, 3, 4, 5, 6, 7, // 7個でひとつの頂点分の情報になる
8, 9, 10, 11, 12, 13, 14,
...
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment