Version: 2023.1
言語: 日本語
ビルトインレンダーパイプラインのレンダリングパス
ディファードシェーディングレンダリングパス

フォワードレンダリングパス

このページでは、Unity のビルトインレンダーパイプラインのフォワードレンダリングパスについて説明します。

フォワードレンダリングは各オブジェクトを 1 つ、または複数のパスで描画します。パス数は、オブジェクトに作用するライトによって決まります。フォワードレンダリングによるライトの扱いも、ライトの設定と強度によって異なります。

実装に関する詳細

フォワードレンダリングでは、各オブジェクトに影響を与える最も明るいライトのいくつかが完全にピクセルごとのライティングモードでレンダリングされます。次に、頂点ごとに 4 つまでのポイントライトが計算されます。他のライトは球面調和関数 (SH) として計算されます。これははるかに高速ですが、近似にすぎません。ライトはピクセルごとのライトになるかどうかは、以下によって決まります。

  • Render Mode (レンダーモード) を Not Important (重要ではない) に設定したライトは常に頂点単位か、球面調和 として計算されます。
  • 最も明るいディレクショナルライトは常にピクセル単位に計算されます。
  • Render Mode を Important (重要) に設定したライトは常にピクセル単位に計算されます。
  • 上記の結果、現在の Pixel Light Count Quality Setting よりライトの数が少ない場合は、明るさが大きいものから順に、ピクセルごとにより多くのライトがレンダリングされます。

各オブジェクトのライティングは以下のように行われます。

  • 1 つのピクセル単位のディレクショナルライトと、すべての頂点単位や球面調和によるライトにベースパスが適用されます。
  • 他のピクセル単位のライトは、加算パスでレンダリングされ、各ライトに 1 つのパスが使用されます。

例えば、複数のライトから影響を受けるオブジェクト (下の図の円の部分。ライト A から H のすべてから影響を受けます) について考えてみましょう。

ライト A から H が同じ色と強度を持ち、すべての Render Mode が Auto に設定されている(レンダリングモードが自動である) と仮定すると、このオブジェクトに関して、この順番のとおりにソートされます。まず、最も明るいライト (A から D) はピクセル単位のライティング (Per-pixel)、それから、4 つのライト (D から G) は頂点単位のライティング (Per-vertex)、最後に残りのライト (G から H) が球面調和によるライティング (SH) でレンダリングされます。

ライトのグループは重複していることに注意してください、例えば最後のピクセル単位のライトは頂点単位のライティングモードにブレンドするため、オブジェクトやライトが動き回る際に、急なライトの変化は少なくなります。

ベースパス

ベースパスでは、1つのピクセル単位のディレクショナルライトとすべての球面調和/頂点ライトでオブジェクトをレンダリングします。このパスにはさらに、シェーダーからのライトマップ、アンビエントライティング、エミッシブライティングすべてが追加されます。このパスでレンダリングされるディレクショナルライトには影があります。ライトマップを適用したオブジェクトは球面調和ライトから照明されないことに注意してください。

OnlyDirectional pass flag がシェーダーで使用されると、フォワードベースパスは、メインのディレクショナルライト、アンビエント/ライトプローブ、ライトマップだけをレンダリングします (球面調和と頂点ライトはパスデータに含まれません)。

加算パス

加算パスは、オブジェクトに影響する追加のピクセル単位ライトごとにレンダリングされます。 multi_compile_fwdadd_fullshadows バリアントショートカットを使用しない限り、これらのパスのライトにはデフォルトでは影がありません(その結果、フォワードレンダリングで影があるのは 1つのディレクショナルライトのみです)。

パフォーマンスの考慮点

ピクセル単位のライト

動的なピクセル単位のライティングでは、影響する全てのピクセルにレンダリング作業が追加されるので、オブジェクトをマルチパスでレンダリングする事になります。モバイルや ローエンド PC の GPU など処理能力の低いデバイスでは、オブジェクトを複数の ピクセルライト で照らすことは避け、毎フレームライティングを計算する代わりに、ライトマップを使用して静的なオブジェクトをライティングしてください。動的な頂点単位のライティングも、頂点をトランスフォームすると顕著にコストが増加します。複数のライトでオブジェクトを照らすことは、なるべく避けるようにしてください。

様々なピクセルライトで照らすために、十分距離を置いているメッシュをまとめることは避けてください。ピクセルライトを使用するとき、各メッシュはそれを照らすピクセルライトの数だけレンダリングされなければなりません。とても距離のある 2 つのメッシュをまとめると、まとめたオブジェクトの有効サイズが増加します。レンダリングのときには、ひとまとめにしたオブジェクトのあらゆる部分を照らしているピクセルライトすべてが考慮されます。そのため、必要なレンダリングパスの数は増加します。一般的に、まとめられたオブジェクトをレンダリングするために必要なパスの数は、離れたオブジェクトそれぞれのパスの合計数で、メッシュをまとめても何の意味もありません。

レンダリング中、Unity はメッシュの周囲のすべてのライトを見つけ、メッシュに最も影響するライトを計算します。Quality ウィンドウの設定が、ピクセルライトとして使用するライトの数と、頂点ライトとして使用するライトの数の変更に使用されます。各ライトは、メッシュからの距離、ライトの強さに基づいて重要度が計算されます。ライトの中には、純粋にゲームのコンテキストのために他よりもずっと重要なものがあります。このため、すべてのライトには Render Mode 設定があり、Important または Not Important に設定することができます。 Not Important に設定されたライトのレンダリングオーバーヘッドは低くなります。

例としてカーレースのゲームで、プレイヤーの車が暗闇の中でヘッドライトをつけて走っているとします。ヘッドライトはもっとも重要な光源となるため、Render Mode はおそらく Important に設定されます。逆に、ゲームの中で重要性がやや劣るライト (他の車のバックライト、街灯柱、等) およびピクセルライトにしてもビジュアル効果が改善されないライトがあります。それらのライトの Render ModeNot Important に無難に設定することで、効果が薄いところに無駄なレンダリングコストを消費することを避けます。

ピクセル単位のライティングの最適化は CPU と GPU の両方を節約します。CPU が処理するドローコールが減り、GPU が処理する頂点数と、余分なオブジェクトレンダリングでラスタライズするピクセル数が減ります。

球面調和ライト

球面調和ライトは 非常に 速くレンダリングされます。CPU のコストがごくわずかであり、GPU を適用する場合も 事実上コストなし です (つまり、ベースパスは常に球面調和ライティングを計算しますが、球面調和ライトの性質から、球面調和ライトの数にかかわらずコストはまったく同じです)。

球面調和ライトには以下のような欠点があります。

  • 球面調和ライトはオブジェクトのピクセルでなく、頂点で計算されます。つまり、ライトのクッキーや法線マップはサポートしません。
  • 球面調和ライトは非常に低周波です。そのため、急なライティングを変化させることができません。また、拡散ライティングにしか作用しません (スペキュラーハイライトには低周波すぎます)。
  • 球面調和ライティングは局所的ではありません。つまり、球面調和ライトで表面に近い、ポイントあるいはスポットライトを作成すると、見た目に違和感があります。

まとめると、球面調和ライトは小さい動的オブジェクトにはだいたい十分です。

ビルトインレンダーパイプラインのレンダリングパス
ディファードシェーディングレンダリングパス