Unity 5.4から搭載されるGPU Instancingで遊んでみます。
GPU Instancingは、複数の「同一メッシュ」かつ「同一マテリアル」なオブジェクトがあった場合に、GPU側で一括で描画してくれる技術みたいです。
扱いにかなりクセがありますが、上手く使えば面白い事が出来るかもしれません。
似たような技術にバッチングがありますが、あちらはCPU側で纏めて描画するのに対し、GPU InstancingはGPU側で纏めて処理を行う事に違いがありそうです。
上の左の絵はGPU Instancingを使用せず色違いのメッシュを大量に配置した場合。右はGPU Instancingを使用した場合です。SetPass Callの数が明らかに異なります。
GPU Instancingを試す
GPU Instancingを試してみます。
まずはGPU Instancingに対応しているシェーダーを用意します。Assets>Create>Shader>StandardSurfaceShader(Instanced) でGPU Instancing対応の、通常のシェーダーとは少し異なるシェーダーが作れます。
後は作成したシェーダーを使用してオブジェクトを描画すると、GPUが纏めて描画してくれます。
GPU InstancingはGraphics.DrawMeshとMeshRendererで使えるみたいです。
GPU Instancingできているか確認する
GPU Instancingができているか確認する手っ取り早い方法は、Frame Debuggerを使用することです。
GPU Instancingで描画されているものは、Draw MeshにInstancedと表示されます。またProfilerのRendererの項目でも新しくInstancedの項目が追加されており、ここからもどの程度纏められているかを確認出来ます。
色を変更したい
GPU Instancingで纏めて描画出来るオブジェクトは「メッシュが同じ」かつ「マテリアルが同一」なオブジェクトです。もしオブジェクトの色を変更したい場合、MaterialPropertyBlockを使用します。
上のコードは、指定したレンダラーの色を一括で更新するサンプルです。これでマテリアルを増やさずシェーダーの色を変更しました。
アニメーションしたい
こうなるとアニメーションを行いたくなりますが、残念ながらGPU InstancingはSkined Mesh Rendererに対応していません。
ので、SkindMeshRendererで変形させたメッシュを取得してMeshRendererに流し込んでやります。
下のアニメーションは3パターンのアニメーションをランダムに再生したものです。数が多くなると基礎となるメッシュを配布した方が全モデルにアニメーションさせるより遥かに安いです。
Robot Kyle * 7000 #unity pic.twitter.com/4CK0gEkgzl
— 椿 (@tsubaki_t1) 2016年6月28日
まあ、メインキャラクターには絶対使えませんが、街に居る(少し離れた)モブとかには使っても良いかもしれません。
ちなみにコレ、別にGPU Instancingでない場合もかなり安いです。
手前の3体がアニメーションの元となる動き、奥のキャラクター達はそのコピーです。分かりやすいように、走ってるモデルは緑、歩いてるモデルは青、アイドルモーションは赤としてみました。
GPU Instancingが使えない条件
GPU Instancingですが、使えない条件が結構あります。
- LightprobeやLightmap、ReflectionProbeの影響下にある事
- ForwardRenderingで複数のライトから照らされている事
- 使用出来るのはMeshRendererとGraphics.DrawMeshのみ。
その他のCanvasRendererやSkindMeshRendererやParticleRendererには使えない。 - Direct 11~12、OpenGL 4.1以降、コンソールの一部で使用可能。Metalは以降
そりゃそうなんですが、描画時にGPUへ渡さなきゃいけない情報の多い表現には使用できないので、まぁ何というか、使いドコロに悩むですはい。