他の人が描いたレイマーチングを魔改造する。(ライティング編)
HAI DO-MO!さやちゃんぐbotです。
この記事はシェーダーアドベントカレンダー9日目の記事として書かれています。
8日目はたなかゆう先生による「高さでグラデーションをかけるシェーダーをUnityで作ってみた」でした。
今日の記事は「他の人が描いたレイマーチングを魔改造する。(カメラ編)」の続編として、ライティングについて扱っていきます。
それでは始めていきましょう!
いまいちなルック
先にちょっとUnityでシーンにキャラを置いて見てみましょう。かふじさんのモデルをライト1灯で照らしてみます。
いまいちなルックです。あるある!割と良くやりがちです。
これをなんとかする方法はないでしょうか?
なんかマシになりました。単にライトを明るくしただけです。とてもシンプル。
「明るくしろ」
とてもシンプルな結論がわかります。
とは言えども、ライティングはある程度わかってくるまではむつかしいものかもしれません。ライティング&レンダリングには「ライティングの初心者は(ライトの使い方がわからないため)、見た目を安定させるために全体を暗くしがち」といったことが書かれています。
ならばライティングについて少し調べていきましょう。ライティングを知らないがために、かわいいキャラを台無しにすることは避けるべきです。
そして、レイマーチングでもルックを向上させるには、ただ明るくするだけで効果があるのです。
ライティング
「ライティングとはどうするのか?」ということを、ライティング&レンダリングから読み取ってみましょう。ポイントだけざっと読みたい方は、以下のScrapBoxにまとめてありますので眺めてみてください。
まず知るべきは、ライトの「デバッグ」は1灯ずつ行うということです。ライトを調整する時には、確認したいライトのみを有効にし、他のライトを無効にします。グローバルイルミネーションを使っている場合にはそれも切ります。
レイマーチングでも同様です。着色(マテリアル毎に色を決定する、空に色を付ける、HSVで距離に応じてフラクタルに色をつける)、フォン、ランバート、カメラからの距離やループ回数によるフォグ、SSS、AOなどをレイマーチングで実装することができます。
ここで色と明るさを加算したり掛け算したりしますが、複数の明るさが混ざった状態で調整することは難しいことです。ひとつのライティングを調整する時は、他の行をコメントアウトします。
三点照明
シーンに照明を配置するセオリーに三点照明があります。
三種類のライト…キーライト、フィルライト、バックライト(リムライト)を配置することで、シーンを効果的にライティングすることができます。現実世界での映画の撮影などだけではなく、3D CGの世界でも使う手法です。
・キーライト
キーライトはシーンの中で最も明るいライトです。昼間の屋外であれば太陽光がキーライトとして扱われ、屋内のスタジオで撮影する場合には部屋を最も強く照らすライトです。
キーライトとカメラの角度は変えて配置します。シーンを上から見下ろすと、キーライトとカメラは被写体を中心に例えば50度くらいあけておきます。
・フィルライト
フィルライトはキーライトの向きと逆側の陰になる部分を補助的に照らすライトです。キーライトからカメラに対して反対側にフィルライトを配置します。
ここまでのライトの配置はイメググると出てきます。こんなかんじです。
・バックライト/リムライト
リムライトはカメラから見て向こう側からキャラクターを照らし、輪郭を明るくするライトです。背景とキャラクターを切り離す効果があります。光の性質で、遮蔽されていても端から光がまわりこんできます。
3Dシーンでは、おそらく単にライトを置くだけではリムライトを実現できないでしょう。マテリアルにSSSを実現するシェーダーを割り当てる必要があります。
・バウンスライト
バウンスライトは対象を直接ライトで照らすのではなく、別の向きに設定して壁の反射などから間接的に照らす手法です。フィルライトの一種と言えます。
バウンスライトは壁や床に向けた光源を利用するか、GIによって実装します。
バウンスライトはスペキュラーを放出しないようなライトオブジェクトです。実は瞳のハイライトはスペキュラーではなく、床全体に反射したソフトな間接光によるものということは、初めて知ると驚くかもしれません。
・スピルライト
スピルライトはキーライトよりも暗い、ソフトな光です。キーライトが描く輪郭を補佐する役割を持ち、キーライトに近い方向から被写体に当てるよう配置します。
キャラクターが顔をそむけてキーライトが照らす範囲が少なくなる場合、スピルライトで補えば、顔のより多くの部分をライトで照らすことができます。
・キッカーライト
キッカーライトは輪郭を強調するライトです。リムライトよりもさらに外側に配置します。
左右にキッカーライトを配置する場合、左右対称にするのは推奨されません。この対応としては、一方のキッカーライトをより明るくしたり、リムライトと組み合わせることなどで、より自然に見えるバックライトにできます。
・スペキュラーライト
スペキュラーライトはディフューズを放出しないライトオブジェクトです。十分に光が当たっているシーンにハイライトのみを追加する用途で利用します。
ライトオブジェクト
3Dツールでは、典型的ないくつかの種類のライトオブジェクトを利用することができます。ここで紹介するライトは、多くの3Dツールでたいていは同じ名前のものが利用できます。
・ディレクショナルライト
ディレクショナルライトは太陽を模したライトオブジェクトです。平行な影を作り、減衰しません。
レイマーチングでディレクショナルライトを実装するには、正規化された三次元のベクトルを用意するだけです。とってもかんたん。
・ポイントライト
ポイントライトは360度全方位に光を放出するライトです。
カメラからレイの進む方向をポイントライトのベクトルに使えば、レイマーチングで動く光源を簡単に作ることができます。
・スポットライト
スポットライトは円錐状に光を放出します。
・エリアライト
エリアライトは平面形状の光源です。
レイマーチング
ここからは、Gam師のメンガーに手を入れたものを例に、レイマーチングでのライティングをバラしていきましょう。
色とライトを実装しているのは、6行です。コメントアウトして確認していきましょう。
HSVでの着色
座標をHUEにしてHSVで色をつけています。一定の範囲でバウンディングボックスとするイメージです。
float dv=32.;
float ind=(ceil(mod(p.x,dv))+ceil(mod(p.y,dv))+ceil(mod(p.z,dv)))*1.618*.1;
フラクタル、fold rotate/pmodといった空間の折り畳みでディテールの複雑な形状を作ったものとHSVの相性は良いです。
ただし、HSVを適用しただけでは色の調整はやりづらいため、フォグなどと組み合わせます。
色反転
1から色の引き算をして色をネガティブ化した状態を確認します。動かす時には時間を使って反転していないものと切り替えると面白いルックになります。
ループ回数によるフォグ
レイがオブジェクトに衝突するまでにかかったループ回数を色に足して明るくすると、奥の遠い箇所が光の中に消えていくような派手な見た目に一変し、ディテールの部分が明るくなって急にルックが向上します。
手前の箇所については、「込み入った箇所が明るくなる」ため、AOの逆のようにはたらいています。引き算に書き換えるとAOに近くなりますが、レイマーチングでは非現実的に明るくした方がたいていはナイスルッキングです。
距離によるフォグ
レイが衝突した座標の原点までの長さをもとに明るさを増やします。
明るくしよう!
レイを突き抜けさせるSSS
オブジェクト形状の端の方に何やら明るく透けるような光が増えました。何が起きているのでしょうか。
c+=clamp(dScene(p+1.2*rd).x*1.2,.0,1.);
レイが衝突した座標からさらにレイを進めた座標を求め、そこから距離関数で求めた距離を明るさに加えています。もし、オブジェクトを突き抜けた場所であれば、距離関数は1に近い値になるでしょう。つまり、オブジェクトの薄い場所ほど明るくなる効果があります。
蝋のように明かりが透けて見える、SSSのようなルックをこれで作ることができます。
レイを引き戻すAO
上の実装とは逆に、レイを手前に引き戻してから距離関数を求め、明るさに加算します。ここでは求めた距離から0.5を引いているため、負の値になる場合があります。全体的に暗くなりましたが、印象的な色の濃さを増しています。
c+=clamp(dScene(p-2.4*rd).x*.8,.0,1.)-.5;
形状が込み入ってる箇所ほど距離関数で求まる値は小さくなり、明るさを減らします。これはAOとしてはたらきます。
いかがでしたでしょうか。
レイマーチングでのライティング手法をいくつか紹介しました。とにかく明るくするということはそれだけで正義だということがおわかり頂けたかと思います。
レイマーチングを写経する時に、このライティング手法のいくつかを取り入れればたいへん楽しく魔改造がはかどります。
どんどんシーンを明るくしていきましょう。
アドベントカレンダー明日10日目の記事はvakさんによる「[UE4]徐々に石化するシェーダーを作る+5色マスクとかおまけ」です。
ではでは。