2013/05/27

水面描画への再挑戦

過去のブロック地形動画の際に、海や湖を表現するために水面のエフェクトを組んでいたのですが、これを汎用化して自作 SharpDX フレームワークに載せようと試みていました。基本的には、波を表すための法線マップを事前にテクスチャとして用意するという方法が嫌いなため、自動生成して利用する枠組みにしています。

過去の実装から思い出していたのですが、元は反射と屈折を考慮した水面を実装していたにも関わらず、何かの理由で反射と屈折を止めた記憶があるなぁ・・・と。

屈折効果に用いる水中シーンを描画するために、GraphicsDevice.ClipPlanes の設定により水面より上をクリップするという XNA のチュートリアル サイトの情報があり、過去の自分はこれを参考に実装したと思われますが、この機能は XNA 4.0 で失われています。恐らく、僕は移行方法が分からずに諦めたのではないかと。

XNA 4.0 における対応としては、クリップ面をシェーダへ渡し、頂点からクリップ面までの距離を算出し、clip 関数を用いて距離が 0 以下 (頂点がクリップ面の裏側) ならばピクセル シェーダの出力を抑制してしまう方法かと思います。
シェーダ モデル 4.0 以上ならば、算出した距離を SV_ClipDistance セマンティクスでピクセル シェーダへ渡せば自動的にクリップしてもらえるようなので、自作フレームワークではこれを利用しました。

他には、頂点シェーダの属性として [clipplanes] でクリップ面を指定すると、SV_ClipDistance に関わるコードを書かずに済むらしいのですが、これは使わない事にしました。僕は、シェーダのコンパイル時警告をエラーとして扱っていますが、clipplanes を指定するとクリッピングに関する頂点シェーダ出力の初期化が完全ではないとの警告が出てしまい、これを解決する術が分からずに断念しました。どうにも、clipplanes 属性の利用に関する情報が少なすぎて。

ひとまず、一般的な水の表現は実装できましたが、水が XZ 平面上にある必要もないと思い、自由に回転させた平面に水面エフェクトを適用しようと試みている所です。

とまぁ、気付いたらまた壮大に脱線し始めたと思うものの、どこかの時点で自身の知識の整理はすべきであり、なおかつ、更に一歩進むべきとの思いもあり。

0 件のコメント:

コメントを投稿

libgdx いじり

Google が提供している Java 版の Tango Examples は Rajawali をベースにしているため、自分が仕事で開発する Tango アプリも Rajawali ベースとしていましたが、最近は libGDX への移行を進めています。一応、要点については移行が...