3Dゲームファンのためのグラフィックス講座
西川善司の3Dゲームファンのための「Panta Rhei」講座(後編)
(2013/8/1 00:00)
流体の描画はレイマーチング法を採用
シミュレーションを終えた流体も、そのままではただのグリッド構造のデータの塊でしかない。映像に“形”として表すには、これを「可視化=グラフィックスとして描画」をしなければならない。
しかし、流体は、一般的なキャラクターモデルのようなポリゴンの集まりで構成されているのではなく、前段までで解説してきたようにグリッド構造のデータでしかないので、普通の手法ではGPUではレンダリングが行なえない。
そこで、実践することになるのがレイマーチング法だ。レイマーチング法は、結論から言えば、レイトレーシング的な手法だ。
描画対称のピクセルから、視線方向にレイを放ち、放ったレイを流体シミュレーション用のグリッドに潜らせていく。潜ったレイはシミュレーション用グリッドに格納されているデータを参照し、流体の密度等のパラメータを取得していき、以降、「打ち切り」となるまでレイを少しずつ進めていく。レイを行進させていく(MARCHING)ような処理系なのでレイマーチング法という名称が付けられている。
例えば、煙のような流体があったときに、あるピクセルからレイを飛ばして、この煙の中に潜ったとする。レイが煙を抜けるまで探査して、煙の密度が濃ければ、そのピクセルは煙色になる。密度が薄ければ煙色は薄く、背景色の方が強くなることだろう。こうした処理を行なうわけだ。流体の密度(濃度)の高低と、描画する流体の色の対応決めは一次元の伝達関数テクスチャで与えている。
なお、レイの行進の打ち切りは、流体シミュレーショングリッドを突き抜けたときは当然として、他者3Dモデル等と衝突した場合などに行なわれる。
清水氏:1つのレイは最大でアーティスト指定ステップ数のグリッドサンプリングを行ないます。レイマーチングをさせる際、隣接するピクセルから放たれたレイとは不揃いに進むような、いわゆるジッタリングさせてやっています。こうすることで少ないサンプル数で比較的、正確な流体の描画ができるようになっています。
前編のレンダリングエンジンの解説編で、拡散反射情報の回収のために12方向にレイを飛ばしたいが、1ピクセルからは1レイしか飛ばさずに、12ピクセルで12方向に飛ばし、最終的にそれらを取りまとめて、1ピクセルから12方向分に飛ばしたと想定できる映像を算術合成する工夫を紹介したが、あの発想を流体描画のレイマーチング方にも応用したようなイメージだ。
三嶋氏:レイを進める際、流体が存在しないグリッド内を延々と進ませるのは処理の無駄になりますので、レイマーチングさせる前に流体シミュレーションのグリッドよりも一段荒いグリッドをMIP-MAP的に生成して、流体が存在しないグリッドを一気にすっ飛ばせるような工夫を入れています。
「Panta Rhei」の流体の描画においてはセルフシャドウが出るような機構も組み込まれている。この流体のセルフシャドウ描画については、GDC2013でNVIDIAが発表した「Particle Shadow Map」法に似たボリュームテクスチャを使用した手法が使用されている。
発想としては、PS3、Xbox 360世代から使われているデプスシャドウ技法の概念を3Dテクスチャに応用したものだ。普通のデプスシャドウ技法では、シーンの遮蔽構造を光源位置からテクスチャにレンダリングして生成した「シャドウマップ」を判断材料にして「影か否か」判定を行なっていく。Particle Shadow Map法では、対象となる流体を、光源位置からその照射方向から複数枚にスライスして、各スライスに対してシャドウマップを生成していくイメージだ。光源位置から見て遠い位置の流体スライスは、近い位置側の流体スライスのシルエットに遮蔽されることになり、このシルエットによってどの程度光源からの光が減衰させられるのかを計算し、この値をも各スライスに格納していく。
シーンのレンダリング時には、この複数スライスによって与えられるParticle Shadow Mapを参照しながら、影色を付けるような感覚で描画していく。レイマーチングを行なって流体を描画する際にも、このParticle Shadow Mapに配慮して描画すれば流体のセルフシャドウも描画出来てしまうわけだ。つまり、シーンに対する流体の影と、流体のセルフシャドウの両方を描画できるわけである。
清水氏:流体越しに光を見たりするような場合の表現については単一散乱(シングルスキャツタリング)に対応しています。これは光筋表現や光散乱表現に応用する事ができます。
単一散乱とは、入射光が流体内部で1度だけ微粒子と衝突して生ずる散乱のこと。雲、煙、霧などの散乱元の粒子の密度が低いケースで適用することができる。単一散乱ケースでは、視点に到達する光は、減衰率を視点までの距離で積分した値に掛けてやることで一意的に求めることが可能だ。
ところで、最終的には、レイマーチング法で描画した流体と、前編で紹介したような通常の3Dモデルの描画結果との合成を行なう必要が出てくる。レイマーチングは、他者モデルとの公差箇所で打ち切られているので、不透明オブジェクトの描画結果とは、単純な加算合成で何の問題もない。問題が起こりうるのは、半透明オブジェクトとの合成の場合だ。
清水氏:『deep down』のリアルタイム映像デモでは、半透明オブジェクトの描画結果とそのまま合成してしまっています。物理的にはこれは正しくないのですが、見た目的に問題がなかったのでそうしてしまいました。万が一、今後、不自然な状況が出てきた場合は、半透明オブジェクトの描画や流体の描画を視点から見て奥行き方向に複数レイヤーに分割して実践して、各レイヤーごとに合成していくような工夫が必要になるかもしれません。