📝 ASP における各シェーダーのパフォーマンスについて
ASP/Character と ASP/Eye の Static Branching
ASP の character shader と eye shader は、どちらも forward rendering の shader です。
また、開発時には shader keyword を厳密に使い、機能ごとの static branching を行っています。
たとえば ASP/Character を使用しているマテリアルで、rim lighting カテゴリ内の fresnel rim light や depth-based rim light を使っていない場合、そのマテリアルは runtime 中に rim lighting 関連の計算を一切行いません。同様に、テクスチャ property も使用していなければサンプリングは発生しません。
そのため、1 つのマテリアルで有効になっている機能が少ないほど、runtime の負荷は小さくなります。
Texture Sampling Count(重要)
一般的に Shader を最適化する際は、各 frame で GPU に渡すテクスチャ数をできるだけ減らし、skinned mesh のマテリアル数を減らしたうえで、異なるマテリアルのテクスチャを 1 枚の atlas にまとめるのが理想です。 理論上は、部位ごとに異なる ramp map を 1 枚の ramp map atlas にまとめ、別の lookup texture や vertex color で UV を制御することもできます(この手法は一部のモバイルゲーム、たとえば原神などでよく見られます)。 ただし、この方法はプロジェクトごとの要件に合わせた厳密な制作フローと運用ルールが必要です。ASP は複数のプロジェクトで使われるプラグインであり、利用上の柔軟性を保つために特定の制作フローを強制していません(唯一の例外は PBR テクスチャのチャンネルです)。 各マテリアルがそれぞれ独立したテクスチャを使う構成では、bandwidth overhead が大きくなります。これはモバイルや VR / Switch のようなプラットフォームの GPU には不向きなため、ASP の既定ターゲットは一貫して PC のみです。
💡 プロジェクト要件に応じたテクスチャ統合の仕組みを作ること自体は、それほど複雑ではありません。モバイルなどのプラットフォームをターゲットにしているチームであれば、ASP の shader をトゥーンレンダリングの土台として使い、独自に改造・拡張することも可能です。
ASP Shadow Map のパフォーマンス
キャラクターのみを個別に描画する ASP Shadow Map は、最大 4 段の cascade shadow map に対応しています。
Cascade shadow map は、いわば影の LOD のようなものです。shadow map を複数の小さな tile に分割し、それぞれを異なる影距離で描画します。
cascade count を増やすことで、shadow map resolution を小さく保ったまま、距離ごとにより安定した影品質を得られます。

一個2層cascsade的shadow map
ただし、cascade が 1 段増えるごとに draw call も 1 回増えます。4 段 cascade の worst case では、キャラクターを shadow map に 4 回描画する必要があります。さらに、キャラクター用 mesh は面数が多い傾向があり、skinned mesh 自体も CPU 側の overhead が高いため(ボーン計算は高コスト)、多段 cascade は CPU bound を招きやすくなります。
💡 ゲームプロジェクトで人物描画に使う skinned mesh renderer 自体が、もともと計算コストの高いオブジェクトであることを忘れないでください。
| 状況 | 推奨設定 |
|---|---|
| CPU bound だが bandwidth に余裕がある | Cascade Count を下げ、できるだけ 1 または 2 にします。その代わり、より大きい shadow map resolution(2048x2048 など)を使用できます。 |
| Bandwidth bound | shadow map resolution を下げます。 |
| 性能を最優先したい | 1 段 cascade を使用し、shadow map resolution を下げます。同時に clip distance を短くして近距離の影品質を上げ、高めの shadow fade ratio を使ってカメラが離れたときに影をフェードさせます。さらに遠距離では、偽の blob shadow へ切り替える構成が有効です(現在 ASP には含まれていません)。 |
Mesh Outline / Depth Offset Shadow
Mesh ベースの outline pass と Depth Offset Shadow pass は、通常の draw call と同じように扱われます(もちろん、これらの pass の per-pixel 計算量自体は非常に低いです)。そのため、これらの pass の実行時間は、描画対象となるオブジェクト数や複雑さにほぼ比例します。
したがって、Rendering Layer Mask を積極的に使い、これらの pass に描画されるオブジェクトを制御して、対象 renderer 数をできる限り減らしてください。
ポストプロセス Shader(スクリーンスペース輪郭線、Tone Mapping)
RTX 3060 Laptop 上での、ASP のポストプロセス pass と Unity の SSAO pass のパフォーマンス比較です。
| ポストプロセス効果 | 実行時間 |
|---|---|
| Unity SSAO | 0.6ms~0.95ms |
| ASP Screen Space Outline | 画面上でキャラクターが占める pixel 数に依存し、通常は 0.4ms~0.5ms、worst case では 0.95ms |
| ASP ToneMapping | 0.2ms |
スクリーンスペース輪郭線の計算では、エッジの細部を最大限に検出するために、_CameraDepthTexture と _CameraNormalTexture を複数回サンプリングし、Material Pass の RT も参照します。 ASP のエッジ検出におけるサンプリング回数は Sobel operator の半分以下ですが、検出できるディテールは Sobel operator と同等以上です。 また、不要なサンプリングを避けるため、スクリーンスペース輪郭線 shader はまず現在の pixel がキャラクターかどうかを判定し、キャラクターでなければ後続の計算をスキップします。 つまり、キャラクターが画面内に占める割合が小さいほど、節約できるパフォーマンスは大きくなります。
screen space outline の volume override には、輪郭線のみに FXAA を 1 回適用して品質を向上させるオプションもあります。FXAA は現代の PC では非常に低コストなので、有効化を推奨します。
Profiling 結果
以下は、RTX 3060 Laptop で 9 体のキャラクター(36 個の Skinned Mesh Renderer)がいるシーンを計測した nsight frame capture です。


Project Setting : Script Backend - Mono
Graphics API : DX 12
GPU Skinning : ON
Graphics Jobs : OFF
| ポストプロセス効果 | 占有 Frame Time |
|---|---|
| Unity SSAO | 0.61ms |
| ASP Shadow Map(Character-Only) | 0.07ms |
| Draw OpaquesObjects | 0.45ms |
| ASP Tone Map Pass | 0.27ms |
| ASP Screen Space Outline | 0.61ms |
| Render Post Processing(Bloom..etc) | 0.35ms |
| Total Frame Time | 3.37ms (~270FPS) |
Draw OpaquesObjects の実行時間は、mesh の数と複雑さ、面数、そして draw call 数の影響を受けます。
mesh の複雑さによる影響を除くと、ASP Screen Space Outline は ASP の shader 群の中でも比較的高コストです。Outline + ToneMapping は 3060 Laptop 環境で合計およそ 0.8~1ms かかります。