Ambient Occlusion
3DVectorのArray対応
さて、ここからは、少し今までの方法と違う事を考えます。
前述の通り、少しランダムな値を入れたベクトルを作り出して、それをリピート処理して平均値を求める方法では綺麗な結果を得られませんでした。
そこで、複数のベクトルをArray(配列)処理できる仕組みに変えてみたいと思います。
Gradientにつながる所は大幅に変更が必要ですが、その仕組みを一旦理解できたら、それを利用すれば良いだけです。
まずは、複数ベクトルの対応からで、つないだ結果を先に見せます。
一番左下は コンパウンドになっていて Fill Interpolated Array って書かれています。
ここに今、4 という カウント数(レイ数になる) を入れていると、次のノードが Pop From Attay なので、1つArray(配列)が削除されて 3 となり、
その数のベクトルが各頂点位置から出ている、っていう図になっています。(ここのカウント数は最終的には10とか16とかなります)
これを、もう少し詳しく説明します。
Fill Interpolated Array
最初のコンパウンドが何やってるの?ですね。
仮に数字 4 が設定されていて 入って来たとします。
黄色の接続点、上(ValueA) が Y=390 、下(ValueB) が Y=30、つまり、360度で1回転に30度足した数字にあえて入っています。
つまり、目的としては Y軸360度を、入って来た数字で割った回転値分のArray(配列)を作り出している代物です。
4 の次の Maxmum には 3 が入っていて、3より下の数値にならないようになってます。
Build Array from Constant には Size も Value にも 最大値が入るので 4 で、4つの 4のArray(配列)を作ります。
Get Array Sub Indices は Array(配列)の順番数を列に入れるので、0,1,2,3 となります。
下に行って、Subtract(減算) は 1 が入っていて 最大値 から 1 減った数 3 になります。
上も下も Integer to Scalar は スカラー数字に変換し、そのままの数字が移行して、
Divide by Scalar は 0,1,2,3 を 3 で 割った数のArray(配列)、0、0.333、0.667、1 となります。
・・・つまり、どんな数字が入って来ても、その数字から 1 引いた数で割った 0 〜 1 の数値のArray(配列)を作り出します。
最後の Linear Interpolate は その割った数に相当する角度を出すので、 Y=30、150、270、390 という Array(配列)を作り出します。
この部分のコンパウンドが作製できたら、 Fill Interpolated Array という名前で コンパウンドを書き出し ておいてください。
で、次も説明してしまうと、30 と 390 って同じベクトルのことなので、Pop From Attay で一番下の列が削除され、
Y= 150、270、390 という Array(配列)を出します。
数字を増やしていっても、きれいに360度を入って来た数値から1引いた数で割った数分のベクトルを作り出す、となっています。
法線とインフィニットライト情報の追加
次は、Rotate Vector ノードを使い、各頂点の法線情報で 求めたArray(配列)ベクトルを配置します。
最後、インフィニットのライトですが、あ、と気が付きますね、1つ前の RotateVector が Z=1でした。
さーこれで、と思いきゃ、今度は HIT 側の工夫が必要です。
|
Array(配列)を0〜1値にする
Array(配列)を使った数値(マルチのデータ)が入って来るので、このようにしないとつながりません。
意味が解ってくれれば、後は使うだけなので・・・・。
では、Raycast の HIT 出力から出る値の意味を説明します。
GetArraySize は必ず 0以上 になるはずなので、=0 に絶対ならないので、
Rescale の前の If はいつも 下の if False の値が使われます。
GetArraySum はHitした総数を計算しているので、直前の If が Hit したら 1 を足していって 0〜2の値を作り出します。
そのArrayを Dived by scalar で いつも1少ない数値(ここでは 2 )で割るので、
かならず 0 〜 1 の値を作り出します。
Gradient につながる Rescale は グラデーションの0が黒なので、
逆になるようにしていて、Clamp にチェックを入れて負数にならないようにしています。
ここも前のところと同じで、ある値に1少ない数値で割ると 0 〜 1 の範囲の値を得られる
っていうのを使うのがミソのようです。
前のポリコンのライトの時の設定と同じく、GetNeighbors を使うため、
一旦 tmp データとして SetData して Get Average で平均した値を Gradient につなぎます。
コンパウンド化
そしたら、ここまでのノードのつながりを、たった 1つのコンパウンドに まとめてしまいます。
Rayの数、表面からの距離、減衰を考慮する距離、
インフィニットのライトを使用するかどうか(色も含む)グラデーションの色、ライトの選択、
は コンパウンドをダブルクリックして表示される設定画面で見えるように設定します。
その中身はこんな感じになっています。
インフィニットのライトを使うかどうかは If によって選べるようになっています。
Gradient や GetLight には Reference で接続して変更できるようにしておきます。
Ambient Occlusion with Light という名前で カテコリ Color として書き出せば、皆で使えるコンパウンドになります。
改良は、まだまだ出来そう・・・なんですね。
グループ対応のコンパウンド化
さて、背景とかに使用するとしたら、複数オブジェクト対応も必要なんだろうなと考えました。
まずは、複数のポリゴンオブジェクトをマージした場合は簡単ですよね。
グループ対応のコンパウンドの作成に伴い、もう少しコンパウンドに機能を追加しました。
Geometryとして左側の紫色の接続点がつなぐと増えるタイプにしました。
Geometry を複数接続する時は、Group Geometry ノードを使用します。
グループノードを追加したり複数接続したりすることができるようにです。
それは、コンパウンドで左側の外部入力の名前から、
プロパティー にて [マルチ-新規のポートを既存のノードに接続] とすると
接続すると、どんどん増えるタイプになりまうす。Geometry 接続点がどんどん増やすことが出来ます↓。
明るい部分と暗い部分を Rescale ノードの Targetのスタート値 と エンド値で変更できるので
それがコンパウンドから操作出来るようにしました。
Multiply Color by Scalar を self.Color へつながる途中に挟み、右側と接続しておけば、コンパウンドから操作できるようになります。
グループ対応のスクリプト
最後は、1つのコンパウンドにまとまったら、
スクリプトを使って、Group登録されているオブジェクトに
ICETreeノードの設定、コンパウンドノードの接続まで、一気にしてしまいます。
Groupに入れた複数のポリゴンオブジェクトに、まずは頂点カラーの設定だけはしておきます。
そして、Group > メンバの選択 をしておいて、以下のスクリプトを走らせます。
sub BindAOICE2OBJ( oObj )
set compound = Dictionary.GetObject( oObj &".ICETree.Ambient_Occlusion_with_Light", false )
if typename(compound) = "Nothing" then
set iceOp = ApplyOp("ICETree", oObj, siNode, null, null, 0)
AddICECompoundNode "Ambient Occlusion with Light", iceOp
ConnectICENodes iceOp & ".port1", iceOp &".Ambient_Occlusion_with_Light.Execute"
end if
end sub
sub BindGroupToAOICE2OBJ( obj )
if typename( obj ) <> "Group" then
logmessage "You must select Group."
exit sub
end if
set oGrp = obj
for i=0 to oGrp.Members.Count - 1
set oObj = oGrp.Members.Item( i )
BindAOICE2OBJ oObj
next
end sub
sub BindSelectionAOICE2OBJ( )
for i=0 to Selection.Count - 1
set oObj = Selection.Item( i )
BindAOICE2OBJ oObj
next
end sub
' BindGroupToAOICE2OBJ( Selection(0) )
BindSelectionAOICE2OBJ
|
良く使うスクリプトなどは このようにボタン形式にすることもできますね。↓
すると、全部のオブジェクトに同じICEノードが接続された状態になります。
このスクリプトも あらかじめ接続するノードが同じである範囲を考慮してスクリプトを改良し、
一気に設定してしまえば作業がどんどん楽になることでしょう。
PS,
Groupを使った複数オブジェクトの状態での頂点色設定は、1つのオブジェクトにマージしたオブジェクトに設定した場合に比べて
結果がはっきりしない、というかあまいというか、差がある場合がありました。特に真平らな面など。
マージしたポリゴンに一旦頂点色を設定して、個別へはGATORなどを使って色を移し変える、
なんてことも考えられると思います。
|
|