忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

[XNA]パラレル・スプリット・シャドウマップで影の解像度を上げる


ここにあるパラレル・スプリット・シャドウマップなるもののデモを少しリファクタリングしてみました。(この記事を書いてから何度か変更しています)

PssmDemo2.0.zip(XNA Game Studio 2.0)

マーチンファウラーさんによれば、他人の書いたコードを理解するのにリファクタリングは役に立つそうですしね。



パラレル・スプリット・シャドウマップ

パラレル・スプリット・シャドウマップというのは、シャドウマップで作った影をくっきり見せるためのテクニックの一つで、2006年から2007年にかけて、香港中文大学のFan Zhangさんとその愉快な仲間たちによって考案されたものです。日本語に訳すとしたら「平行分割シャドウマップ」といったところでしょうか…?。普通のシャドウマップは影にカメラを近付けると影がジャギジャギになってしまうので、「それならシャドウマップをいくつかに分割して、カメラに近いところは高い解像度にすればいい!」というのが基本的なアイデアです。そういう意味で、3DMark2006のカスケード・シャドウマップに似ていると言えます。

もう少し詳しく見ていきます。そもそもなぜこのパラレル・スプリット・シャドウマップというのが考え出されたのかというと、フツーのシャドウマップには影がジャギジャギになるという問題があるからです。

sm.jpg
普通のシャドウマップです。遠くの影はそうでもありませんが、手前の影はでこぼこが目立ちます。

これはシャドウマップの精度が足りないからです。もちろんシャドウマップの解像度を上げればこのジャギジャギは緩和されますが、それではビデオメモリを食いまくります。

そこでどうするのかというと、カメラに写っている空間を何分割かして、それぞれの領域のシャドウマップを別々に作ってやります。

pssmDesc1.jpg

この分割がミソで、この分割を上手くやらないと効果はありません。といっても難しいことはなく、ようするにカメラに近いところは小さく区切って、カメラから遠いところは大きく区切ればいいのです。そうすれば自動的に、近いところのシャドウマップは高解像度に、遠いところのシャドウマップは低解像度になります(もちろんこれはすべてのシャドウマップのサイズが同じ場合です。分割を同じようにやって、なおかつシャドウマップのサイズを近いところは大きく、遠いところは小さく、というふうにしても同じような結果が得られるでしょう)。そうすると…近いところの影も鮮明に描けます!めでたしめでたしというわけです。


2分割の場合
split2.jpg
すばらしいですね。影がぐっとはっきりしてきました。

3分割
split3.jpg
2分割のときほど劇的な変化はありませんが、それでもさらに影がはっきりしています。


PSSM公式(?)サイトにあるXNAのサンプルでは1つのレンダーターゲットを各シャドウマップに使いまわして描画しています。つまり、シャドウマップ1を描画、空間1の物体を影付きで描画、シャドウマップ2を描画、空間2の物体を影付きで描画……ということを繰り返しています。ということは「空間の分割数 * 2」のDrawコールが必要です。これはCPUがボトルネックになりそうです。

シャドウマップ1を描画 → 空間1の物体を描画 →
シャドウマップ2を描画 → 空間2の物体を描画 →
シャドウマップ3を描画 → 空間3の物体を描画 →
…以下略

もっとも、シャドウマップを別々のレンダーターゲットに描画して、それをテクスチャの配列としてEffectにセットして、シーンを一気に描画するという方法も使えるはずです(ということがZhangさんの文に書いてました)。この方法なら「空間の分割数 + 1」ですみますからね。


拍手[0回]

PR