Unityで行うGPU instancingについて
はじめに
UnityではInstancingの方法が何パターンかあります.Instancing自体はそこまでハードルが高いものではありませんが,毎回1から書くのはめんどくさいと思うので,簡単なインスタンシングを実装したプロジェクトを作りました.よかったらGitHubからcloneしてみてください.(Instancing_Surfの中身を見てみてください)また今回はComputeShader, ComputeBufferを平行して使用することを前提としております.
コード解説(C#)
Graphics.DrawMeshInstancedIndirect(Mesh instanceMesh, int subMeshIndex, Material instanceMaterial, Vector3 bounds, ComputeBuffer argsBuffer);
Graphics.DrawMeshInstancedIndirect(Mesh instanceMesh, int subMeshIndex, Material instanceMaterial, Vector3 bounds, ComputeBuffer argsBuffer);
このメソッドを用いることでInstancingを行うDrawCallを発行するすることが出来ます.これからひとつずつ必要な引数のデータについて見て行きましょう.
- Mesh instanceMesh : InstansingしたいMesh
- int subMeshIndex : 何番目のsubMeshかを指定する.
- Material instanceMaterial : Instansingするmeshに適応させるShader
- ComputeBuffer argsBuffer : InstancingするためのMesh情報を詰め込んだ配列情報.(↓を参考にしてみてください)
argsBuffer = new ComputeBuffer (int count, int stride, ComputeBufferType type);
args[0] = (uint)instanceMesh.GetIndexCount(subMeshIndex);
args[1] = (uint)instanceCount;
args[2] = (uint)instanceMesh.GetIndexStart(subMeshIndex);
args[3] = (uint)instanceMesh.GetBaseVertex(subMeshIndex);
argsBuffer.SetData(args);
コード解説(Shader)
Shader側ではVertexShader+FragmentShader
とVertexShader+Surface Shader
の2つの型があります.
VertexShaderとFragmentShaderを用いる方法
実行画像
Target
Shaderは使用するバージョンによってGeometryやComputeShaderが使える使えないなど,使用出来る機能に差があります.Targetを指定することで,どのバージョンのShaderを使用するかを決定することが出来ます.
Targetについてはここに詳しく書かれていますが,#pragma target4.5
以上にすることでComputeShader,つまりComputeBufferを使用することが可能です.(今回はComputeShaderを使用するのでこの設定で)
VertexShader
変換について
VertexShaderではComputeBufferに詰められた情報をもとに座標変換を行います.またここでの変換は通常の変換通り,Projection座標系までの変換を行います.
InstanceIDの取得
Instanceをした際には個々のユニークなIDを取得することが出来ます.例えば,1万個MeshをInstanceした際には座標などを格納するComputeBufferも同じ数だけ用意し,このIDを頼りにアクセスしていけば個々の座標を動かしたり..みたいなことが出来ます.
以下の例ではVertexShaderの引数にuint instanceID : SV_InstanceID
を渡すことで参照可能となります.
#if SHADER_TARGET >= 45
StructuredBuffer<float4> positionBuffer;
#endif
//====================================================
//省略
//====================================================
v2f vert(appdata_full v, uint instanceID : SV_InstanceID)
{
#if SHADER_TARGET >= 45
float4 data = positionBuffer[instanceID];
#else
float4 data = 0;
#endif
v2f o;
float3 localPosition = v.vertex.xyz * data.w;
float3 worldPosition = data.xyz + localPosition;
o.vertex = mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f));
return o;
}
FragmentShader
fixed4 frag(v2f i) : SV_Target
{
return _Color;
}
Author And Source
この問題について(Unityで行うGPU instancingについて), 我々は、より多くの情報をここで見つけました https://qiita.com/keito_takaishi/items/b07709ca3f760d067409著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .