2014年5月30日金曜日

NUKE Normalを使ったLambertShaderの再現

昔の記事で少し触れましたが、改めて。

ランバートシェーダー。
CGで最も基本的な物体に陰影をつける手法だそうです。

http://asura.iaigiri.com/OpenGL/gl29.html

RenderManのお勉強(Surfaceシェーダ編1)

(勝手に掲載すみません・・・)

なんか、よく分かりませんがある面に対する法線と光源の向きのcosθを求めればいいっぽいですね。点光源は難しそうなので、平行光源で行こうと思います。




 ということで3Dソフトから法線情報をexrで出力。アンチエイリアシングはかけて出力しました。

exr使ったのはフロートではない画像形式にすると値を0-1に収まるように色々工夫しないといけなかったり色々あるので・・・。

Worldとしたので、シーンにおける面の向きっすね。Normal vectorなので、正規化されたベクトル。いわゆる単位ベクトルという事になるようです。
Normalizeと勘違いしました。法線ベクトルです。正規化させた法線の向きのベクトル情報だそうです。

こんな感じ。黒いところにはマイナス値があります。

こんなイメージ。四角の右上が[1,1]で左下が[-1,-1]です。

 
光源の向きですが、コンスタント作ってスポイトで上の画像からピックすることで取得するようにしました。スポイトで吸い取った面に垂直に光が当たっているというイメージ。
NUKEの3Dシーンでライト作って原点からのライトの方向の単位ベクトルを計算してもいい気もします。




これで、「面の向き」と「光源の向き」の2つが手に入りました。

 「二つのベクトルが単位ベクトルとなっていれば、内積の値そのものが2つのベクトルのなす角のcosの値となります。」ということですので

A(x,y,z) 、B(x,y,z)の2つのベクトルの内積は

cosθ= Ax * Bx + Ay * By + Az * Bz

という事になるんでしょうか。
MergeExpression使って計算してみます。

出来た

最初に紹介したブログにハーフ・ランバートの解説もあったのでやってみました。(MAYAのビューポートこれですか?とても綺麗に見えます。MAXのビューポートは如何にもランバートっぽいです。)

多分出来てる・・・。
 
こんなイメージ。緑の線ですね。

あれ?でも、これランバートの値を0.5リフトすれば同じじゃないか?ということでやってみた。
合ってるかどうかの自信はないけど、数値は同じになった。
コンポジットソフトではそのまま使う事はないですし、こっちの方が使い勝手よさそうですね。光の強さもGainとかで再現出来ますし。black clampあるのでついでにマイナス値も切ってくれますし。

 後は、拡散反射光を乗算してみたり、マスクとして使ってみたり、マスク使って必要な所を取り出してみたりお好きなように。スポイトでノーマルから色を拾うとき、2画面に分割しておくと便利です。

カメラからの法線情報も出力しておけば、スペキュラーとかも入れれそうですね。 フォンモデル。

---------------------------

追記:後で気づいたのですが、画像からピックする方法だと逆光が出来ませんね。簡単な方法としてconstatのカラーパレット開いてRGBの数値を調節するのはどうでしょうか?正規化されたベクトルではなくなってしまいますが、感覚的に使えるのでこれはこれで便利かなと。

今回のnormalmapの場合

R 光源が横方向に移動
G 奥行き方向に移動
B 高さ方向に移動

という感じになるかと思います。



[1,0,0] 右側から
[-1,0,0]左側から
[0,1,0]奥から
[0,-1,0]手前から
[0,0,1]真上から
[0,0,-1]真下から

です。
 -----------------------

ランバートの情報にトーンカーブを使ってBRDFをいじってる気分でちょっとだけ遊んでみた。
トゥーンっぱくしてみたり

メタリックっぽくしてみたり

マイナス値を利用して補色っぽいトーンにしてみたり
 ノーマル、ボディのマスク、オクルージョンで色々遊べそうですね。

 -----------------------

調べてから書けばいいのですが、3dsMAX標準の淡いNormalや整数でやり取りしたときのものについても少しだけ。
全く自信ないですが、多分こんな感じになってると思いますので
-0.5オフセットして
2倍にすれば最初のノーマルと同じになる気がなんとなくします・・・。
簡単にテストしてみると一応出来ているっぽいです。

0 件のコメント:

コメントを投稿