読者です 読者をやめる 読者になる 読者になる

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】GPU Instancingで遊ぶ

3D Unity シェーダー

Unity 5.4から搭載されるGPU Instancingで遊んでみます。

docs.unity3d.com

GPU Instancingは、複数の「同一メッシュ」かつ「同一マテリアル」なオブジェクトがあった場合に、GPU側で一括で描画してくれる技術みたいです。

扱いにかなりクセがありますが、上手く使えば面白い事が出来るかもしれません。

似たような技術にバッチングがありますが、あちらはCPU側で纏めて描画するのに対し、GPU InstancingはGPU側で纏めて処理を行う事に違いがありそうです。

f:id:tsubaki_t1:20160628215025j:plain

上の左の絵はGPU Instancingを使用せず色違いのメッシュを大量に配置した場合。右はGPU Instancingを使用した場合です。SetPass Callの数が明らかに異なります。

GPU Instancingを試す

GPU Instancingを試してみます。
まずはGPU Instancingに対応しているシェーダーを用意します。Assets>Create>Shader>StandardSurfaceShader(Instanced) GPU Instancing対応の、通常のシェーダーとは少し異なるシェーダーが作れます。

f:id:tsubaki_t1:20160628215458j:plain

f:id:tsubaki_t1:20160628220700j:plain

後は作成したシェーダーを使用してオブジェクトを描画すると、GPUが纏めて描画してくれます。
GPU InstancingはGraphics.DrawMeshとMeshRendererで使えるみたいです。

GPU Instancingできているか確認する

GPU Instancingができているか確認する手っ取り早い方法は、Frame Debuggerを使用することです。
GPU Instancingで描画されているものは、Draw MeshにInstancedと表示されます。またProfilerのRendererの項目でも新しくInstancedの項目が追加されており、ここからもどの程度纏められているかを確認出来ます。

f:id:tsubaki_t1:20160628221059j:plain

f:id:tsubaki_t1:20160628221331j:plain

色を変更したい

GPU Instancingで纏めて描画出来るオブジェクトは「メッシュが同じ」かつ「マテリアルが同一」なオブジェクトです。もしオブジェクトの色を変更したい場合、MaterialPropertyBlockを使用します。

gist.github.com

上のコードは、指定したレンダラーの色を一括で更新するサンプルです。これでマテリアルを増やさずシェーダーの色を変更しました。

f:id:tsubaki_t1:20160628221853j:plain

アニメーションしたい

こうなるとアニメーションを行いたくなりますが、残念ながらGPU InstancingはSkined Mesh Rendererに対応していません。

ので、SkindMeshRendererで変形させたメッシュを取得してMeshRendererに流し込んでやります。
下のアニメーションは3パターンのアニメーションをランダムに再生したものです。数が多くなると基礎となるメッシュを配布した方が全モデルにアニメーションさせるより遥かに安いです。

 まあ、メインキャラクターには絶対使えませんが、街に居る(少し離れた)モブとかには使っても良いかもしれません。

ちなみにコレ、別にGPU Instancingでない場合もかなり安いです。

手前の3体がアニメーションの元となる動き、奥のキャラクター達はそのコピーです。分かりやすいように、走ってるモデルは緑、歩いてるモデルは青、アイドルモーションは赤としてみました。

f:id:tsubaki_t1:20160629004702j:plain

 GPU Instancingが使えない条件

GPU Instancingですが、使えない条件が結構あります。

  • LightprobeやLightmap、ReflectionProbeの影響下にある事
  • ForwardRenderingで複数のライトから照らされている事
  • 使用出来るのはMeshRendererとGraphics.DrawMeshのみ。
    その他のCanvasRendererやSkindMeshRendererやParticleRendererには使えない。
  • Direct 11~12、OpenGL 4.1以降、コンソールの一部で使用可能。Metalは以降

そりゃそうなんですが、描画時にGPUへ渡さなきゃいけない情報の多い表現には使用できないので、まぁ何というか、使いドコロに悩むですはい。

関連

forum.unity3d.com

docs.unity3d.com

docs.google.com