Volume & atmosphere

Volumetric Fog

ボリューメトリックフォグ

空間の霧に照明を当てて光の存在を見せる。

6 / 10

Interactive demo

Preparing the demo…

Volumetric Fog

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

空間を満たす霧に、ライトの光が当たって散乱する様子を計算し、光そのものが空間に見えるようにする表現です。普通の霧(距離で色を混ぜるだけ)とは違い、スポットライトの円錐、窓から差し込む光の筋、影で区切られた光の帯、懐中電灯の光線が見えるようになります。ホラーゲームやダンジョン、教会や廃墟の雰囲気作りに欠かせません。

ゲームでの使いどころ

  • 光の筋・光の帯:窓やステンドグラスから差し込む光、木漏れ日、雲の切れ間の光。
  • 懐中電灯・ヘッドライト:暗闇の中で光線そのものが見える。ホラーゲームの定番。
  • 雰囲気・空気感:ほこりっぽい倉庫、湿った洞窟、ライブ会場のスモーク。
  • ゲームプレイの手がかり:光の筋で出口や目的地を示す。

しくみ

ボリュームレイマーチングの一種で、画面の各画素について、カメラから(不透明な物体の手前まで)霧の中を進みます。各地点では次の 3 つを調べます。

  1. 光が届くか:スポットライトの円錐の内側か、距離による減衰はどれくらいか
  2. 影になっていないか:ライトのシャドウマップを読み、その地点がライトから見て物体の陰にあるかを調べる。これが光の筋を柱や窓枠で区切る
  3. どれだけ目に向かって散乱するか:霧の密度と位相関数
L=∑iTi⋅σs(pi)⋅V(pi)⋅p(θi)⋅Llight(pi) ΔtL = \sum_i T_i \cdot \sigma_s(\mathbf{p}_i) \cdot V(\mathbf{p}_i) \cdot p(\theta_i) \cdot L_{\text{light}}(\mathbf{p}_i)\,\Delta t

VV は影の判定(届くなら 1、影なら 0)、TiT_i はカメラからそこまでの透過率です。最後に、奥の景色を透過率で弱めて、散乱光を足します。

フロクセル方式:実際のゲーム(Frostbite、Unreal Engine の Volumetric Fog など)では、画面を奥行き方向にも分割した粗い 3D グリッド(視錐台のボクセル = フロクセル、例:160×90×64)を作り、各セルに届く光と密度を計算してから、奥行き方向に積算します。画素ごとにレイマーチするより安く、複数のライトや半透明物の霧にも対応できます。

実装のポイント

  • 深度バッファで打ち切る:不透明な物体の奥の霧は見えないので、シーンの深度から物体までの距離を求め、そこで積分を止めます。
  • ジッターと時間方向の平均:少ない歩数で縞が出ないよう、開始位置を画素ごと・フレームごとにずらし、TAA で平均します。
  • ムラのある霧:密度に 3D ノイズを掛けて時間でゆっくり動かすと、光の中を漂う霧の空気感が出ます。
  • 低解像度で計算して合成:霧は低周波なので、画面の半分〜4 分の 1 の解像度で計算し、深度を考慮して拡大します。

つまずきやすい点

  • 負荷:画素ごとに数十歩、各歩でシャドウマップとノイズを読むので重い処理です。解像度と歩数の調整が必要です。
  • 影の解像度:シャドウマップが粗いと、光の筋の縁がギザギザになったり、ちらついたりします。
  • 強すぎる霧:密度を上げすぎると、画面全体が白っぽくなり、コントラストが失われます。光の筋を見せたい場所だけ密度を上げる(局所的な霧のボリューム)のが効果的です。

デモで試すこと

  1. 暗い広間に斜めにスポットライトが差し込み、柱の影で光の筋が区切られています。視点を回して、光の円錐が空間に見えることを確かめてください。
  2. 「影で光をさえぎる」をオフにすると、光の円錐全体が一様に光り、柱を突き抜けた不自然な光になります。
  3. 「濃さのむら」をオンにすると、光の中を霧が漂います。オフにすると均一でのっぺりした光になります。
  4. 「視線方向の歩数」を下げると、ざらつきが増えます。これを時間方向に平均して消すのが実際のゲームの方法です。

References

Unreal Engine Sky Atmosphere ↗

A general reference for this subcategory.