Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
宇治社中 〜平行光源によるライティング〜
[go: Go Back, main page]


平行光源によるライティング

副題:さよならワイヤーフレーム


■物が光るということ

物が見えるということはどういう事でしょうか。その点での光が眼に入るからです。その点での光は大きく4つの構成要素から成っています。環境光、拡散反射光、鏡面反射光、透過の4つです。では、その構成要素を1つずつ見ていくことにしましょう。

環境光(Ambient light)は、常にそこにある光を言います。陰になっている部分でも、うすぼんやりと光っているのです。真っ暗な部屋でも眼が慣れてくるとぼんやり見えますね。全くの闇は存在しないといえば肯けるでしょうか。そういった光です。実はこれが、画面全体のトーンを決めるのに重要な役割を果たしています。野外でのロケ撮影と屋内でのスタジオ撮影は一目で区別できますもんね。

拡散反射光(Diffuse reflection)は、最も大切な光です。これが物の色をつかさどっているとも言えます。光源からの入射光が一様に(拡散)反射されてこの光が生まれます。式を見てみましょう。

Ld = Kd*Ip*cosθ

ここで、Kdは拡散反射係数、Ipは入射光の強度、θは面の法線と、光源に向かうベクトルとの成す角です。この時点で外積や内積の出番の匂いがしてきますが、ここではKdに注目してみます。この拡散反射係数は0〜1の値を取り、物体により決まっているとされています。それより解りやすいのは、色のパラメータとしての存在でしょう。

Lr = Kr*Ir*cosθ
Lg = Kg*Ig*cosθ
Lb = Kb*Ib*cosθ

と書けば、感の良い方は成る程なと思われることでしょう。もちろんrgbは赤緑青を表しています。そうです、世の赤い物体というのは、KgやKbが非常に小さく、黄色の物体はKbが非常に小さい物を言うのです。(注:正確には吸収された入射光の残りが拡散される訳で上記の説明は誤りです。色をつかさどるのは拡散反射係数ではなく各色に対する吸収率です。ここでは便宜上拡散反射係数により色が変化しているとして話を進めています。)

鏡面反射光(Specular reflection)は、その名の通り、鏡のように眼を直接射る光を言います。先ほどの拡散反射光が視点が何処にあろうと、誰も見ていなくても存在するのに対し、この鏡面反射光は違います。入射光の一部は吸収され、散乱し、残りの一部は、鏡に差し込んだ光のように正反射方向に反射します。この反射方向と視点の方向をφとして、

Ls = Ip*ω(θ)*(cosφ)^n

で求められます。ここでωは物体特有の鏡面反射率を求める関数であり、nはハイライトの広がりを示す係数です。この鏡面反射光により、金属っぽい感じを出せるのですが、今回はあまり触れないで置きましょう。光源と法線と視点の絡む計算なんて、ぞっとしませんからね。

透過光(Transparency)はもっと特殊です。ガラス等の色は単独では決められません。その後ろにある物の色も影響してくるからです。

Lt = Kt*Iq + (1-Kt)*Ip

として表され、Ktが透過率と呼ばれるものです。Iqは後ろにある物体の光の強度です。これも今回はあまり触れないで置きましょう。Ktが0の物体が、つまり不透明な物体であることを認めるだけでも大丈夫です。

これらの4つの色が合成され、ある点の光Lが求まります。

L = La + Ld + Ls + Lt

■面の色を決める

では、実際に実装に取りかかりましょう。面の色 Lを求めるにはどうすれば良いのでしょうか?話を簡単にするために、今回は環境光と拡散反射光だけに絞りましょう。すると、

L = La + Kd*Ip*cosθ

ということになります。先程少し触れたように、ここは内積の出番でしょう。

面の法線ベクトルnは手に入っています。次に光線ベクトルlを求めれば間のcosθは容赦なく求まります。どちらも単位ベクトルだとすると、

v・l = cosθ

ですね。代入して以下のような式を作ると、

L = La + Kd*Ip*(v・l)

これで、その面の光具合が求まります。

■光源について

次に問題になるのは、光源ベクトルの求め方です。光源にもいくつか種類があるのですが、今回は一番シンプルな平行光源に関して説明してみましょう。平行光源とは無限遠にある光源のことで、例えば太陽光のような物を指します。この光源が実装上一番楽であることは容易に想像がつくと思います。なんせ、光の方向が一方向であるので、一度定義して単位ベクトル化してしまえば、全ての面の色計算に関してこれを利用出来るのですから。

で、前回裏面消去の時に利用した逆変換と同じ方法が使えます。光源ベクトルを、カメラ行列に相当する回転をさせた物を用意しておいて、視点ベクトルに掛けた逆変換と同じ逆変換をすれば、オブジェクト座標と同じ土俵で内積を求めることが出来ます。

ただし注意点として、内積の値が負の値になった場合は、すこし話が違います。その場合は、光に対して面が背を向けていることになり、上記の式では光が求まりません。それどころか負になってしまいます。こういう時は代わりに次の式を使います。

L = La

いわれてみれば、当然ですね。光が当たっていないのですから。

■まとめ

では、ここまでのサンプルおよびソースを付けておきましょう。

サンプルバイナリ(42.2KB)

サンプルソース(13.0KB)

前回と殆ど変っていないので、見るべき所は少ないかも知れません。気が向いたらで結構です。

また、ここで用いている、面の色でポリゴンを塗りつぶす方法は、フラットシェーディング(Flat Shading)またはコンスタントシェーディング(Constant Shading)と呼ばれる方法です。次回からは当然のようにこう呼びますので、覚えておいていただきたいと思います。


<戻る>

devilman/team-UJI 1998/07/26