最近のゲームはが画面綺麗ですよね。
大抵のことはゲームエンジンがやってくれます。ゲームエンジンは使われれば使われるほど進化していきます。特にアンリアルエンジンはオープンソースなので、技術習得にちょうどいいです。
まともに一から全部自分で作ろうとすると、やる事が多すぎて挫折すると思います。せいぜいアニメーションを付けたモデルがキーボードで操作出来て終わるのではないでしょうか? ここからコリジョンやらイベントやアニメーションブレンド、ポストエフェクトなど沢山工程をふみます。
綺麗に見せる手法として、物理ベースレンダリングがあります。現実と同じように光源計算を行い、モデルの陰影をはっきりさせます。ただ、まともに計算してしまうと、光源計算で処理を取られてしまい、ゲームになりません。光の計算は事前にしておいて、モデルのレンダリング時にその結果を反映させます。そのため動的な光源計算には向いておりません。
最近は何でもかんでもテクスチャにデータを入れます。昔はモデルの表面の絵をシールのように張るだけでした。今は光や法線情報、計算結果などを入れています。画面に出ている絵は、こねくり回した最終形態の一枚のテクスチャみたいなものです。
話を本題に戻して、大気散乱シミュレーションの話です。
大気圏外から入ってくる光を減衰させながらスクリーン上の一ピクセルまで計算する感じです。レイリー散乱、ミー散乱等があります。
レイリー散乱は、光源からの光が長距離大気中を通過すると赤くなっていきます。夕日のように地平線が赤くなるのは、光が長い距離大気中で減衰されるためです。
ミー散乱はプログラム的には太陽を書いています。結果的に太陽になってくれるので助かります。大きさも決まります。主に大気中の粒子にあたって光が散乱するイメージです。
両方足して空の色を決めます。そこからモデルに投影する光を球面調和関数を使い計算していきます。とても時間のかかる処理なので、事前に計算してパラメーターを求めます。詳しくはGPU GEMS2 16章を見るとよいです。
ソースも公開されています。本ではバーテクスシェーダーで実現していますが、ピクセルシェーダーで表現するほうがきれいです。当時よりグラボが進化したため実現できています。
肝心なのはカメラの位置とカメラの向き上の大気圏までの距離を計算することです。
カメラから外周までの距離は
sqrt(OuterRadius*OuterRadius – rayPos*rayPos + pow( dot( rayPos, rayDir ), 2 ) ) – dot( rayPos, rayDir );
です。これにrayDirをかけて、rayPosを足せば、外周の交点が出ます。
この式とオリジナルソースを合体して、天球を描画するときれいな空ができます。
雲の減衰までできればいいんですけどね。
コメント