z Metal-cpp 04 : Draw Multiple Instances of an Object :: C++, 그래픽 기술 블로그

 간략하게 소개를 하자면, 동일한 mesh를 공유하는 여러 물체를 그릴 때, 하나씩 draw를 호출하여 그리는 것보다 한번의 draw에 동일한 물체들을 한번에 다 그리는 것이 더 효율적입니다. 렌더러는 각 개체에 대한 위치 및 색을 따로 보관하고, 이를 적용하여 그릴 수 있습니다. 먼저 instancedatabuff부터 만들어, 각 개체가 가진 고유한 특성을 저장하게 해야합니다.

for ( size_t i = 0; i < kMaxFramesInFlight; ++i )
{
    _pInstanceDataBuffer[ i ] = _pDevice->newBuffer( instanceDataSize, MTL::ResourceStorageModeManaged );
}

 그 후에, 필요한 데이터를 _pInstanceDataBuffer에 적절하게 채워넣어 줍니다. 그 후에 이를 setVertexBuffer로 등록을 하고, draw 함수를 호출할 때 drawIndexedPrimitives를 호출하여, indexbuffer가 사용한 draw 함수를 호출해야 합니다.

pEnc->setVertexBuffer( pInstanceDataBuffer, /* offset */ 0, /* index */ 1 );
pEnc->drawIndexedPrimitives( MTL::PrimitiveType::PrimitiveTypeTriangle,
                            6, MTL::IndexType::IndexTypeUInt16,
                            _pIndexBuffer,
                            0,
                            kNumInstances );

이를 vertex function에서 사용할 때는 다음과 같이 사용합니다.

v2f vertex vertexMain( device const VertexData* vertexData [[buffer(0)]],
                       device const InstanceData* instanceData [[buffer(1)]],
                       uint vertexId [[vertex_id]],
                       uint instanceId [[instance_id]] )
{
    v2f o;
    float4 pos = float4( vertexData[ vertexId ].position, 1.0 );
    o.position = instanceData[ instanceId ].instanceTransform * pos;
    o.color = half3( instanceData[ instanceId ].instanceColor.rgb );
    return o;
}

[[instance_id]] 한정자는 실행시간에 개체값을 가지며, 이는 instanceDataBuffer에서 값을 가져오는데 활용됩니다.

+ Recent posts