水の流体物理シミュレーション
水(液体)についても煙を基本としていくつかの改変を行うことで表現できるとしている。
最も重要なのは「水面」という概念の導入だ。
炎や煙では密度情報を記録していたが、その代わりに、パラメータとして「水面」までの最短距離を符号付きスカラ値で持つようにする。符号は水面上をプラス(+)、水面下をマイナス(-)、と判断できるようにする狙いがある。そしてこの水面が移流することになる。
また、水面上の圧力は常にゼロとし、重力などの外力の影響も受けないものとし、シミュレーション計算も行わない。
そして、水のシミュレーション結果の描画レンダリング・フェーズは炎や煙とはだいぶ異なる。
描画にレイキャスティングを行うが、水面と衝突した時点で視線を突き進めるのを中断する。この視線と水面の衝突は、水面情報を記録した3Dテクスチャの符号(±)が変化する部分を探し出すことで判定できる。
この方法で水面が探し出せたら、周囲の水面情報をサンプルして、この部分の法線ベクトルを推定算出する。
法線ベクトルが求まれば、あとは普通のポリゴンベースで作った水面のレンダリングと同じだ。
視線ベクトルと法線ベクトルから適当に反射ベクトルを算出して環境マップをサンプルすれば映り込みが表現できるし、適当に屈折ベクトルを算出してレンダリング済みの水底シーンをサンプルして屈折表現ができる。この映り込みと屈折の混ぜ具合を水面と視線の関係で調整して変化させればフレネル反射の表現が実現できるのも、普通のポリゴンベースの水面のシェーディングと同じ。
ただ、問題がある。
それは、煙の時もそうだったが、マッハバンドの問題だ。流体物理シミュレーションの解像度がそれほど高くないので水面の衝突判定が"段段"になってしまいがちなのだ。
このマッハバンドを回避するためにNVIDIAの実装では結構強引な二分探索法を用いて正確な水面位置を検索している。
これは最初の水面境界判定に引っかかったらその中間地点を求めてそこから水面がレイキャスティングの入射方向のどちら側にあるのかを調べて水面のある方向に再び中間点を求める。NVIDIAの実装ではこの反復を三回繰り返して十分な精度が得られているとのこと。
また、画質、精度を高めるために、NVIDIAの実装では、水面検索と水面の傾き水底算出の際の3Dテクスチャサンプルにトライリニア(Trilinear)フィルタリングやトライキュービック(Tricubic)フィルタリングを用いている。トライリニアは近傍8点の線形補間で、トライキュービックは8組のトライリニア参照を行うので8×8=近傍64点で補間計算を行うもの。
NVIDIAの実装経験によればフィルタリングメソッドを高品位にするよりも、二分探索法の方が高精度を得やすいとのことであった。
これは筆者個人の意見であるが、画面ショットを見る限り、確かに二分探索法+トライリニア・フィルタリングで高精度な結果が得られているとは思う。