LoginSignup
0
0

More than 5 years have passed since last update.

Objective-cでMetalを使用してテクスチャを表示しよう

Last updated at Posted at 2018-11-30

Metalを使用して、テクスチャ表示する覚書
「Objective-cでMetalを使用して三角形を描画しよう」を参照
https://qiita.com/sanoh/items/cfc7ecb057b7588c2a52

■Step1:シェーダー変更

まずはShaderType.h を追加します。
スクリーンショット 2018-11-30 12.26.44.png

ShaderType.h
#ifndef ShaderType_h
#define ShaderType_h

#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)
{
    BufferIndexMeshPositions = 0
};

typedef NS_ENUM(NSInteger, TextureIndex)
{
    TextureIndexColor    = 0,
};

#endif /* ShaderType_h */

Shader.Metal を編集

Shader.Metal
#include <metal_stdlib>
#include <simd/simd.h>
#import "ShaderType.h"

using namespace metal;

struct Vertex {
    float2 position;
    float2 texCoord;
};

struct ColorInOut{
    float4  position [[position]];
    float2  texCoord;
};

vertex ColorInOut myVertexShader(constant Vertex *vertices [[buffer(BufferIndexMeshPositions)]],
                                 uint vid [[vertex_id]]) {
    ColorInOut  out;

    out.position    = float4(vertices[vid].position, 0.0, 1.0);
    out.texCoord    = vertices[vid].texCoord;
    return out;
}

fragment half4 myFragmentShader(ColorInOut vert [[stage_in]],
                                texture2d<half> colorMap     [[ texture(TextureIndexColor) ]]) {
    constexpr sampler defaultSampler;
    half4 imageColor = colorMap.sample(defaultSampler, vert.texCoord.xy);
    return imageColor;
}

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

MetalRenderer.m
#import "MetalRenderer.h"
#import "ShaderType.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;

    id <MTLTexture> _color_image;   //<新規>
}

-(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view;
{
    //頂点情報<変更>
    float vertices_array[]={
        +0.0, +1.0, 0.0, 0.0,
        -1.0, -1.0, 1.0, 0.0,
        +1.0, -1.0, 1.0, 1.0,
    };
    if(self= [super init])
    {
        _device = view.device;
        _in_flight_semaphore = dispatch_semaphore_create(MaxBuffersInFlight);
        _command_queue = [_device newCommandQueue];
        view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
        //  頂点情報の登録
        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);
        }
        //  テクスチャ読込+登録<新規>
        MTKTextureLoader* textureLoader = [[MTKTextureLoader alloc] initWithDevice:_device];
        NSDictionary *textureLoaderOptions =
        @{
          MTKTextureLoaderOptionTextureUsage       : @(MTLTextureUsageShaderRead),
          MTKTextureLoaderOptionTextureStorageMode : @(MTLStorageModePrivate)
          };
        _color_image = [textureLoader newTextureWithName:@"colorImage"
                                             scaleFactor:1.0
                                                  bundle:nil
                                                 options:textureLoaderOptions
                                                   error:&error];
        if(!_color_image || error)
        {
            NSLog(@"Error creating texture %@", error.localizedDescription);
        }
    }
    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 setFragmentTexture:_color_image
                                   atIndex:TextureIndexColor];
        //  モデルの設定
        [render_encoder setRenderPipelineState:_pipeline_state];
        [render_encoder setVertexBuffer:_buffer_position
                                 offset:0
                                atIndex:BufferIndexMeshPositions];
        [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

■Steop3:テクスチャをアセットに登録

「Assets.xcassets」に右クリックでメニューを出し「New Texture Set」を選択します。
スクリーンショット 2018-11-30 12.29.06.png
「Texture」が作成されます。
スクリーンショット 2018-11-30 12.29.13.png
今回用意したテクスチャ(Pngファイル)
color.png
テクスチャを「All Universel」にドラッグ&ドロップし名前を「colorImage」に変更します。
スクリーンショット 2018-11-30 12.29.45.png

■Setp4:実行

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

0
0
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
0
0