2007年9月29日土曜日

intersectRay

今回のスクリプトはまったくの初心者向けで無いですので、別ラベルにしました。
で、ずっとほったらかしの内容があります。
それはライトからライトを作ってみようという課題です。
どうしてそんなことをしたいかというと、ローカルイルミネーションでありながら、
GIのようなバウンス効果を作れないかなと考えているからです。
(ただしローカルイルミネーションではGIのように光源の形状や大きさに応じた正しいハイライトを狙うことはできませんけどね。)
アニメーションするキャラクターには向きませんが、背景では有効な気がしてなりません。
実を言うとけっこう前にざっくり試しましたが、手法を単純化しすぎたためなのか、まったくいい感じになりませんでした。PCが壊れたときにコードもどこかに無くしたみたいなので最初から書きます。
むしろ最初から書いたほうが早いです。
連載形式で試していきたいと思います。
では第一回。



MAXScriptにはすごい部品も少なくありません。
なかなか驚きなものに、レイとサーフェイスの交点を求めてしまうintersectRayがあります!
レイというとライトあるいは光線なのかと思うかもしれませんが、そういうことではなく、ターゲットしているオブジェクトに向いたベクトルの始点と方向を得るものです。テープオブジェクトでもいいということです。
こんな難しいことは私の素頭では簡単には出来ませんが、MAXScriptを使えばプイッとできてしまいます。
MAXファイルをアップできれば話が早いのですが、ファイルのアップは出来ないみたい。
このシーンではBox01というボコボコのコの字形のオブジェクトにスポットライトSpot01を当ててます。
ボコボコしているのは、平らなままだとあたった箇所の面の角度に応じた角度がうまくついているのかわかりにくいからです。
んでは、Spot01を選択しつつ以下のコードを実行します。

fn refRay lgh obj = (
local r = lgh as ray
local newLgh = freeSpot rgb:lgh.rgb shadowColor:(color 0 0 0)
newLgh.position = (intersectRay obj r).position
newLgh.wirecolor = green
newLgh.dir = (intersectRay obj r).dir
)
refRay $Spot01 $Box01

おぉ、ちゃんと交点のところにライトができました。うれしい。
あれ?向きがヘンですよ?
どうやら法線とは真反対を向いているみたいですね、これを最初から反転させる方法はまだ見つけてませんが、もし簡潔な方法が見つからなくても無理やりできなくもありません。でも出来るだけエレガントな手法に収めようとするのも美学ですのでちょっと調べてきます。

・・・とい思ったら、もうわかったわ。
fn refRay lgh obj = (
local r = lgh as ray
format "intersectRay %\n" (intersectRay obj r)
format "intersectRayEx %\n" (intersectRayEx obj r)
local newLgh = freeSpot rgb:lgh.rgb shadowColor:(color 0 0 0)
newLgh.position = (intersectRay obj r).position
newLgh.wirecolor = green
newLgh.dir = -(intersectRay obj r).dir
newLgh.multiplier *= 0.5
)
refRay $Spot01 $Box01

マイナスすれば反転。いかにもコンピュータちっくです。 けどそこがコンピュータのいいところで、もともとある情報をすぐに加工して新しい価値を生み出します。
物理的には正しくないけどついでに光の強さも半分にしてみました。
さて、物理上のことを実はわかってないんですが、今はあたった面の向きに跳ね返っているに過ぎませんが、ディフューズ面に対して拡散するはずなので、面の粗さに応じてランダムに反射するってことなんですかね?
するとランダムな角度に光が分散してはじかれて、なおかつエネルギーも失っていくってことなんですよねきっと。
それを勉強しないとなぁ。

ちょっとズルをして、手でいじってみました。できればいいんですよ絵なんだから。


なるほど、1次ライトを15度くらいに狭くして、2次ライトを180度に広げてやるとそれらしい傾向が・・・こういうのでもっといい感じになって欲しいです。

制作・©:のぼる/N.Lab