traP Advent Calendar 19日目、phi16です。まさしく光について書きます。はい。
視界
人間が風景を視認している原理は、「目に入ってきた光がレンズを通して受光器を発火させること」です。まぁそれだけなんですけど。
これを丁寧に解釈するといろんな現象が理解できるのです。みんなもPhysically-Based Renderingやろう。私はやらない。
あと感覚で書いてたりするので間違いの指摘とかあればよろしくおねがいします。
眼の中身から風景の方へ解説していきます。
光
波です。みんなしってるよね。波動説のあれ。
三原色
光の三原色というのは良くいう話ですが、この「3」はどこから出てきたのでしょう?
答えは人間の網膜には3種類の錐体細胞が存在しているからです。わかりやすい。
それぞれ長波長/中波長/短波長の光を受けた時に発火し、これが赤・緑・青に対応します。
網膜内に大量に存在して(でも600万ぐらいらしい)、それぞれが視界の「画素」になっているのです。
一部だけ頭内部への接続のために錐体細胞が存在しない場所があって、それが盲点ですね。
錐体細胞はある1つの波長にだけ反応するのではなく連続的なものなので人間には自然に連続的な色が見えます。
なので、「黄色570nm」と「赤640nmと緑500nmと青450nmを適切に合成した光」は人間には区別ができません。
また「白」は「全ての可視な波長を均等に含む光」のことですが、人間的には「三波長の合成光」と「全波長を含む光」を区別できません。3種の細胞がいいかんじに発火さえすれば白に見えます。
区別できなければ考えなくて良い・・・と思わなくもないです。実際通常PC内では三色で考えられています。
でも実際の光の屈折を考えると中間の色を入れないと綺麗に色が出ないのです。波長によって屈折率が変わるので。
適当につくってみたのですがあばうとにわかってくれるとうれしいです :
あと人間には明るさだけをとる桿体細胞があるわけですが、基本的にはこちらの存在は無視されている気がします。
なので桿体細胞のシミュレートを適当にやったらなんかおもしろいものができるかもしれません。具体的には暗いけど見やすいシーンがつくれるかも。知らないけど。
レンズ
知っての通り人間の目には水晶体と呼ばれるレンズが存在します。こちらは外からくる光を屈折させて内部のガラス体を通して錐体細胞に光を届ける働きを持ちます。
レンズには焦点がつきもので、焦点のあったところに綺麗に像ができます。人間の水晶体は筋肉によって変形することができて、実際「物がくっきり見える」のは網膜にその物体の綺麗な像ができるようにレンズが変形されている状態です。
ここから生まれる視界の現象は、ボケです。焦点が合わなかったら、ボケます。ミニチュア写真とかわかりやすい。
そういえば眼鏡は水晶体の代わりをするもので、ボケないようにいい感じに屈折させてくれるやつですね。たぶん。
ボケを再現するにはレンズをシミュレートすればいいんですが確率的サンプリングとかやらなきゃいけなくてつらいので大体はぼかしでそれっぽくやります。
あと確率的サンプリングを行う際に虹彩/絞りを考慮すると円形ボケじゃないのができます。
物の色
本題です。色って何でしょう?
りんごは赤、ぶどうは紫とは言ったものの、例えば鏡にはちょうどいい言い方ができません。
結論から言うと「波長・入射方向・反射方向などに依存して決まる反射率分布」です。反射率です。
現実には能動的に光る物体はあんまり無いです。ありますけどエネルギーを消費しますよね。
まぁそれでそのような能動的発光物体からくる光が眼の方向に反射してきたとき、眼に色として知覚されます。
例えば700nm付近の光を強く反射(といっても増幅はしない)反射して他の光を吸収しやすいような物体は「赤」に見えます。
CGではよくBRDFという「波長・入射方向・反射方向」に依存する反射率分布をよく用います。
これには材質の情報も埋め込まれてて、「色」と「材質」にはあんまり違いが無いということがわかります。
※擬似図(入射角固定,反射角固定でもある)
例えば金では鏡面反射させた方向に強く反射し、粘土では方向に依存せず光を反射させ、金属光沢となるのです。
光沢についてはWikipediaの鏡面ハイライトの項目が詳しいです。ふつうに役にたつ。
いわゆる「色」っていうのは波長毎の反射率の比なのかもしれません?鏡のようにあからさまに鋭い場合を除けば反射光は混ざって平均的な色をつくるはずです。
そういえば金属にも屈折率ってあるんですよね。しかも複素数になっちゃったりおもしろい(詳しい話しらない)。
ゲームなどではBRDFを大雑把に「拡散」「反射」で分けることが多いです。まじめにやると計算量(ry
実際の所Phongの反射モデルでそれっぽさは十分でているので十分という話もあります、が、後述。
鏡の色は?って聞かれたら「入射方向と反射方向が鏡面反射で一致するときにインパルスを持つデルタ関数による分布」って答えればいいんだとおもいます。
大域照明
Phongの反射モデルにおいては、実は「拡散」「反射」に加えて「環境」が加えられています。式としては「自己発光」になってしまいますが、これはなんなのでしょうか?
実は、現実世界にあるのは「能動的発光物体から直接きた光」だけではないのです。まぁ物体から反射した光見てるんですからあたりまえなんですけど。
物体で反射した光はまた別の物体に衝突し、またBRDFによって異なる方向に確率的反射していきます。これが間接光となります。
昔のゲームでの単純な光の近似では間接光を表現することができなかったのである程度の間接光があることを前提とさせたわけですね。しかたない。
光源からでた光は何度も反射し、減衰していきます。その結果「風景」は定常状態に落ち着きます。それを表現するのがレンダリング方程式で、これを直に計算しようとするのがラジオシティ法ですかね。
本来なら眼はどこにあっても「風景」は(方向依存を含めば)定常のはずですが、計算資源的につらいので拡散だけを考えていることがほとんどです。そうすると空間の1点に1色が定まるので式が楽になります。まぁそれだけで十分ともいえます?
大域照明をやるとリアルにしかみえなくなります(個人差)。でも実際にリアルタイムでBRDFから計算するのは計算資源がつらいのでベイクするのが一番でしょうか。
LightProbeの技術とかもあるし最近はそんな感じで綺麗なゲームも多いですね。がんばってください(丸投げ)。
影と陰
わかるとおもうんですけど、影/陰って、作るものじゃなくて元々存在するものなんですよね。
最初が黒(エネルギーがない)なので。光が来ないから影が生まれるのです。おもしろいですね。
影と陰には一般には違いがありますが物理現象としては「光が来ない」だけで同じことです。
影は他の物体に遮られて光がこないこと、陰は元々光が来にくい場所にあることかなと思います。
光を再現すると影は勝手にできます。いぇい。
散乱
実はBRDFだけでは不完全です。まぁ。
例えば「蝋」は、一度来た光は内部を通って複雑な屈折をしてまた外に出てきます。このような現象を散乱といいます。
言ってしまえば空とか霧とか夕焼けとか全部散乱です。さらには牛乳もめっちゃ散乱してます。
ですが、CGの面で一番重要な散乱は、「人間の肌」です。重要性をわかってくれるとおもいますが。
散乱は「透明感」につながり、人間の肌が結構明るい色をしているた(全体的に)ことを表現するには必須です。
肌が肌らしいのは中を光が通っているという「透明感」があるからです。なんかCMにもありそう。
手を太陽にかざすと端のほうが赤くなるのは赤色は散乱の影響を受けにくいからで、夕焼けと同じ原理です。たぶん。端すぎると普通の色に戻るし。
BRDFだとダメなのは反射しか考えてないからです。屈折を真面目に考えると多分こうなるのかな。
で、これをどうやって再現するかですが、細かいことをやるとするとBRDFの代わりにBSSRDFを使えばいいということになるんですが、つらいです。
大体は距離とかに散乱度がおおまかに依存することを使って擬似的に求めてる感じです。表面下散乱(SSS)とかいいます。
あきらめてHalf-Lambertのように経験則を使うのもアリかとおもいます。
まとめ
とりあえず光が実際にどうなっているか、いろいろかいてみました。資料とかは調べると結構slideshareが出てくるのでみるといいです。おもしろいこと結構あるので。
あとPBRをやるには確率とか測度っぽいものとかいろいろやっとくといいんだと思います。でもなんだか最近は焼きなまし的なものを使ったりもするみたいなのでまぁ いろんなことに詳しくなろう。
ただもう一つ、個人的におもうのは 「リアルな絵」はがんばってシミュレートすれば出るけど、逆にリアルじゃなくて綺麗なもの(Rezとか)を作るには経験?とかいろいろあるのかなとか。
というわけで、「綺麗なものをつくる」という目標には、きっとRealisticとNon-Realisticがあるのです。どっちも良いとおもうので自由につくれるようになりたいですね。
みなさんも「ゲームの絵作り」がんばってください。