TT Lab
はじめる
学ぶ 学習パス コース

3D数学とソフトウェアラスタライザ

明るさはどこから来るのか

TT Labで続きを見る

一言でいうと

表面の明るさは、法線と光の方向がなす角度のコサインに比例します。これがランバートモデルで、内積1つで計算されます。

なぜ必要なのか

前の段階までで、三角形を色で塗りつぶせるようになりました。ところが、立方体を1色で塗ると、六角形のシルエットしか見えず、立体感がありません。人が形を読み取る手がかりは、明るさの違いだからです。

明るさをどう決めるのでしょうか。物理的には、表面に届く光の量が問題で、同じ強さの光でも、表面が傾いていれば、同じ面積に落ちる光は少なくなります。正面から受けるときが最も明るく、90度傾けば0です。この関係が、まさにコサインです。

どう動くのか

ランバート拡散反射は、次のように計算します(コードブロックの中の韓国語は、順に、表面の法線、光が来る方向、色、基本色を表すプレースホルダーです)。

n = normalize(표면 법선)
l = normalize(빛이 오는 방향)
k = max(0, dot(n, l))
색 = 기본색 * (ambient + (1 - ambient) * k)

max(0, ...)が必要な理由は、内積が負なら、光が表面の後ろから来ているからです。そのままにすると、負の明るさが出て、色が逆にあふれます。そして、ambientは、ほかの表面で跳ね返ってきた光をひとまとめにした定数で、これがないと、光に背を向けた面が完全に黒くなって、形が消えます。物理的に正確な値ではなく、大域照明を計算しない代わりに入れる補正です。

法線をどこから得るかが、次の問題です。三角形ごとに1つ置くと(面法線)、各面が均一な明るさになって、角ばった姿になります。立方体には、これが合っています。逆に、頂点ごとに法線を置いて、重心座標で補間すると(フォンシェーディング)、曲面が滑らかに見えます。球を三角形で近似するときに必要な方式です。

法線はモデル変換に合わせて回す必要があります。物体を回転させると、表面も一緒に回るからです。ただし、法線は位置ではなく方向なので、w=0にして掛ける必要があります。そうしないと、移動量まで足されて、法線が見当違いの場所を指し、物体が原点から離れるほど、照明がおかしくなります。原点の近くで試すと引っかからない種類のバグです。

アニメーションは、特別なものではありません。角度だけを変えて、同じシーンを何度も描けば済みます。ただし、回転行列を毎フレーム掛けて蓄積すると、浮動小数点の誤差が積み重なって、物体がだんだん歪むので、角度を状態として持ち、フレームごとに行列を作り直すほうが安全です。

ランバートだけでは、金属や濡れた表面の輝きを作れません。拡散反射は、光をすべての方向に均等に跳ね返すモデルなので、見る角度と無関係だからです。輝きは鏡面反射で、見る方向が関与します。フォンモデルは、光の反射方向と視線の方向の角度を、ブリン・フォンモデルは、光と視線の中間ベクトルと法線の角度を使います。どちらにしても、コサインを大きな指数でべき乗して、狭い角度でだけ明るくするのが要点で、その指数が、表面のなめらかさを表します。

そして、明るさを掛けた値を、そのままファイルに書くことにも、問題があります。画面に書かれる0–255は、光の強さに比例せず、ガンマ曲線を通した値だからです。物理的に正確であるためには、線形空間で照明を計算してから、最後にガンマを適用する必要があり、これを抜かすと、明るい所が白く飛んで、暗い所がつぶれます。このラボは、単純さのためにそのままにしますが、結果がどこか濁って見えるなら、ここを疑うのが正しいです。

現場での姿

照明が逆に見えるバグの大部分は、法線の符号です。三角形の頂点を回る順序が反転していると、外積の結果が内側を指し、そうすると、光を受ける面が暗く、背を向けた面が明るくなります。診断方法は、法線を色として塗ってみることです。(n * 0.5 + 0.5) * 255に変えて描くと、どの面がどちらを向いているかが、絵として明らかになります。

もう1つは、正規化を抜かすことです。法線の長さが1でないと、内積がコサインではなくなって、明るさが倍に跳ね上がったり、消えたりします。不均等な拡大縮小が入ったあとに、とくに生じやすいです。

光の種類も、区別しておく価値があります。このラボが使うのは、平行光源です。太陽のようにとても遠くにあるとみなして、すべての地点で方向が同じで、距離による減衰がありません。計算が最も安く、影も扱いやすいです。逆に、点光源は位置を持ち、表面の各地点ごとに、光の方向を求め直す必要があり、距離の2乗に反比例して弱くなります。スポットライトは、そこに角度の制限が付きます。ラボで平行光源から始める理由は、照明の計算で、方向がすることと距離がすることを、分離して見るためです。

そして、明るさと影は別の問題です。ランバート係数が0ということは、その面が光に背を向けているという意味にすぎず、ほかの物体に遮られて日陰になったという意味ではありません。遮蔽を知るには、その地点から光源まで、光が実際に届くかを別に確認する必要があり、それがシャドウマップやシャドウレイがする仕事です。シェーダーのコースの最後のラボで、この確認を自分で行うことになります。

次のラボですること

直方体のメッシュを作って、面ごとに法線を求めたあと、ランバートモデルで、6つの面を、それぞれ異なる色と明るさで塗ります。次に、角度を45度ずつ変えて8枚を描き、ブラウザーで回してみて、最後に、8枚を1枚につなげた比較シートを作ります。