Unityは2Dゲーム作成ツールとして触っていましたが、3Dは鬼門でした。なんだかよくわからない、、、。
サンプルを作ることはできるのですが、全体像が分からないため、何がどうなっているのか今一わかっていませんでした。その状況を打開すべく、素人なりに調べてみた結果をまとめてみます。数式などは極力省いて(とういか自分が理解できなくなっちゃう)説明していく予定です。
謝辞
以下の書籍やサイトを参考にさせていただきました。一部パクリみたいになっていると思います。ご指摘いただければ変更削除いたします。
- 3D-CGプログラマのためのリアルタイムシェーダー入門
- 光と色の話(CCS株式会社)
- ここも増えていく予定です
目次(今のところ予定)
- そもそもレンダリングってなんだろう
- そもそも反射ってどんな現象だろう
- 拡散(diffuse)反射(直接光)
- 鏡面(specular)反射(直接光)
- 間接光(環境光)
- 物理ベースレンダリングについて
- 間接光について(Unityの場合)
レンダリングってなんなんだろう
表示したい物体表面上の1点に注目してみます。その点をpとします。そのpから視点vに向かって出ていく光を計算することがレンダリングです。
この画像のサイズは460x320です。ピクセル個数は147200個になります。このピクセル一つ一つが点pに相当し、各ピクセル毎にレンダリングの計算が行われて、色が決定されます(全部不透明と仮定します。透明だと同じ地点でも複数回レンダリングの計算されますよね)。ものすごい計算量ですよね。
レンダリング方程式
点pから視点vへ出ていく光を計算する方程式をレンダリング方程式と呼びます。関数名Rとします。Radiance(放射輝度)の頭文字です。
\vec{v}:視線方向のベクトルです\\
上矢印が付いているのはベクトルです。\\
R(p,\vec{v})
点pが発する光は、自分自身が発光する光$R_{emmision}(p,v)$と、他から照らされた光を反射した光$R_{reflection}(p,v)$の2つに分けて考えられます
R(p,\vec{v}) = R_{emmision}(p,\vec{v}) + R_{reflection}(p,\vec{v})
反射光(ライト1つ)
$R_{reflection}(p,v)$に注目します(自己発光は単純ですし、あんまり自分が光る物ってないです)。
点pに入ってくる光がライト1つの場合を想定してみましょう。
入射した光がそのまま反射することはありません。実際は特定の波長だけ吸収されたり、減衰したりします。材質によって振る舞いが変わります。またライトと点pの角度によっても明るさが変わるでしょう(真横から照らしても照らされない)。
点pに入射した光がどれくらい反射するか係数を計算する必要があります。その係数と入射した光を掛けて、点pから視点vに向う光が計算されます。
l = ライトの入射の向き\\
L(p) = 点pに入ってくるライトの光\\
k(p,v,l) = どれくらい反射するかを表現する関数\\
R_{reflection}(p,\vec{v}) = k(p,\vec{v},\vec{l})L(p)
反射光(ライト複数)
ゲームシーンにライトが1つしかないケースはまれです。実世界で電球を増やせば机の上の明るさが増すように、複数ある場合は足す事で表現できます。
R_{reflection}(p,\vec{v}) = \sum k(p,\vec{v},\vec{l}_{i})L_{i}(p)
反射光の反射光の反射光の、、、、
点pに入射する光は光源だけとは限りません。すでに照らされた別地点が反射した光で照らされる事もあります。もしかしたら、その別地点も、また別地点の反射した光で(以下略)。このことを「多重パスによる反射」と呼ばれます。式で見てみましょう(自己発光はないものとします)。
k(p,\vec{v},\vec{l}_{i})をkと略します\\
R(p,\vec{v}) = \sum kL_{i}(p)\\
= \sum k(\sum k'L_{i}(p')')\\
= \sum k(\sum k'(\sum k''L_{i}(p'')'')\\
= 何回必要かわからない。反射した回数分\\
ここを比較的正直に計算して高品位な画像を得ているのが「レイトレース」とか「ラジオシティ」などの手法です。しかしゲームのようなリアルタイムな物はこの計算はあまりに重たすぎます。そこで大胆にカットしたり様々な工夫をしてきました。後半そのあたりの説明ができたらなと思います。
直接光、間接光
ライトから直接地点pに入射する光を「直接光」
それ以外の様々な別地点で反射して地点pに入射する光を「間接光」
と呼びます。
間接光の計算は膨大なため、昔のレンダリングは間接光をバッサリと無視し、直接光だけを計算しました。次の回「古典的レンダリングについて」ではそこを説明しようとおもいます。