フォグ

Fog別名:霧、距離フォグ

概要

遠くのものほど、決めた色(多くは地平線付近の空の色)に近づけて描く効果。空気のかすみを表して奥行きを出すほか、描画を打ち切る距離の境目を隠すのにも使う。

デモ

デモを読み込んでいます
白い線を左右にドラッグすると、フォグなしとありを見比べられます。「フォグの色を空に合わせる」を切ると、遠くの木や建物が空とは違う灰色に沈み、切り絵のように浮いて見えます。

使われる場面

  • 屋外の風景

    遠くの山や街並みを空の色に近づけて、奥行きを出す。晴れた日の遠景でも、わずかにかけるだけで距離感が出る。

  • 霧や煙の演出

    朝霧、森のもや、水中、ほこりの舞う廃墟のように、空気そのものの濁りを表す。

  • 描画距離の境目を隠す

    遠くの物体を描かない距離を決めているゲームで、物体が急に現れたり消えたりする境目を、フォグの向こうに隠す。

  • 夜や暗い場所

    フォグの色を暗くすると、遠くが闇に沈み、見通しの悪さや不安な雰囲気を出せる。

判断基準

こういうときこうする
遠景がくっきりしすぎて、奥行きが感じられない薄いフォグをかける。色は地平線付近の空の色に合わせる。
霧や煙のような、濃く濁った空気を表したい指数(二乗)のフォグを濃くかける。手前は澄んだまま、ある距離から急にかすむので、霧らしく見える。
遠くの物体が急に現れたり消えたりする描画を打ち切る距離の手前で完全にフォグの色になるよう、線形のフォグの終わりの距離を合わせる。
フォグをかけたら、遠くの物体が空と違う色の影のように浮いて見えるフォグの色が背景の空と合っていない。地平線付近の空の色に合わせる。
谷にたまる霧や、地面をはう霧のように、高さで濃さを変えたい距離だけで決まる通常のフォグでは表せない。高さで濃さが変わるフォグや、空気の中の光を計算する表現を使う。

こう見えたら

指示の例

  • 遠くの山や建物がくっきりしすぎて、奥行きが感じられない。薄いフォグをかけて、色は地平線あたりの空の色に合わせて

  • フォグをかけたら、遠くの木が灰色の影のように浮いて見える。フォグの色を背景の空の色に合わせて

  • 遠くの物体が急に現れるのが目立つ。描画距離の少し手前で空の色に溶け切るよう、線形フォグの終わりの距離を調整して

  • 朝の森のような、もやのかかった空気にしたい。指数の二乗のフォグにして、数十メートル先がかすむくらいの濃さにして

詳細

遠くのものが空の色に近づく理由

屋外で遠くの山を見ると、近くの山より青白く、明暗の差も小さく見える。物体から目に届くまでに、光の一部が空気中の分子やちりに吸収されたり散らされたりして弱まり、代わりに周りの空の光が散って視線に入り込むためである。距離が長いほどこの入れ替わりが進み、遠くのものは空の色に近づく。絵画では、この現象を使って奥行きを表す技法を空気遠近法と呼ぶ。

フォグは、これを単純化して再現する。カメラからの距離に応じて、物体の色を決めた色(フォグの色)へ混ぜていく。

距離から混ぜる割合を決める

カメラからの距離を dd、フォグの割合を ff(0〜1)とすると、描く色は次のようになる。

C=(1−f) Cobj+f CfogC = (1 - f)\,C_\text{obj} + f\,C_\text{fog}

ff の決め方で種類が分かれる。線形のフォグ(flinf_\text{lin})は、開始の距離 d0d_0 から終わりの距離 d1d_1 までで割合を直線的に上げる。指数のフォグ(fexpf_\text{exp})と指数の二乗のフォグ(fexp2f_\text{exp2})は、密度 ρ\rho を使って距離に応じた指数関数で上げる。

flin=clamp⁡ ⁣(d−d0d1−d0, 0, 1),fexp=1−e−ρd,fexp2=1−e−(ρd)2f_\text{lin} = \operatorname{clamp}\!\left(\frac{d - d_0}{d_1 - d_0},\ 0,\ 1\right), \qquad f_\text{exp} = 1 - e^{-\rho d}, \qquad f_\text{exp2} = 1 - e^{-(\rho d)^2}

指数のフォグは、一様な空気の中を光が進むと、距離に応じて指数関数的に弱まる性質に対応している。二乗の形は、手前がしばらく澄んだまま、ある距離から急にかすむので、見た目の調整がしやすく、よく使われる。線形のフォグは、終わりの距離で必ず完全にフォグの色になるので、描画を打ち切る距離に合わせたいときに向く。

float d = length(vViewPosition);               // カメラからの距離
float f = 1.0 - exp(-pow(fogDensity * d, 2.0)); // 指数の二乗
gl_FragColor.rgb = mix(gl_FragColor.rgb, fogColor, f);

見分け方と落とし穴

フォグの色は、背景の空の地平線付近の色に合わせる。空はふつうフォグの計算の対象外なので、色がずれていると、遠くの物体が空とは違う色に沈み、切り絵のように浮いて見える。デモで「フォグの色を空に合わせる」を切ると、この失敗が再現できる。

通常のフォグは距離だけで決まるので、高さや光の向きによる違いは出ない。太陽の方向ほど明るくかすむ様子や、谷にたまる霧を表すには、高さで濃さを変えるフォグや、空気の中の光の散乱を計算する方法が必要になる。

加算で重ねる光のエフェクトは、フォグの色に近づけると、遠くほどかえって明るく浮いてしまう。加算の場合は、遠くほど足す量を 0 に近づけて、フォグに溶け込ませる。

関連