分散シャドウマップについて

はじめに

分散シャドウマップ (Variance Shadow Maps) について調べたことのまとめです。

モーメントシャドウマップという手法の方が新しく提案されていて、これは分散シャドウマップを改良した方法のようです。

最初はモーメントシャドウマップを調べていたんですが、分散シャドウマップについて知らないと理解できなそうだったので分散シャドウマップを先に調べることにしました。

分散シャドウマップ

元の論文が Web 上で公開されていて読むことができました。

www.punkuser.net

http://www.punkuser.net/vsm/vsm_paper.pdf

最初は Web 上の解説記事などを読んだりしていたんですが、 この論文はそこまで難しくはなさそうだったので論文を読んだほうが確実な気がします。

分散シャドウマップについて説明してみます。

シャドウマップでの影の描画ではまずライトを視点として、ライトから一番近いポリゴンの深度をシャドウマップ用のテクスチャに書き出します。

それからカメラ視点からポリゴンを描画していき、描画するピクセル部分のライトからの距離がシャドウマップよりも遠い場合はライトとの間に遮蔽物があることがわかるので影が落ちるように明るさを変えて描画します。

シャドウマップの解像度が低い場合にエイリアシングが起こることがよくあります。

分散シャドウマップではエイリアシングが改善され、影の境界がスムーズに描画されます。

分散シャドウマップでは MIPMAP や異方性フィルタリングなど通常の画像に使われるエイリアシングの対策が有効に使えるというのも利点のようです。

描画の方法

  1. まずシャドウマップを作成します。ただし通常のシャドウマップと違ってライトからの深度と深度の二乗を出力します。

  2. 必要に応じて事前に2パスガウシアンブラーでフィルタリングを行います。

  3. シャドウマップの MIPMAP を生成します。OpenGL では MIPMAP を自動で生成する API が使えます。

  4. カメラ視点で描画を行います。フラグメントシェーダーでシャドウマップから深度と深度の二乗を取得します。シャドウマップから取得した値は局所的な平均値になっています。 描画部分のライトからの深度がシャドウマップの深度より小さい場合は影は落ちないと判定します。 描画部分のライトからの深度がシャドウマップの深度よりも大きい場合はチェビシェフの不等式を使って影の強さを計算して描画します。

チェビシェフの不等式について

分散シャドウマップで使われているのはチェビシェフの不等式の single tail バージョンです。

en.wikipedia.org

読み方がわかりませんがカンテリ (コンテリ?) の不等式と呼ばれているようです。

論文に出てくるのは下の式です。

{
P(x \geq t) \leq p_{max}(t) \equiv \frac {\sigma ^{2}}{\sigma ^{2}+(t - \mu)^{2}}
}

{t > \mu} という条件があります。

{\mu} は深度の平均値です。 {\sigma ^2} は深度の分散で {\mu} と深度の二乗の平均から求められます。

{
\sigma ^{2} = E(x ^2) - E(x) ^2
}

{P(x \geq t)} は影を作る遮蔽物の深度が t よりも大きい場合の確率です。 t は描画する部分の深度なのでこの確率は影にならない場合の確率だと思います。 t が大きくなると分母が大きくなり、影にならない確率は小さくなります。