HD レンダーパイプラインのシャドウ
HD レンダーパイプライン (High Definition Render Pipeline、HDRP) の ライト は、1 つのゲームオブジェクトから別のゲームオブジェクトへ、シャドウを作ることができます。ゲームオブジェクトの位置とスケールが明確になるため、シャドウがなければ平坦に見えてしまうシーンに、奥行きと現実感が生まれます。
シャドウマップ解像度
ライトのシャドウマップの解像度は、シャドウマップのサイズを決定します。シャドウマップが大きいほどシャドウの正確性が増し、シャドウを投影しているジオメトリの小さなディテールを、HDRP がより的確にキャプチャできます。シャドウマップをより高い解像度でレンダリングすると、外観がよりシャープになります。
特定のライトのシャドウマップの解像度は、Light コンポーネントの Shadows セクションで設定します。
HDRP がライトごとにレンダリングするシャドウマップの数は、ライトの Type によって異なります。
- スポットライトがレンダリングするシャドウマップは 1 つです。
- ポイントライトがレンダリングするシャドウマップは 6 つです (キューブマップの面数)。
- ディレクショナルライトはカスケードごとに 1 つのシャドウマップをレンダリングします。ディレクショナルライトのカスケード数は、シーンの ボリューム の HD シャドウ設定 から設定します。デフォルト値は、4 カスケードです。
HDRP はシャドウマップの動的リスケールを実行して、シャドウアトラス内のスペース使用量を最大限にすることができますが、同時にシーンの小規模を占めるライトのパフォーマンスインパクトを減少させます。具体的には、ライトが占める画面エリアの大きさに応じ、HDRP がライトのシャドウマップ解像度を低くします。画面のエリアが小さいほど、HDRP は Light コンポーネント で設定された値から解像度を低くします。この機能を有効にするには、Unity プロジェクトの HDRP Asset の Shadow セクションへ移動して、HDRP に動的にシャドウマップをリスケールさせたいシャドウアトラスの Dynamic Rescale プロパティーを有効にします。 HDRP はキャッシュされたシャドウマップの動的リスケールはサポートしません。
シャドウアトラス
HDRP はフレームに対するすべてのリアルタイムシャドウを、シャドウマップアトラスを使って パンクチュアルライト シャドウすべてにレンダリングします。ディレクショナルライトのシャドウには、別のシャドウマップアトラスを使います。
これらのアトラスは、Unity プロジェクトの HDRP Asset で設定します。アトラスのサイズは、シーン内のシャドウの最大解像度を決定します。
例えば、あるアトラスのデフォルトサイズが 4096 x 4096 の場合には以下に一致します。
- 1024 x 1024 ピクセルのシャドウマップが 16。
- 2048 x 2048 のシャドウマップ 2 つ、1024 x 1024 のシャドウマップ 4 つ、512 x 512 のシャドウマップ 8 つ、そして 32 の 256 x 256 のシャドウマップ。
画面上のシャドウマップ最大数を制御する
アトラスの他にも、HDRP が単一フレームでレンダリングするシャドウマップの最大数を設定することができます。この手順はまず、Unity プロジェクトの HDRP Asset を開いて Shadows セクションへ移動し、Max Shadows on Screen 値を入力します。画面上のシャドウマップ数がこの限度を超えている場合、HDRP はそれらをレンダリングしません。
シャドウバイアス
シャドウマップは基本的に、ライトの視点から投影されるテクスチャです。HDRP は投影内のバイアスを利用して、シャドウを作るジオメトリがそれ自体にシャドウを作らないようにします。
HDRP では、各 Light コンポーネントが以下のパラメーターを使って、それぞれのシャドウバイアスを制御します。
- Near Plane
- Slope-Scale Depth Bias
- Normal Bias
これらの設定は Shadows セクションの下にあります。プロパティーフィールドが見つからない場合は、その他のオプション 歯車をクリックしてください。各プロパティーがシャドウバイアスを具体的にどのように制御するかについては、ライトに関するドキュメント を参照してください。
シャドウバイアス値を高くすると、メッシュから光が "漏れる" 場合があります。これはシャドウと影を作るものの間に目に見えるギャップがあり、影を作るキャスターの形を正しく表現しない影になります。
シャドウフィルタリング
シャドウマップをキャプチャした後、HDRP は低解像度のシャドウマップで発生するエイリアシングエフェクトを減少させるために、マップでフィルタリングを行います。フィルターはそれぞれ、シャドウの知覚的なシャープネスに影響します。
使用するシャドウフィルター品質を変更するには、Unity プロジェクトの HDRP Asset で、Filtering Quality プロパティーを変更します。品質が高いと、GPU パフォーマンスに影響します。 現在、ディレクショナルライトおよびパンクチュアルライトに、3 つのフィルター品質プリセットがあります。利用可能なフィルター品質に関する情報は、Filtering Qualities 表 を参照してください。
シャドウマスク
HDRP は以下の 2 つの 混合ライティングモード をサポートします。
シャドウマスクの有効化
HDRP でシャドウマップを使うためには、Unity プロジェクトの HDRP Asset でシャドウマスクサポートを有効にしてから、Frame Settings で Cameras がシャドウマスクを使うようにしなければなりません。
- Render Pipeline Supported Features の下で、Shadowmask チェックボックスを有効にします。これで Unity Project でシャドウマスクがサポートされます。
- 次に Cameras がシャドウマップを使うようにしなければなりません。HDRP Asset で Default Frame Settings > Lighting へ移動し、Shadowmask チェックボックスを有効にして Cameras がデフォルトでシャドウマスクを使うようにします。
HDRP 内の特別設定
フレキシブルなライティング設定を実現するため、HDRP ではシャドウマスクがそれぞれのライトにどのように動作するかを選択することができます。シャドウマスクの動作は、ライトの Shadowmask Mode を変更して変えることができます。ライトの Mode を Mixed に設定して、Shadows セクションの Shadow Map ドロップダウンで Shadowmask Mode を展開します。
Shadowmask Mode | 説明 |
---|---|
Distance Shadowmask | カメラとライトの距離がパンクチュアルライトの Fade Distance よりも小さいときに、ライトがすべてのゲームオブジェクトにリアルタイムシャドウを作るようにします。ディレクショナルライトが使う代替えの距離プロパティーについては、以下 を参照してください。カメラとライトの距離が Fade Distance よりも大きくなると、HDRP はライトに対してリアルタイムシャドウを計算するのをやめます。代わりに静的ゲームオブジェクトに対してシャドウマスクを使い、非静的ゲームオブジェクトはシャドウを作りません。 |
Shadowmask | ライトは非静的ゲームオブジェクトのみにリアルタイムシャドウを作ります。その後、カメラとライトの距離が Fade Distance よりも小さくなると、これらのシャドウを静的ゲームオブジェクトのシャドウマスクと組み合わせます。カメラとライトの距離が Fade Distance よりも大きいときは、HDRP はライトに対してリアルタイムシャドウを計算するのをやめます。代わりに静的ゲームオブジェクトに対してシャドウマスクを使い、非静的ゲームオブジェクトはシャドウを作りません。 |
ディレクショナルライトは Fade Distance を使いません。代わりにシーンのボリュームの HD のシャドウ設定 にある、Max Distance プロパティーを使います。
Distance Shadowmask はより GPU に負荷がかかりますが、より現実的に見えます。これはライトに近いリアルタイムのライティングが、遠くのエリアを表現するために選択された低解像度のシャドウマスクテクスチャよりも、より正確なためです。
Shadowmask はよりメモリー使用量がかかります。これはカメラがカメラに近い静的ゲームオブジェクトにシャドウマスクテクスチャを使い、より高い解像度のシャドウマスクテクスチャが必要となるからです。
シャドウ更新モード
Update Mode を使って、HDRP が ライト のシャドウマップを更新するために使う、計算方法を特定することができます。利用できる Update Modes は以下の通りです。
Update Mode | 説明 |
---|---|
Every Frame | HDRP は各フレームでライトに対してシャドウマップを更新します。 |
On Enable | HDRP はゲームオブジェクトを有効にしたときに、ライトに対してシャドウマップを更新します。 |
On Demand | HDRP は要求があるたびに、ライトに対するシャドウマップを更新します。これは、ライトの HDAdditionalLightData コンポーネントで RequestShadowMapRendering() 関数を呼び出して行います。 |
HDRP はシャドウキャッシングを使って、ライト に不必要にシャドウマップを更新することなく、パフォーマンスを向上させます。HDRP には、パンクチュアル、エリア、そしてディレクショナルライト用のシャドウアトラスがあり、さらにキャッシュされたパンクチュアルとエリアライト専用の、別のシャドウアトラスもあります。キャッシュされたディレクショナルライトは、通常のディレクショナルライトと同じアトラスを使います。 ライトの Update Mode は、HDRP がシャドウマップをキャッシュするかを決定します。ライトの Update Mode を OnEnable または OnDemand に設定すると、HDRP はライトの シャドウマップをキャッシュします。ライトの Update Mode を Every Frame に設定すると、HDRP はライトのシャドウマップをキャッシュしません。 シャドウをキャッシュするライトが初めてシャドウマップをレンダリングする際に、HDRP はシャドウマップをキャッシュされたシャドウアトラスに割り当てる、キャッシュされたシャドウマネージャーに登録します。ディレクショナルライトの場合は、HDRP はキャッシュされていてもいなくても、同じシャドウアトラスを使います。
ライトの Update Mode が OnDemand に設定されている場合は、HDRP がライトのシャドウマップを更新するように、手動で要求することができます。この手順はまず、ライトの HDAdditionalLightData コンポーネントにアクセスし、RequestShadowMapRendering
関数を呼び出します。また、ライトに複数のシャドウがある場合は (1 つのディレクショナルライトの複数のカスケードなど)、特定のサブシャドウの更新を要求できます。これは、RequestSubShadowMapRendering(shadowIndex)
関数を使って行います。
シャドウをキャッシュするライトについては、そのライトを無効にするかまたはUpdate Mode を Every Frame に設定すると、HDRP はキャッシュされたシャドウアトラス内にライトのシャドウマップの場所を保存します。つまり、ライトを再び有効にすると、HDRP はシャドウを再度レンダリングする必要がなくなるか、またはシャドウアトラス内に配置します。ライトにシャドウマップの場所をキャッシュされたシャドウアトラスに保存させる方法については、シャドウアトラス場所の保存 を参照してください。
HDRP は一般的なケースのショートカットとして、ライトの位置または回転のいずれかが特定のしきい値を超えたときに、自動的に更新を開始するオプションがあります。このオプションを有効にするには、ライト を選択して、Inspector の Shadow セクションで Update on light movement を有効にします。
更新を開始するためには、ライトがどれくらい動く、または回転する必要があるかを決定するために、HDRP が使うしきい値は、カスタマイズできます。これはライトの HDAdditionalLightData コンポーネントで、cachedShadowTranslationUpdateThreshold
と cachedShadowAngleUpdateThreshold
プロパティーを使って行います。このモードで更新を実行する必要があるかを決定する際、ポイントライトは角度の差異を無視しますので注意してください。
シャドウキャッシュをカスタマイズする
HDRP はパンクチュアルライトのシャドウマップを 1 つのアトラスに、エリアライトを別のアトラスに、そしてディレクショナルライトをキャッシュされていないディレクてょなるライトと同じアトラスに、キャッシュします。最初の 2 つのキャッシュされたシャドウアトラスの解像度は、それぞれ個別に変更できます。この手順は以下の通りです。
- HDRP Asset を選択し、Inspector で表示します。
- パンクチュアルライトは、Lighting > Shadows > Punctual Light Shadows に移動します。エリアライトは、Lighting > Shadows > Area Light Shadows に移動します。
- Cached Shadow Atlas Resolution の値を好きな値に設定します。シャドウアトラスを整理するために、それぞれのシャドウマップの解像度は 64 の倍数になるようにしてください。できるだけ多くのシャドウマップを同じ解像度に設定することが、理想的です。
ライトがスポットを要求したときにシャドウアトラスがいっぱいであれば、キャッシュされたシャドウマネージャーはそのライトのシャドウマップを追加しないため、そのライトはシャドウを投影しません。つまり、利用できるスペースを管理することが重要です。シャドウアトラスに空きがあるかを確認するには、 HDCachedShadowManager.instance.WouldFitInAtlas
ヘルパー関数を使います。すでにアトラス内にライトの場所があるか、それとも場所を待っている状態なのかを確認するために、Render Pipeline Debug ウィンドウ にはキャッシュされたシャドウアトラスのステータスを記録するオプションが含まれています。これを利用するには、
- メニュー: Window > Render Pipeline > Render Pipeline Debug をクリックします。
- Lighting > Shadows に移動します。
- Log Cached Shadow Atlas Status ボタンをクリックします。そうすると Console ウィンドウに、すでにアトラス内にライトの場所があるか、それとも場所を待っている状態なのかを説明するメッセージが表示されます。
シーンが既に配置された Lights すべてを読み込んだ後で、キャッシュされたシャドウを持つ新しいライトをシーンに追加すると、HDRP はそれを配置してアトラス内の穴を埋めようとします。ただし挿入順序によっては、アトラスが断片化され、利用できる穴にライトのシャドウマップが入りきらない場合があります。この場合は、追加のライトのためにアトラスを最適化します。これは、ターゲットアトラスを関数 HDCachedShadowManager.instance.DefragAtlas
にパスして行います。
その結果、HDRP がアトラス内のすべてのシャドウマップをダーティとしてマークし、つまり親ライトが可視化されると同時に、それらをレンダリングすることになりますのので、注意してください。
シャドウアトラス配置を保存する
ライトを無効にするか、または Update Mode を Every Frame に変更すると、キャッシュされたシャドウマネージャーは、キャッシュされたシャドウアトラス内のライトのシャドウマップのスペースを予約せず、HDRP はフレームごとにライトのシャドウマップを通常のシャドウアトラスにレンダリングし始めます。キャッシュされたシャドウマネージャーが、別のライトに対してアトラスのスペースを割り当てる必要がある場合は、元のライトのシャドウマップが現在占領しているスペースをオーバーライドすることができます。
ライトの Update Mode をあくまでも一時的に Every Frame に設定して、後から On Enable または On Demand に戻したければ、ライトのシャドウマップ場所をアトラスに保存することができます。これは例えば、HDRP に遠くのライトのシャドウマップをキャッシュさせたいものの、カメラ に近づいたらフレームごとに更新させたい場合などに役立ちます。これは、ライトの HDAdditionalLightData コンポーネントにアクセスし、preserveCachedShadow プロパティーを有効にして行います。このプロパティーが true
に設定されている場合は、HDRP はライトのシャドウマップのスペースをシャドウアトラスに保存します。このプロパティーが有効になっていても、ライトを破棄するとシャドウアトラス内の場所が失われますので、注意してください。
ノート
Unity Editor 内にいる間は、シャドウを作るライトを変更するたびに、HDRP はシャドウマップを更新します。ビルドされたアプリケーションでは、ライトで異なるプロパティーを変更するとき、または以下の関数のいずれかを呼び出すときに、HDRP はキャッシュされたシャドウマップを最新情報に更新します。
- SetShadowResolution()
- SetShadowResolutionLevel()
- SetShadowResolutionOverride()
- SetShadowUpdateMode() または shadowUpdateMode (この場合、モードが Every Frame と not Every Frame 間で変化する場合、HDRP はキャッシュされたシャドウマップのみを更新します)。
HDRP はメインビューが動くたびにキャッシュされたシャドウマップの自動更新を行わないため、ビューに依存するものはすべて、キャッシュされたシャドウマップとの問題が発生する可能性が高いです。わかりずらいこの例の 1 つは、テッセレーションです。テッセレーション要素はビューに依存するため、メインカメラが把握するジオメトリは HDRP がキャッシュされたシャドウマップにレンダリングするジオメトリとは、一致しない場合があります。これが目に見えて明らかな場合は、HDRP にライトのシャドウマップを更新するよう、リクエストをトリガーしてください。これは、ライトの Update Mode が On Demand に設定されていることを確認し、RequestShadowMapRendering
を呼び出して行います。
コンタクトシャドウ
Contact Shadow (コンタクトシャドウ) は、HDRP が近距離の範囲で深度バッファ内のスクリーンスペースで レイマーチ するシャドウです。通常シャドウマップがキャプチャできないジオメトリのディテールに対して、小さく、詳細なシャドウを供給します。
コンタクトシャドウの有効化およびカスタマイズの方法に関する詳細は、コンタクトシャドウオーバーライドに関するドキュメント を参照してください。
コンタクトシャドウは、一度に 1 つのライトしか作ることができません。つまり、画面で表示されるコンタクトシャドウを作るライトが複数ある場合は、主要なライトのみがコンタクトシャドウをレンダリングします。HDRP はライトの境界ボックスのスクリーンスペースサイズを使って、主要ライトを選びます。コンタクトシャドウを作る Direction Light は常に主要ライトになります。