シャドウ深度マップを向上させるための一般的な方法
1978 年に初めて導入されたシャドウ マップは、ゲームにシャドウを追加するための一般的な手法です。 30 年後、ハードウェアとソフトウェアの進歩にもかかわらず、シャドウアーティファクト (エッジの輝き、遠近のエイリアシング、その他の精度の問題) は持続します。
この技術記事では、一般的なシャドウ 深度マップ アルゴリズムと一般的なアーティファクトの概要について説明し、基本的なものから中間的なものまで、標準的なシャドウ マップの品質を向上させるために使用できるいくつかの手法について説明します。 通常、基本的なシャドウ マップをタイトルに追加するのは簡単ですが、シャドウアーティファクトの微妙な違いを理解するのは困難な場合があります。 この技術記事は、シャドウを実装した中間グラフィックス開発者向けに書かれていますが、特定の成果物が表示される理由を完全には理解していないため、それらの回避方法がわかりません。
特定のアーティファクトを軽減するための適切な手法を選択することは、何の問題にもなります。 シャドウ マップの欠点に対処すると、品質の違いが印象的になる可能性があります (図 1)。 これらの手法を正しく実装すると、標準の影が大幅に改善されます。 この記事で説明する手法は、DirectX SDK の CascadedShadowMaps11 サンプルに実装されています。
図 1. 重大なアーティファクトを含むシャドウ (左)、およびこの記事で説明されている手法を実装した後のシャドウ (右)
影深度マップ レビュー
シャドウ深度マップ アルゴリズムは、2 パス アルゴリズムです。 最初のパスは、ライト空間で深度マップを生成します。 2 番目のパスでは、このマップを使用して、各ピクセルのライト空間の深度を、ライト空間深度マップ内の対応する深度と比較します。
図 2. シャドウ シーンの重要な部分
Pass 1
シーンを図 2 に示します。 最初のパス (図 3) では、ジオメトリはライトの観点から深度バッファーにレンダリングされます。 具体的には、頂点シェーダーはジオメトリをライト ビュー空間に変換します。
この最初のパスの最終的な結果は、ライトの観点からシーンの深度情報を含む深度バッファーです。 これをパス 2 で使用して、ライトからどのピクセルが隠れているかを判断できるようになりました。
図 3。 基本的なシャドウ マッピングの最初のパス
Pass 2
2 番目のパス (図 4) では、頂点シェーダーは各頂点を 2 回変換します。 各頂点はカメラのビュー空間に変換され、ピクセル シェーダーに位置として渡されます。 各頂点もライトのビュー プロジェクション テクスチャ マトリックスによって変換され、テクスチャ座標としてピクセル シェーダーに渡されます。 ビュー プロジェクション テクスチャ マトリックスは、1 つの追加の変換でパス 1 でシーンをレンダリングするために使用されるのと同じマトリックスです。 これは、ポイントを拡大縮小し、ビュー空間 (-1 から X と Y の 1) をテクスチャ空間 (X では 0 から 1、Y では 1 から 0) に変換する変換です。
ピクセル シェーダーは、補間された位置と補間されたテクスチャ座標を受け取ります。 深度テストを実行するために必要なすべてのものが、このテクスチャ座標に含まれるようになりました。 深度テストを実行するには、最初のパスの深度バッファーに X と Y のテクスチャ座標を指定し、結果の深度値を Z テクスチャ座標と比較します。
図 4 基本的なシャドウ マッピングの 2 番目のパス
シャドウ マップアーティファクト
シャドウ深度マップ アルゴリズムは、最も広く使用されているリアルタイム シャドウ アルゴリズムですが、それでも軽減を必要とする複数のアーティファクトが生成されます。 発生する可能性がある成果物の種類を次に要約します。
パースペクティブエイリアシング
図 5 に、一般的な成果物であるパースペクティブ エイリアシングを示します。 これは、ビュー空間内のピクセルとシャドウ マップ内のテクセルのマッピングが 1 対 1 の比率でない場合に発生します。 これは、近くの平面に近いピクセルが一緒に近く、より高いシャドウ マップ解像度を必要とするためです。
図 6 は、シャドウ マップとビューの錐台を示しています。 目の近くでは、ピクセルは一緒に近く、多くのピクセルは同じシャドウ テクセルにマップされます。 遠方平面のピクセルが広がり、遠近法のエイリアシングが減少します。
図 5。 高遠近法のエイリアシング (左) と低遠近法のエイリアシング (右)
左側の画像では、遠近法のエイリアシングが高くなります。同じシャドウ マップ テクセルにマップされている視線空間ピクセルが多すぎます。 右の画像では、視線空間ピクセルとシャドウ マップ テクセルの間に 1 対 1 のマッピングがあるため、遠近法のエイリアシングは低くなります。
図 6。 シャドウ マップを使用して視錐台を表示する
遠方平面の明るいピクセルは低遠近のエイリアシングを表し、近くの平面の暗いピクセルは高遠近のエイリアシングを表します。
シャドウ マップの解像度が高すぎる場合もあります。 解像度が高いほど目立たなくなりますが、電話線などの小さなオブジェクトがシャドウを投影しないことがあります。 また、解像度が高すぎると、テクスチャ アクセス パターンのために重大なパフォーマンスの問題が発生する可能性があります。
パースペクティブ シャドウ マップ (PSM) とライト スペースパースペクティブ シャドウ マップ (LSPSM) は、ライトの投影マトリックスを傾斜させて、必要な場所に目の近くにテクセルを配置することで、遠近法のエイリアシングに対処しようとします。 残念ながら、どちらの手法もパースペクティブエイリアシングを解決できません。 シャドウ マップ内のテクセルに視線空間ピクセルをマップするために必要な変換のパラメーター化は、線形スキューではバインドできません。 対数パラメーター化が必要です。 PSM は目の近くにディテールが多すぎるため、遠くの影の品質が低かったり、消えたりします。 LSPSM は、目の近くで解像度を上げ、オブジェクトに十分な詳細を残すことの中間点を見つけるより優れた仕事をします。 どちらの手法も、一部のシーン構成では正投影シャドウに縮退します。 この変性は、ビューの錐台の各面に対して個別のシャドウ マップをレンダリングすることで対処できますが、これはコストがかかります。 対数パースペクティブ シャドウ マップ (LogPSM) では、ビューの錐台の面ごとに個別のマップもレンダリングされます。 この手法では、非線形ラスター化を使用して、目の近くにさらにテクセルを配置します。 D3D10 および D3D11 クラスのハードウェアでは、非線形ラスター化はサポートされていません。 これらの手法とアルゴリズムの詳細については、「参照」セクションを参照してください。
カスケード シャドウ マップ (CSP) は、パースペクティブ エイリアシングを処理するための最も一般的な手法です。 CSP は PSM や LSPSM と組み合わせることができますが、不要です。 CSP を使用してパースペクティブ エイリアシング エラーを修正する方法については、コンパニオン記事「 Cascaded Shadow Maps」を参照してください。
射投影のエイリアシング
投影エイリアシングは、遠近法のエイリアシングよりも表示が困難です。 図 7 で強調表示されている意図しない影は、射影エイリアシング エラーを示しています。 射光エイリアシングは、カメラ空間内のテクセルとライト空間のテクセル間のマッピングが一対一の比率でない場合に発生します。これは、ライト カメラに対するジオメトリの向きが原因です。 投影エイリアシングは、ジオメトリの接線平面が光線と平行になると発生します。
図 7. 射射量の多いエイリアシングと射射量の少ないエイリアシング
遠近法のエイリアシング エラーを軽減するために使用される手法では、射射エイリアスも軽減されます。 投影エイリアシングは、サーフェス法線がライトに直交する場合に発生します。これらのサーフェスは、拡散光方程式に基づいて受光が少なくなります。
影にきびと誤ったセルフシャドウ
シャドウ にきび (図 8) は、誤った自己シャドウと同義の用語で、シャドウ マップがテクセル全体の深度を量子化するときに発生します。 シェーダーが実際の深度をこの値と比較すると、影が付いていないのと同じくらい自己シャドウされる可能性があります。
影にきびのもう 1 つの理由は、ライト空間内のテクセルが深度マップ内の対応するテクセルの深さに非常に近いので、精度エラーによって深度テストが誤って失敗するということです。 この精度差の理由の 1 つは、深度マップが固定関数ラスター化ハードウェアによって計算され、比較される深度がシェーダーによって計算されたということです。 射影エイリアシングは、影のにきびを引き起こす可能性もあります。
図 8. 影にきびアーティファクト
左側の画像に示すように、一部のピクセルは深度テストに失敗し、スペックルされたアーティファクトとモアレ パターンを作成しました。 誤ったセルフシャドウを減らすために、ライトスペースビュー錐台のニアプレーンとファープレーンの境界をできるだけ厳密に計算する必要があります。 傾きのスケールベースの深さのバイアスと他の種類のバイアスは、影のにきびを軽減するために使用される他のソリューションです。
Peter Panning
Peter Panning という用語は、影が切り離され、飛ぶ可能性のある子供の本のキャラクターからその名前を派生させます。 このアーティファクトにより、影のないオブジェクトがサーフェスからデタッチされ、サーフェスの上に浮いているように見えます (図 9)。
図 9. Peter Panning アーティファクト
左側の画像では、影がオブジェクトからデタッチされ、浮動効果が作成されます。
表面にきびを除去するための1つの技術は、光空間のピクセル位置にいくつかの値を追加することです。これは深度オフセットの追加と呼ばれます。 ピーター パンは、使用される深度オフセットが大きすぎる場合に発生します。 この場合、深度オフセットによって深度テストに誤って合格します。 シャドウ にきびのように、深度バッファーに精度が不十分な場合、Peter Panning は悪化します。 厳密な近くの平面と遠くの平面を計算すると、ピーター パンを回避するのにも役立ちます。
シャドウ マップを改善する手法
タイトルに影を追加することはプロセスです。 最初の手順は、基本的なシャドウ マップを動作させる方法です。 2 つ目は、すべての基本的な計算が最適に行われるようにすることです。フルスタはできるだけ緊密にフィットし、ニア/ファー プレーンは緊密にフィットし、傾きスケーリングバイアスが使用されます。 基本的なシャドウが有効になり、可能な限り適切に表示されると、開発者はシャドウを十分に忠実にするために必要なアルゴリズムをより適切に把握できます。 このセクションでは、基本的なシャドウ マップの最適な表示に必要な基本的なヒントについて説明します。
傾きスケール深度バイアス
前述のように、セルフシャドウは影にきびにつながる可能性があります。 バイアスを追加しすぎると、Peter のパンが発生する可能性があります。 さらに、傾斜が急な多角形 (ライトに対して相対的) は、(ライトに対して) 浅い斜面を持つポリゴンよりも射光エイリアシングの影響を受けます。 このため、各深度マップ値には、ライトに対するポリゴンの傾きに応じて異なるオフセットが必要になる場合があります。
Direct3D 10 ハードウェアには、ビューの方向に対する傾きに基づいて多角形をバイアスする機能があります。 これは、光の方向にエッジオンで表示される多角形に大きなバイアスを適用する効果がありますが、光に直接向いている多角形にはバイアスを適用しません。 図 10 は、同じ偏りのない傾きに対してテストを行うときに、2 つの隣接するピクセルが影付きと影のないピクセルの間でどのように交互に表示されるかを示しています。
図 10. 偏りのない深度と比較した傾きスケーリングされた深度バイアス
厳密な射影の計算
ライトの投影をビューの錐台に厳密にフィットすると、シャドウ マップのカバレッジが増加します。 図 11 は、任意の投影を使用するか、投影をシーン境界に適合させる場合に、遠近法のエイリアシングが高いことを示しています。
図 11. 任意の影の錐台および影の錐台はシーンに合う
ビューはライトの観点から見たビューです。 台形は、ビュー カメラの錐台を表します。 イメージの上に描画されたグリッドは、シャドウ マップを表します。 右側の画像は、同じ解像度のシャドウ マップがシーンにより緊密に収まるときに、より多くのテクセル カバレッジを作成することを示しています。
図 12 は、正しくフィットする錐台を示しています。 投影を計算するために、ビューの錐台を構成する 8 つの点が光空間に変換されます。 次に、X と Y の最小値と最大値が見つかります。 これらの値は、正投影の境界を構成します。
図 12. 円錐台を表示するためのシャドウ プロジェクションフィット
さらに狭い境界を取得するために、視錐台をシーン AABB にクリップすることもできます。 ライト カメラの投影のサイズがフレームからフレームに変更される可能性があるため、これはすべての場合に推奨されません。 「ライト テクセル サイズの増分の移動」セクションで説明されているような多くの手法では、ライトの投影のサイズがフレームごとに一定のままである場合に、より優れた結果が得られます。
ニアプレーンとファープレーンの計算
近面と遠方平面は、投影行列を計算するために必要な最後の部分です。 平面が近いほど、深度バッファー内の値の精度が高くなります。
深度バッファーは、16 ビット、24 ビット、または 32 ビットで、0 ~ 1 の値を使用できます。 一般に、深度バッファーは固定小数点であり、近くの平面に近い値は、遠方平面に近い値よりも密接にグループ化されます。 深度バッファーで使用できる精度の程度は、遠方平面に対するニア プレーンの比率によって決まります。 可能な限り厳密なニア/ファー プレーンを使用すると、16 ビット深度バッファーを使用できます。 16 ビットの深度バッファーを使用すると、処理速度を上げながらメモリの使用を減らすことができます。
AABB ベースのニア プレーンとファー プレーン
近くの平面と遠方平面を簡単かつ単純に計算する方法は、シーンの境界ボリュームをライト 空間に変換することです。 Z 座標の最小値は近くの平面で、最大の Z 座標値は遠方平面です。 シーンとライトの多くの構成では、このアプローチで十分です。 ただし、最悪のシナリオでは、深度バッファーの精度が大幅に低下する可能性があります。図 13 は、このようなシナリオを示しています。 ここでは、遠方平面に対するニアプレーンの範囲は、必要以上に4倍大きい。
図13の視錐台は、意図的に小さいと選択された。 小さなビューの錐台は、ビュー カメラから伸びる柱で構成される非常に大きなシーンに表示されます。 近くの平面と遠くの平面に対してシーン AABB を使用することは最適ではありません。 Cascaded Shadow Maps で説明されている CSM アルゴリズム技術記事では、非常に小さな錐台の近くおよび遠くの平面を計算する必要があります。
図 13. シーン AABB に基づく近くの平面と遠くの平面
Frustum ベースのニア プレーンとファー プレーン
近面と遠方平面を計算するもう 1 つの手法は、錐台を光空間に変換し、Z の最小値と最大値をそれぞれ近面と遠方平面として使用することです。 図 14 は、このアプローチの 2 つの問題を示しています。 まず、円錐台がシーンのジオメトリを超える場合に示すように、計算は保守的すぎます。 次に、近くの平面が狭すぎて、シャドウ キャスターがトリミングされる可能性があります。
図 14: 視錐台のみに基づく近面と遠方平面
近くの平面と遠くの平面を計算するためにシーンと交差する光錐台
近面と遠方平面を計算する適切な方法を図 15 に示します。 正投影光錐台の4つの平面は、光空間におけるビュー錐台のX座標とY座標の最小値と最大値を使用して計算された。 直交ビューの円錐台の最後の 2 つの平面は、近くの平面と遠方の平面です。 これらの平面を見つけるために、シーンの境界は、既知の 4 つの光錐台平面に対してクリップされます。 新しくクリップされた境界の最小および最大の Z 値は、それぞれニアプレーンとファープレーンを表します。
この操作を実行するコードは、CascadedShadowMaps11 サンプルにあります。 世界の AABB を構成する 8 つのポイントは、光空間に変換されます。 ポイントをライト空間に変換すると、クリッピング テストが簡略化されます。 光錐台の 4 つの既知の平面を線として表現できるようになりました。 ライト空間内のシーン境界ボリュームは、6 つの四角形として表すことができます。 これらの 6 つの四角形は、三角形ベースのクリッピングのために 12 個の三角形に変換できます。 三角形はビューの視錐台の既知の平面に対してクリップされます (これらは、光空間の X および Y の水平および垂直線です)。 交差点が X と Y で見つかると、その点で 3D 三角形がクリップされます。 クリップされたすべての三角形の Z 値の最小値と最大値は、ニアプレーンとファープレーンです。 CascadedShadowMaps11 サンプルは、 ComputeNearAndFar 関数でこのクリッピングを実行する方法を示しています。
可能な限り狭い近距離平面と遠方平面を計算するために使用できる手法は、さらに 2 つあります。 これらの手法は、CascadedShadowMaps サンプルには示されていません。
シーンの階層またはシーン内の個々のオブジェクトをライトフラスタムと交差させることで、より厳密な近距離平面と遠方平面を計算できます。 これは、計算が複雑になります。 CascadedShadowMaps11 サンプルでは示されていませんが、これは一部のタイルで有効な手法である可能性があります。
遠方平面は、次の最小値を使用して計算できます。
- ライトスペース内のビュー錐台の最大深度。
- ビュー視錐台とシーン AABB の交差部分の最大深度。
この方法は、ビューの錐台の外部でインデックスを作成できるカスケード シャドウ マップで使用すると問題になる可能性があります。 この場合、シャドウ マップにジオメトリが見つからない可能性があります。
図 15: ライト フラスタムの 4 つの計算平面とシーンの境界ジオメトリの交差に基づく近平面と遠方平面
テクセル サイズの増分でライトを移動する
シャドウ マップの一般的なアーティファクトは、きらめくエッジ効果です。 カメラが動くと、影の端に沿ったピクセルが明るく暗くなります。 これは静止画像では見ることができませんが、リアルタイムでは非常に目立ち、気が散ります。 図 16 は、この問題を強調し、図 17 は影の端がどのように表示されるかを示しています。
光投影行列はカメラが動くたびに再計算されるため、きらめくエッジ エラーが発生します。 これにより、生成されたシャドウ マップに微妙な違いが生じます。 次の要因はすべて、シーンをバインドするために作成されたマトリックスに影響を与える可能性があります。
- ビューの視錐台のサイズ
- 視錐台の向き
- ライトの位置
- カメラの位置
このマトリックスが変更されるたびに、影のエッジが変化する可能性があります。
図 16: 影のエッジをきらめく
カメラが左から右に移動すると、影の境界線に沿ったピクセルが影の中と外に出ます。
図 17: エッジを輝かさない影
カメラが左から右に移動すると、シャドウ エッジは一定に保たれる。
方向ライトの場合、この問題の解決策は、X と Y (正投影境界を構成する) の最小値/最大値をピクセル サイズの増分に丸める方法です。 これは、除算演算、床演算、乗算を使用して行うことができます。
vLightCameraOrthographicMin /= vWorldUnitsPerTexel;
vLightCameraOrthographicMin = XMVectorFloor( vLightCameraOrthographicMin );
vLightCameraOrthographicMin *= vWorldUnitsPerTexel;
vLightCameraOrthographicMax /= vWorldUnitsPerTexel;
vLightCameraOrthographicMax = XMVectorFloor( vLightCameraOrthographicMax );
vLightCameraOrthographicMax *= vWorldUnitsPerTexel;
vWorldUnitsPerTexel 値は、ビューの錐台の境界を取得し、バッファー サイズで除算することによって計算されます。
FLOAT fWorldUnitsPerTexel = fCascadeBound /
(float)m_CopyOfCascadeConfig.m_iBufferSize;
vWorldUnitsPerTexel = XMVectorSet( fWorldUnitsPerTexel, fWorldUnitsPerTexel, 0.0f, 0.0f );
ビューの錐台の最大サイズを境界付けすると、正投影のフィットが緩みます。
この手法を使用する場合、テクスチャの幅と高さが 1 ピクセル大きくなることに注意してください。 これにより、シャドウ 座標がシャドウ マップの外部でインデックスを作成できなくなります。
背面と前面
シャドウ マップは、標準の背面カリングを使用してレンダリングする必要があります。これは、ビューアーが見ることができないオブジェクトのラスタライズをスキップし、シーンのレンダリングを高速化するプロセスです。 もう 1 つの一般的なオプションは、前面カリングを有効にしてシャドウ マップをレンダリングすることです。つまり、ビューアーに面するオブジェクトは削除されます。 この引数は、オブジェクトの背面を構成するジオメトリがわずかにオフセットされるため、セルフシャドウに役立ちます。 この考え方には 2 つの問題があります。
- 前面または背面のジオメトリが不適切なオブジェクトでは、シャドウ マップにアーティファクトが発生します。 ただし、前面または背面のジオメトリが正しくないと、他の問題が発生するため、前面と背面のジオメトリが正しく行われると想定しても問題ない場合があります。 葉などのスプライト ベースのジオメトリの背面を作成するのは現実的でない場合があります。
- 壁などのオブジェクトの基部付近のピーター パンとシャドウ ギャップは、シャドウ深度の差異が小さすぎるため、発生する可能性が高くなります。
シャドウ マップ - フレンドリ ジオメトリ
シャドウ マップで適切に動作するジオメトリを作成すると、Peter Panning やシャドウ ニキビなどのアーティファクトと戦う際の柔軟性が向上します。
ハード エッジは、セルフシャドウに問題があります。 エッジの先端付近の深さの不均衡は非常に小さい。 オフセットが小さい場合でも、オブジェクトの影が失われる可能性があります (図 18)。
図 18: 鋭いエッジは、オフセットとの低深度の不一致から生じるアーティファクトを引き起こす
壁などの狭いオブジェクトは、表示されていなくても背面を持つ必要があります。 これにより、深度の不一致が増加します。
また、ジオメトリが向いている方向が正しいことを確認することも重要です。つまり、オブジェクトの外側は背面に、オブジェクトの内側は前面に向いている必要があります。 これは、背面カリングを有効にしてレンダリングする場合や、深度バイアスの影響に対処する場合に重要です。
カスケードされたシャドウ マップ
また、 Cascaded シャドウ マップおよび CascadedShadowMaps11 サンプル アプリも参照してください。 このサンプルでは、カスケード シャドウ マップ (CSM) アルゴリズムと、シャドウ マップを効率的に使用するために使用できるいくつかの手法を示します。
このサンプルは、DirectX ソフトウェア開発キット (SDK) にあります。 または、Web 検索を実行して GitHub で検索することもできます。
まとめ
この記事で説明する手法を使用して、標準のシャドウ マップの品質を向上させることができます。 次の手順では、標準のシャドウ マップで適切に機能する手法を確認します。 CSP は、パースペクティブ エイリアシングに対処するための優れた手法として推奨されます。 パーセンテージの近いフィルター処理または分散シャドウ マップを使用して、影のエッジを柔らかくすることができます。 詳細については、 Cascaded Shadow Maps 技術記事を参照してください。
Donnelly、W.、Lauritzen、A. 分散シャドウ マップ。 対話型3Dグラフィックスシンポジウム,インタラクティブ3Dグラフィックスとゲームに関する2006年シンポジウムの議事録. 2006年、pp. 161-165.
エンゲル、ウォフガン F. セクション 4. カスケード シャドウ マップ。 ShaderX5、 Advanced Rendering Techniques、Wolfgang F. Engel、Ed。 チャールズ・リバー・メディア、ボストン、マサチューセッツ州。 2006. pp. 197-206.
Stamminger、Marc、Drettakis、George。 パースペクティブ シャドウ マップ。 コンピュータグラフィックスとインタラクティブ技術に関する国際会議, コンピュータグラフィックスとインタラクティブ技術に関する第29回年次大会の発表. 2002年、pp 557-562。
Wimmer、M.、Scherzer、D.、および Purgathofer、W. ライトスペースパースペクティブシャドウマップ。 レンダリングに関するユーログラフィックシンポジウム. 2004 年. 2005 年 6 月 10 日改訂。 Technische Universität ウィーン.