Help us understand the problem. What is going on with this article?

# Objective-cでMetalを使用して三角形の色を変更しよう

More than 1 year has passed since last update.

Metalを使用して、シェーダーを使って、三角形の色を後から変更する覚書
「Objective-cでMetalを使用して三角形を描画しよう」を参照
https://qiita.com/sanoh/items/cfc7ecb057b7588c2a52

## ■Step1：シェーダー変更

#ifdef __METAL_VERSION__
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define NSInteger metal::int32_t
#else
#import <Foundation/Foundation.h>
#endif

#include <simd/simd.h>

typedef NS_ENUM(NSInteger, BufferIndex)
{
BufferIndexPositions = 0,
BufferIndexUniforms  = 1
};

typedef struct
{
float   color[3];
} Uniforms;

#include <metal_stdlib>

using namespace metal;

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

fragment half4 myFragmentShader(constant Uniforms & uniforms [[ buffer(BufferIndexUniforms) ]]) {
return half4(uniforms.color[0],  uniforms.color[1], uniforms.color[2] , 1.0);
}

## ■Steop2:MetalRenderer.mを編集します。

MetalRenderer.m
#import "MetalRenderer.h"

static const NSUInteger MaxBuffersInFlight = 3;
static const size_t kAlignedUniformsSize = (sizeof(Uniforms) & ~0xFF) + 0x100;

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

id <MTLRenderPipelineState> _pipeline_state;
id <MTLBuffer>   _buffer_position;

id <MTLBuffer> _dynamic_uniform_buffer; //＜新規＞
uint8_t _uniform_buffer_index;          //＜新規＞
}

-(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.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);
}
//パラメータバッファの登録＜新規＞
NSUInteger uniform_buffer_size = kAlignedUniformsSize * MaxBuffersInFlight;
_dynamic_uniform_buffer = [_device newBufferWithLength:uniform_buffer_size
options:MTLResourceStorageModeShared];
}
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;
{
dispatch_semaphore_signal(block_sema);
}];
MTLRenderPassDescriptor* render_pass_descriptor = view.currentRenderPassDescriptor;
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)
{
_uniform_buffer_index = (_uniform_buffer_index + 1) % MaxBuffersInFlight;
//パラメータの更新＜新規＞
uint32_t  uniform_buffer_offset = kAlignedUniformsSize * _uniform_buffer_index;
void*     uniform_buffer_address = ((uint8_t*)_dynamic_uniform_buffer.contents) + uniform_buffer_offset;
uniforms->color[0]  = 0.0f;    //  R   色指定
uniforms->color[1]  = 0.0f;    //  G
uniforms->color[2]  = 1.0f;    //  B

id <MTLRenderCommandEncoder> render_encoder = [command_buffer renderCommandEncoderWithDescriptor:render_pass_descriptor];
//パラメータの設定＜新規＞
[render_encoder setFragmentBuffer:_dynamic_uniform_buffer
offset:uniform_buffer_offset
atIndex:BufferIndexUniforms];
//モデルの設定
[render_encoder setRenderPipelineState:_pipeline_state];
[render_encoder setVertexBuffer:_buffer_position
offset:0
atIndex:BufferIndexPositions];
[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

## ■Setp3：実行

iOsは実機で実行してくださいMacの場合は以下のようになります。

Why do not you register as a user and use Qiita more conveniently?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away