LoginSignup
3
4

More than 5 years have passed since last update.

Objective-cでMetalを使用して三角形を描画しよう

Last updated at Posted at 2018-11-21

Metalを使用して、シェーダーを使った、最小限のサンプル、覚書

■Step1:初期化

以前の初期化を参照してください
・iOsでObjective-cを使ってMetalを初期化
https://qiita.com/sanoh/items/f123306bd347764fcac4
・MacでObjective-cを使ってMetalを初期化
https://qiita.com/sanoh/items/fa49b9888e24fc977e0d

■Setp2:シェーダー作成

まず「Shader.metal」を作成します。
スクリーンショット 2018-11-21 16.07.47.png

Shader.metal
#include <metal_stdlib>
using namespace metal;

vertex float4 myVertexShader(const device packed_float3* vertex_array [[ buffer(0) ]],
                             unsigned int vid [[ vertex_id ]]) {
    return float4(vertex_array[vid], 1.0);
}

fragment half4 myFragmentShader() {
    return half4(1.0);
}

■Setp3:MetalRenderer.mの編集

MetalRenderer.m
#import "MetalRenderer.h"

static const NSUInteger MaxBuffersInFlight = 3;

@implementation MetalRenderer
{
    dispatch_semaphore_t _in_flight_semaphore;
    id <MTLDevice> _device;
    id <MTLCommandQueue> _command_queue;

    id <MTLRenderPipelineState> _pipeline_state; //<新規>
    id <MTLBuffer>   _buffer_position;           //<新規>
}

-(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view;
{
    //頂点データ<新規>
    float vertices_array[]={
        0.0, 1.0, 0.0,
        -1.0, -1.0, 0.0,
        1.0, -1.0, 0.0,
    };
    if(self= [super init])
    {
        _device = view.device;
        _in_flight_semaphore = dispatch_semaphore_create(MaxBuffersInFlight);
        view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
        _command_queue = [_device newCommandQueue];
        //頂点情報の登録<新規>
        NSInteger size = sizeof(vertices_array);
        _buffer_position=[_device newBufferWithBytes:vertices_array 
                                              length:size
                                             options:MTLResourceOptionCPUCacheModeDefault];
        //シェーダーの登録<新規>
        id <MTLLibrary> library = [_device newDefaultLibrary];
        MTLRenderPipelineDescriptor *descriptor = [[MTLRenderPipelineDescriptor alloc] init];
        descriptor.vertexFunction = [library newFunctionWithName:@"myVertexShader"];
        descriptor.fragmentFunction = [library newFunctionWithName:@"myFragmentShader"];
        descriptor.colorAttachments[0].pixelFormat=MTLPixelFormatBGRA8Unorm;       
        NSError *error = NULL;
        _pipeline_state = [_device newRenderPipelineStateWithDescriptor:descriptor 
                                                                  error:&error];
        if (!_pipeline_state)
        {
            NSLog(@"Failed to created pipeline state, error %@", error);
        }
    }
    return self;
}

- (void)drawInMTKView:(nonnull MTKView *)view
{
    dispatch_semaphore_wait(_in_flight_semaphore, DISPATCH_TIME_FOREVER);

    id <MTLCommandBuffer> command_buffer = [_command_queue commandBuffer];
    __block dispatch_semaphore_t block_sema = _in_flight_semaphore;
    [command_buffer addCompletedHandler:^(id<MTLCommandBuffer> buffer)
     {
         dispatch_semaphore_signal(block_sema);
     }];
    MTLRenderPassDescriptor* render_pass_descriptor = view.currentRenderPassDescriptor;
    render_pass_descriptor.colorAttachments[0].loadAction=MTLLoadActionClear;
    render_pass_descriptor.colorAttachments[0].storeAction=MTLStoreActionStore;
    render_pass_descriptor.colorAttachments[0].clearColor=MTLClearColorMake(1.0, 0.0, 0.0, 1.0);
    if(render_pass_descriptor != nil)
    {
        id <MTLRenderCommandEncoder> render_encoder = [command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
        //モデルの設定<新規>
        [render_encoder setRenderPipelineState:_pipeline_state];
        [render_encoder setVertexBuffer:_buffer_position 
                                 offset:0 
                                atIndex:0];
        [render_encoder drawPrimitives:MTLPrimitiveTypeTriangle 
                           vertexStart:0 
                           vertexCount:3];

        [render_encoder endEncoding];
        [command_buffer presentDrawable:view.currentDrawable];
    }
    [command_buffer commit];
}

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
{
}

@end

■Setp4:実行

iOsは実機で実行してくださいMacの場合は以下のようになります。
スクリーンショット 2018-11-21 16.08.22.png

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4