光の効果まとめ

まえがき

今、マイクラみたいな見た目のゲームを作ろうとしている。

ブロックを大量に配置して……とやるわけだが、なぜか壁で四方を囲まれた空間が真っ暗にならない。調べて出てきたページ(https://ekulabo.com/scene-environment-light)によると、

>Sceneが真っ暗にならないのは環境光が原因

ということで、当該記事にて世界を闇に包む方法が書かれているが、環境光をどう利用するかという情報が自分にとって足りない。

Unityの公式リファレンスも怪レい日本語と唐突に入る英語が並びがち、画像が少ないがちで見る気が起きないのでまとめることにした。

ちなみに付け焼き刃で自分のためにメモで書いているので間違った記述があったらTwitterなりで指摘してもらえるとありがたい。

パフォーマンス的な話(あんま関係ないので読み飛ばしてOK)

Unityはデフォルトでフォワードレンダリングを行う。これは各オブジェクトについてどう見えるか計算を行った上でそれらをスクリーン上に配置していくような手法だ。一方でディファードレンダリングはスクリーン上の各ピクセルについて深度、法線ベクトルを計算してから光源を考慮した見た目の計算を行う。

フォワードレンダリングは光源が増えれば各オブジェクトについての計算数が増えるので、二次関数的に計算量を増やさないためにも光源の数を絞る必要がある。動きのない光源・オブジェクトなら見え方を予め計算しておくこと(ベイク)ができ、計算量を減らせる。

ディファードレンダリングでは先に空間的な情報を算出してしまうので不透明情報を計算するのに工夫が必要で制約がかかる。

詳しいことはここを参考。

デフォルト状態

これが何も考えずにブロックを配置した状態。Unityらしいのっぺりとした印象を受ける。

ちなみに今回光源オブジェクト(DirectionalLight,SpotLight)はすべてNoShadowsにしているのでモノに遮られたときの影が考慮されていない。

光を全部切った状態

後ろにSkyboxが見えるが、これは何もない場所の背景として使われているだけで設定しないと光を及ぼさない。

DirectionalLightのみ

立方体での全く光が当たらない面の方向が真っ黒になっているのがよくわかる。

2つ目の画像から露骨にわかる通り、光源オブジェクトの位置は関係な。こういった向きの光がワールド中に遍在しており、面の向きだけを見て反射光が考慮される。そもそも光が当たらない部分は真っ黒だが、光が当たる部分ではカメラとの位置関係によって明るさが変わって見えている。当たり前か。

ついでにSkyboxの見た目も変わる。

SpotLightのみ(デフォに置いてなかったやつ)

SpotAngleを70、Intensityを5にした。

距離に応じて明るさが変わる。

EnvironmentLightingのみ

薄ぼんやり色がつく。

1枚目はSkyboxをソースとしているので上面が青っぽく、側面が少し明るめになっている。

2枚目はColor(赤単色)をソースとした。面の向きによる違いがないので地面に穴がないように見える。

3枚目はGradient(意味:勾配)をソースとしたもの。3つのパラメータを上からR,G,Bそれぞれ単色にした。角度によってこれらがブレンドされるので、パラメータによってはSkyboxと似た雰囲気を与えられそうだ。

4枚目はSkyboxのIntensityを3(デフォは1)にしたもの。元から白いものは簡単に白飛びする。全体的に白っぽくなるものだから、カメラのフラッシュを炊いたらめちゃくちゃ明るくなっちゃった、という雰囲気は出る。

EnvironmentReflectionsのみ

ここではSkyboxを使用。明暗しかつかないように見えるが実はうっすら色がついている。マテリアルの色が出ないあたり乱反射というより反射光をみるものだろう。

原理はよくわからないが、面の法線に対して垂直に近いほど明るく見える。これにより丸っぽい物体は輪郭がはっきりして見える。

まとめ

ということで、これらを適用するとやっとこさいつものUnityの画面になる。

EnvironmentLightingは完全な暗闇にはさせない程度の明るさ付け。
EnvironmentReflectionsは太陽があることが前提の輪郭わかりやすさ光。
光源オブジェクトは太陽やライトなどの露骨に明るいものの再現。
そしてそこにオプションで影がつく。物体の位置関係を計算するので工夫しないとかなり重い。

これらの効果を理解して設定すれば意図どおりのライティングができるんじゃないでしょーか。

いかがでしたか?

追記

2021/10/29

レンダリングのお勉強をしたところ、ちょびっとだけそれぞれの役割がわかった気がする。

簡易なライティングにおいては拡散反射光(ディフューズ)、環境光、反射光(スペキュラ)の3つが実行される。

拡散反射光と反射光はUnityでの光源によるものに対応する。

一方環境光はどちらかというと見栄えで、光が全く当たらないところが一律(0,0,0)でのっぺりしてしまわないための光っぽい。