描画負荷(SetPassCalls/Batches)削減ノウハウ

入稿ルールでは以下のように、1スペースあたりの SetPassCalls と Batches の上限が決められています。
この記事では、これらの値の意味と、unityでの描画負荷の削減方法についてご案内します。

PCワールド、Questワールド

実行時のSetPassCallsの基準値 20
実行時のBatchesの目安基準値 30

※Poppin' Jumpのみ

実行時のSetPassCallsの基準値 120
実行時のBatchesの目安基準値 180

なおこれら基準値は配置先ワールドおよびスペース数によっても変化しますので、必ず入稿ルールを確認していただくようお願いいたします。

入稿ルールはこちら

そもそも SetPassCalls/Batches とは?

おおよその描画負荷を計測したものと捉えていただければ相違ありません。unity の Game ビュー右上の Stats から確認することができます。^1

なおブースの入稿時には VketTools が各ブースの描画負荷を計測します。Game ビューにて確認できる値は参考値として捉えてください。(入稿物以外がカウントに含まれている場合があります)

rendercost

  1. Batches
    • 1フレームあたりの「描画するメッシュをCPUがGPUに指示した回数」です
  2. SetPassCalls
    • 1フレームあたりの「描画するマテリアルをCPUがGPUに指示した回数」です

描画にあたっては、unity は「Batchesにてメッシュを指定し、SetPassCallsにてマテリアルを指定し、DrawCallにて描画する」という手順を踏みます。

これらの値が大きいほど、1フレーム内に描画するものが多い、つまり描画負荷が高いことになります。

削減方針

SetPassCalls や Batches を削減するには『とにかくメッシュを少なくする』『とにかくマテリアルを少なくする』となってしまうのですが、幸いなことに unity 自体の機能やツールなどにより、描画負荷の軽減が可能です。

多くのブースを1ワールド内に収めるため、描画負荷の軽減にご協力をお願いいたします!

How To

  1. Batching Static を設定する
  2. 複数のマテリアルを結合し、1つのマテリアルにする
  3. 複数のメッシュを結合し、1つのメッシュにする
  4. 描画負荷の重いシェーダから軽いシェーダに変更する

ベストプラクティス

『アバター1体を設置し、その周囲にブース構造物を用意する』といったブース構成を考えると、最も容易な案は以下のようになります。

  • 方針として、ブース構造物では描画負荷を抑え、メインであるアバターにリソースを割けるようにする
    • ブース構造物のメッシュを結合し、1メッシュに集約する
    • ブース構造物のマテリアルを結合し、「不透明(Opaque)」と「透過(Transparent)」の2マテリアルに集約する
  • アバター自体のメッシュも可能なかぎり結合する
    • 可能であれば1メッシュ2マテリアルにまで集約したい……
    • 各出展者様にて、いちばん表現したいものに描画リソースを割り当てていただければと思います
  • 最後に、動かないメッシュには Batching Static を設定する

手法その1. Batching Static を設定する

  • 動かないメッシュについては Batching Static にチェックを入れておくと、unity が周囲のメッシュと合わせて『バッチ』を作成するため Batches の軽減に繋がります。
  • ただし Batching を想定していないシェーダの描画がおかしくなることがあるので注意。
    • なぜかというとバッチ化においてメッシュの Transform、特に Rotation と Scale が失われてしまうため。
    • 頂点座標を扱うシェーダ、例えば「アウトライン付きのトゥーンシェーダ」や「ファーシェーダ」などがおかしくなりやすい。
  • Unity Editor では正常に見えているが VRChat 内では表示がおかしくなるといった事例が多いです。そのため 入稿前の実機確認を強く推奨 します。
  • シェーダ側でDisableBatchingをTrueにしているとそのメッシュはバッチの対象とならないため、Batchesの軽減に繋がらないことがあります。

Batching Static の設定は、static 設定のここにあります。

rendercost

手法その2. 複数のマテリアルを結合し、1つのマテリアルにする(テクスチャのアトラス化)

1つのマテリアルで描画すると SetPassCalls の削減に繋がります。また、マテリアルが同一のメッシュはバッチ化されるため Batches の削減に繋がることもあります。
複数のマテリアルをひとつにするには、次の3点が必要です。

  1. マテリアルのシェーダを統一する
  2. マテリアルの設定値を統一する
  3. テクスチャをアトラス化 (複数のテクスチャを1枚に集約し、集約したテクスチャに合わせてメッシュのUVを再構築) する

テクスチャのアトラス化は、次の方法で行うことができます。

  1. Blenderなどの3Dモデリングソフト内でアトラス化する。
  2. Unity内でアトラス化を行うツールを用いる。

手法その3. 複数のメッシュを結合し、1つのメッシュにする(メッシュベイク)

複数のメッシュが結合されひとつのメッシュとなっていれば Batches の削減につなげることができます。

方法

  1. Blenderなどの3Dモデリングソフト内でメッシュを結合する。
  2. Unity内でメッシュを結合するツールを用いる。

手法その4. 描画負荷の重いシェーダから軽いシェーダに変更する

複数回の描画を行うシェーダ(マルチパスシェーダ)では SetPassCall も複数回実行されるため、重いシェーダから軽いシェーダに変更することで描画負荷を削減できることがあります。

削減の例として、「アウトライン付きのトゥーンシェーダ」を使用している場合は「アウトライン無しのバージョン」の使用を検討するのが良いでしょう。これは、一般的にトゥーンシェーダではアウトラインと本体を別のパスで描画しているため、アウトライン機能を使っていないのであれば描画負荷を削減できる可能性があるためです。
アウトラインの幅を0としただけでは描画処理が動いてしまうため、各シェーダに用意された「アウトライン無しのバージョン」を用いると良いでしょう。また描画負荷の軽減のために本来はアウトラインを使っている部分についてアウトラインを削ってしまうといった判断も可能です。

  • MMS3
    • Mnmrshader3 はアウトライン無し、Mnmrshader3_Outline がアウトライン付きです。
  • Reflex Shader2
    • アウトライン無しのシェーダが No Outline 内に用意されています。
  • UnlitWF
    • アウトライン有りのシェーダは _Outline と名称が付けられています。
  • UTS
    • アウトライン無しのシェーダが NoOutline 内に用意されています。

^1: ちなみに以下の値はたまたま開いていたVRCアバター1体分のStatisticsです。つまりこのアバター1体を描画するコストはブース2~3個分を描画するコストとほぼ同じです。