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

Objective-cでMetalを使用して色加算をしよう

More than 1 year has passed since last update.

ブレンドモードで色加算を実現する覚書
「Objective-cでMetalを使用してテクスチャを表示しよう」を参照
https://qiita.com/sanoh/items/d947dba6514a1f8713bc

■Setp1: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;
        //  ブレンドモードの設定(色加算)<新規>
        descriptor.colorAttachments[0].blendingEnabled=true;
        descriptor.colorAttachments[0].rgbBlendOperation=MTLBlendOperationAdd;
        descriptor.colorAttachments[0].alphaBlendOperation=MTLBlendOperationAdd;
        descriptor.colorAttachments[0].sourceRGBBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].sourceAlphaBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].destinationRGBBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].destinationAlphaBlendFactor= MTLBlendFactorOne;

        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 

■解説

なにも設定しないと、アルファは「false」の設定

        //  ブレンドモードの設定(色加算)
        descriptor.colorAttachments[0].blendingEnabled=true;
        descriptor.colorAttachments[0].rgbBlendOperation=MTLBlendOperationAdd;
        descriptor.colorAttachments[0].alphaBlendOperation=MTLBlendOperationAdd;
        descriptor.colorAttachments[0].sourceRGBBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].sourceAlphaBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].destinationRGBBlendFactor=MTLBlendFactorOne;
        descriptor.colorAttachments[0].destinationAlphaBlendFactor= MTLBlendFactorOne;

■Setp2:実行

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

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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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