Unity のレンダリング パイプライン
Replaced Shadersでのレンダリング

シェーダを書く場合のパフォーマンスのヒント

常識を使う ;)

必要なものだけ計算します。実際に必要ないものは全て省くことが出来ます。例えば,各マテリアルごとのカラーをサポートするのはシェーダを柔軟にするには良いですが,いつもカラーが白のままならば,画面上で頂点またはピクセルごとのレンダリングのために計算するのは無駄です。

もう一つ頭に入れておくべきことは計算の頻度です。通常,ピクセル(ピクセルシェーダとして実行)のほうが頂点(頂点シェーダとして実行)より多くのがレンダリングされ,さらに頂点ほうがオブジェクトより多くレンダリングされます。このため,一般的にはできることならば,ピクセルシェーダの計算を頂点シェーダに移動する,あるいはシェーダから計算を完全に除いてスクリプトから値をセットするようにします。

汎用サーフェイスシェーダを減らす

Surface Shaders はライティングと相互作用するシェーダを書く場合に優れています。しかし,これらのデフォルトのオプションは“一般的なケース” 向けに有効化されてます。多くの場合,それを微調整することでシェーダの実行を速くするか,せめて小さくすることが出来ます。

  • approxview ディレクティブは,ビュー方向を使用するシェーダ(鏡面)のためにあり,ピクセルごとでなく頂点ごとにビュー方向を正規化します。概算ですが,通常はこれで十分です。
  • halfasview は鏡面シェーダタイプをさらに早くします。Half-vector(ライティング方向とビューベクトルの中間)が計算され頂点ごとに正規化され,lighting function (ライティングの関数)はあらかじめ,中間ベクトルをビューベクトルの代わりに,引数として受け取ります。
  • noforwardadd によりシェーダは,Forward Renderingで指向性ライトのみ完全にサポートします。残りのライトは,頂点ライトや球面調和としてのエフェクトを,引き続き表現することが出来ます。これはシェーダを小さくすることに優れていて,複数のライトが存在していても,常にひとつのパスでレンダリングされます。
  • noambient により,シェーダの環境光ライティングおよび球面調和を,無効化しますこれによりわずかに速くなります。

計算の精度

Cg/HLSLでシェーダを書く場合,3つの基本的な数値タイプがあります:float ,half ,およびfixed (更に,これらのベクトルやマトリクスの変種,すなわちhalf3およびfloat4x4)です。

  • float: 高い精度の浮動小数点数。通常32ビット,すなわち一般的なプログラミング言語のfloatと同様。
  • half: 中程度の精度の浮動小数点数。通常16ビット,–60000から+60000まで十進数にして3.3桁の精度。
  • fixed: 低い精度の固定小数点数。通常11ビット,–2.0から+2.0まで1/256の精度。

できるかぎり低い精度を使用します。これはiOSやAndroidなどモバイルプラットフォームでは特に重要です。経験則から:

  • カラーや単位長ベクトルについてはfixed を使用します。
  • その他については,範囲と精度が十分であればhalf を使用し,そうでなければfloat を使用します。

モバイルプラットフォームについて,鍵はフラグメントシェーダで,出来うるかぎり低い精度を維持することをチェックすることです。ほとんどのモバイルGPUでは,低い精度(fixed/lowp)にswizzle演算の適用するのは高価です。同様にfixed/lowpと高い精度のタイプの変換は相当に高価です。

アルファテスト

Fixed function(固定関数)のAlphaTest ,またはそのプログラマブル同等物であるclip() は,異なるプラットフォームで異なるパフォーマンス特性を示します:

  • 一般的に,ほとんどのプラットフォームで,完全に透過のピクセルをカリングするのに使用するのは小さい利点があります。
  • しかし,iOSといくつかのAndroidデバイスでみられるPowerVR GPUでは,アルファテストは高価です。この場合は,かえって遅くなるため,“パフォーマンス最適化” として使用しません。

カラーマスク

いくつかのプラットフォーム(ほとんどがiOSとAndroidデバイスでみられるモバイルGPU)では,ColorMask を使用してチャネルを除くこと(すなわちColorMask RGB )は,高価であり,本当に必要な場合のみ使用して下さい。

Unity のレンダリング パイプライン
Replaced Shadersでのレンダリング