Volume & atmosphere

Beer–Lambert Law / Transmittance

ビール・ランバート則

通過距離と密度で光を減衰させる。

2 / 10

Interactive demo

Preparing the demo…

Beer–Lambert Law / Transmittance

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

This explanation is currently available in Japanese.

ひとことで

光が物質(水、ガラス、霧、煙)の中を通るとき、通り抜けた距離に対して指数関数的に弱まるという法則です。同じ厚みを通るたびに同じ割合ずつ減るので、1 m で半分になるなら、2 m で 4 分の 1、3 m で 8 分の 1 になります。弱まり方が色ごとに違うと、厚くなるほど残りやすい色が強調されます。

T(d)=e−σdT(d) = e^{-\sigma d}

TT は透過率(届く光の割合)、σ\sigma は吸収・散乱のしやすさ(消散係数)、dd は通った距離です。

ゲームでの使いどころ

  • 水の色と深さ:浅瀬は透明で、深くなるほど青緑になり、底が見えなくなる。水中の視界が遠くほど青くかすむ。
  • 霧・煙・雲の透け具合:ボリュームレイマーチングの基本。雲の厚い部分ほど暗く、光を通さない。
  • 色付きガラス・液体:ワインボトル、ポーション、宝石。厚い部分ほど色が濃くなる。
  • 影の濃さ:半透明の物体や雲が落とす影の濃さ。
  • 肌や蝋の透け具合:表面下散乱で、厚みに応じて光を弱める。

しくみ

薄い層 Δd\Delta d を通るとき、光は σΔd\sigma \Delta d の割合だけ減ります。層を何枚も重ねると、

T=(1−σΔd)d/Δd  ⟶  e−σd(Δd→0)T = (1 - \sigma \Delta d)^{d/\Delta d} \;\longrightarrow\; e^{-\sigma d}\quad(\Delta d \to 0)

となり、指数関数になります。密度が場所によって違う場合は、通り道に沿った密度の合計(光学的厚さ)を使います。

T=exp⁡ ⁣(−∫σ(s) ds)T = \exp\!\left(-\int \sigma(s)\,ds\right)

色ごとの係数:σ\sigma を RGB で別々に持つと、色が変わります。

物質吸収しやすい色厚いと
海水赤青緑になる
紅茶・ウイスキー青琥珀色になる
煙・すす全色ほぼ同じ灰色のまま暗くなる

指数関数の性質上、係数の小さな違いでも、厚みが増えると大きな色の差になります(デモのグラフの 3 本の曲線の開き方)。

実装のポイント

  • 厚みの求め方:単純な形なら視線との交差から、複雑な形なら表面と裏面の深度の差、事前に焼いた厚みマップ、または距離場をたどって求めます。
  • 乗算合成で安く:デモの水槽は、透過率を奥の画面に掛け合わせる(乗算合成)だけで描いています。追加のテクスチャ読み込みは不要です。
  • 係数は「距離の単位」を意識:σ\sigma は「1 m あたりどれだけ減るか」です。シーンの単位(cm か m か)が変わると、見た目が大きく変わります。

つまずきやすい点

  • 散乱を忘れる:ビール・ランバート則は「減る」ことだけを表します。霧や雲が明るく光るのは、途中で散乱されて目に向かう光があるからで、別に計算が必要です(ボリュームレイマーチング)。
  • 線形に減らしてしまう:厚みに比例して透明度を下げる(線形)と、厚い部分が不自然に早く真っ黒になったり、薄い部分の変化が大きすぎたりします。
  • 多重散乱:雲のような濃い媒質では、何度も散乱した光が奥まで届くため、単純な指数関数より明るくなります。雲の描画では補正を加えることがあります。

デモで試すこと

  1. 5 つの水槽は、厚みが 0.25 m から 3 m まで違います。海水では厚いほど赤が失われ、青緑が濃くなります。
  2. 右下のグラフは、厚みに対する各色の透過率です。赤の曲線が最も早く下がります。点は 2 m の位置です。
  3. 中身を「紅茶」にすると青が早く減るので、厚いほど琥珀色になります。「煙」では全色が同じだけ減るので、灰色のまま暗くなります。
  4. 「濃さ」を上げると、すべての曲線が急になり、薄い水槽でも色が付きます。

References

Unreal Engine Sky Atmosphere ↗

A general reference for this subcategory.