« Making of 花火。 c03。 Comp。 | トップページ | Making of 花火。 c04。 Comp。 »

2011年10月28日 (金)

Making of 花火。 c04。 ICE / RenderTree。

c04 です。





水面に映り込む花火、というイメージは初期からありましたね。 そういう絵は美しいであろうと思えたし、しかも現実の花火大会は河川敷など水際で行われることも多いので、花火+水というのは俺にとってはごく自然な組み合わせでした。


問題は、水面を出してしまうとパーティキュラー花火大会のレギュレーションに違反しないかどうか、ということですね。やはり意識はしました。背景は指定の画像以外使ってはいけないという規則があったので。



しかし俺の場合は、背景というよりは前景として使いたいこと、水面自体に独自の質感を持たせずに素直に指定の背景を100%映り込ませるつもりであること、レギュレーションには指定の背景と花火以外のものを出してはいけないとは書いてないこと、そんなに厳密なルールのつもりで書いているわけじゃなく同じ世界観の中での花火という方向で統一したいだけなのであろうと想像したこと、などを理由に、結局使うことにしました。




いやね、ほら、俺がこのコンテスト用に何か作るなら、当然 XSI を使った 3DCG になるわけですよ。3DCG でやるからには、3D らしいカメラをやりたくなるじゃないですか。 奥行きが欲しかったり、アオったりフカンにしたり、Z を感じる絵にしたくなるわけですよ。 しかしそうなると、地面を入れられないのが非常に苦しくなるんですよね。 指定の背景画は空だけで、地面が描かれてなかったのです。

だとすると基本はアオリ傾向のカメラアングルしかできないということになります。それはあまりにもキツい。地面が欲しい。でもルール上背景に描き足すわけにもいかない。 この辺の事情が、水面を後押ししました。 まあ、これを理由に失格になってもいいやと思えたので、気にしないことにしましたよ。 当初は ICE の研究をするという目的があったし、誰に頼まれたわけでもなく勝手にやり始めたのに、作りたいものを作れないんじゃ楽しくないな、と思ったのでね。もし受理してもらえなくても、ひとり裏花火大会として Youtube かどっかにアップできるだろうしね。


大会当日のUST中継を録画したものを後から見たら、やはり水面について疑問は出されていましたね。 でも結局受け入れてもらえたようで、ありがたかったです。 っていうか、背景に月を足した作品とかありましたよね? あれについては何も言ってなかったなあ。 背景の一部を切り取ってそこから実写の人間がのぞいているなんて作品もありました。 それについても特に何も指摘はなく、むしろ賞賛されていたように見えます。  まあ、もともとバーチャルな花火大会なんだから、自由な発想で色んな花火が出てくるのが楽しいはずですから、スタッフの皆さんもあまり厳格になるつもりはなかったんだろうなあと思います。


あれれれ。前置きが長くなっちまった。
すんません。



XSI 上での作業画面はこれです。

00_xsiscreen
クリックするとでかい画像。



例によってシンプルですね。 カメラ、空背景用のグリッド、エミッタ、PointCloud、水面グリッド、水面グリッド変形用 Lattice、ライトです。 パーティクル自体は相変わらずライティングに影響されないマテリアルを持たせてあるけれど、今回は水面があり、こちらはライトに影響されるシェーディングが必要なので、ライト1灯だけ焚きました。


水面グリッドは、やけにメッシュの解像度が高い。 これは水面の波デフォーメーションを、ディスプレイスメントマップなどではなく、ICE デフォーメーションでやろうとしたからです。 ま、カメラから遠い部分はここまで細かい必要はなかったかもしれません。逆にカメラに近い部分はもっと細かくても良かったかも。





### ICE 編




このヘンな台形みたいなのがエミッタオブジェクトなんですがね。

03_emitter

カメラの視野よりも外に花火を上げてもしようがないので、見えるところだけに発生するよう、カメラの FOV に合わせて末広がりな形のエミッタにしています。無駄に重くしたくないですからね。これは花火だけじゃなく例えばモブやる時なんかも常套手段ですよね。


ただし視野ギリギリいっぱいまでのエミッタだと不十分で、少しは余分に広くしておかないとダメですね。 画面の上下左右など端っこ部分の情報量って実はすごく大事で、ここがどう見えるかによって、画面外にまだまだその要素が続いているのか、それとも画面内にしか無いのか、印象が決まってしまいます。 言い換えれば、シーン全体のスケール感や量感を担っているのは、画面の端っこだと言っても過言ではない。 黒澤明が言ったんだっけ、「1000人のモブシーンを作りたいなら1000人のエキストラを呼んでもダメだ。10000人呼んで来い」みたいな意味の格言をどこかで読んだことがありますが、名言だと思います。 だから俺も、いつも画面の端っこを気にするようにしています。


このカットの場合はまあ、そんな大げさなもんじゃないんですけどね。おそらくは無駄な重さを避けようとしただけで、シーン全体の量感とかそこまでは気にしてなかったと思います。 悪い癖ですね、そんな大したことやってないくせに大したことのようにエラソーに語り出すのは。すいませんすいません。


ICETree 全体はこんな感じです。

04_icetree_all
クリックするとでかい画像。


一番上の部分が、最初のエミッションと、そのエミッションによって発射される State 0 のパーティクルです。 こいつは花火そのものを発射するのではなく、花火を起爆するトリガとしてしか使っていません。 花火そのものは次の State1 です。State0 はレンダされることは無く、State1 を発射させるためだけに使われています。

State1 は花火本体で、State2 は花火が空間に残していく軌跡=トレイルです。


ではひとつずつ見て行きます。






●エミッションと、すぐ死ぬトリガパーティクル( State 0 )

ICETree はこれです。

10_icetree_state0
クリックするとでかい画像。




・Surface から発射

Emit From Geometry コンパウンド使ってますね。エミッタは上記の台形みたいなやつ。 で、その PPG を見てみると、

03_emissionppg

Emission TypeSurface になっています。Volume ではない。 俺、Volume があまり好きでなくて、というか、いつもいい感じの分布にさせられなくて、結局 Surface にしてしまうことが多いですね。 今回の場合も、花火1個の直径がエミッタの高さと同じくらいなので、そしてアオって見ているので、Surface で発生させるくらいが画面上ちょうど良い分布位置になったんでしょうね。↓

03_distibution



・一瞬で死に、次の State に託す

このエミッションで発射されるパーティクルは、ただのトリガです。0.01秒で死ぬようにしてあります。その死亡をトリガにして、次の State のパーティクル=実際の花火を発射させています。


なぜこうしたかと言いますとですね、Emit From Geometry で普通に Surface から発射させると、エミッタオブジェクトのポリゴン表面のどこかある1点から、1個ずつのパーティクルが発射されますよね。 でも丸い放射状の花火を発生させたいので、ある1点から1個パーティクルが出たんじゃダメなわけですよ。 ある1点の場所はエミッタ表面ならどこでもいいんだけど、その1点から発射されると決まったら、同地点から球状全方位にたくさんのパーティクルが発射されなければ、花火にならないわけです。

この 「エミッタ表面に存在する、ランダムで決まる様々なパーティクル発射地点において、それぞれの発射地点から複数のパーティクルを発射させる」 というやり方がわからなかったんですよ。 誰か教えて下さい。 たぶん、自分でエミッションシステムを作るなり、エミッションコンパウンドに潜って行ってどこか書き換えるなりしないとダメですよね?

なので今回は安直に、ダミーのパーティクルとでも言うか、トリガのためだけに存在する State を作って、そいつはすぐ死ぬことにし、死んだらその地点からたくさんのパーティクルを発射させることにしたのです。 この方式なら、Spawn on Trigger で簡単にできますからね。

ということで、上の ICETree 画像の左側にあるように、Test Particle Reached Age Limit を使ってパーティクルが死んだかどうか判断し(寿命は 0.01なのですぐ死ぬ)、Spawn on Trigger でその死亡地点から 500個のパーティクルを 180度の広がり(=球状全方位)で発射しているわけです。この500個のパーティクルが State 1 であり、次に説明する、実際の花火の本体です。


このトリガパーティクルがエミッタ表面上のどこにどのタイミングで現れるかは、ICEまかせです。タイミングの方は、後に説明する Rate のアニメーションで若干の制御はできているものの、基本的には ICE まかせになっています。 なので、本当は音楽に合わせるなど気持ちのいいタイミングで花火が出てきて欲しいし、レイアウト的にも気持ちのいい場所にだけ出てきて欲しいのですが、今回はそこまで制御することはあきらめています。 エミッタオブジェクトが1つのままこれをやろうとすると、やはり独自のエミッションシステムを構築しないとダメだと思います。


・色

花火の色は、ここで決まります。 Randomize Color by Gradient です。 0.01秒で死ぬパーティクルなのでこの State0 の色はどうでもいいのですが、次の State1 のためにここで色を決めてしまっています。 どういうことかと言いますと・・・・。


普通にパーティクルの色をランダマイズなどしてしまうと、ツブ1つ1つの色が変わってしまうので、この花火にはふさわしくありません。 1輪ごとに1色であって欲しいわけです。 なので、最初のトリガパーティクルの時点で色を決めるのです。トリガパーティクルは1粒なので、上記の Randomize Color by Gradient でその1粒の色が決まり、そしてそのパーティクルが 0.01秒後には死んで500個の State1 パーティクルが発射されるわけですが、この State1 では色を何もいじっていません。そのため、死んだ1粒の色が500個のパーティクルに引き継がれ、結果、1輪につき1色になります。


本当はこの1輪=500個で1色ではなく、500個1つ1つ色を変えたりとかやってみたかったんですが、パパっとは上手く行かずに断念してしまいました。 この1色を基準にしてあるランダム範囲で色相をずらすとかは可能なんだけど、これだとランダム範囲の中で採り得る値がグラデーション過ぎて、ガツンと全く違う色を唐突に発生させるとかが上手く出来なかったんですよね。 出てくる値を round するとかして、中間の値が出ないようにすればいいのかなあ・・・?

あと、今回はシンプルに全球状に広がる花火ですが、1回の Spawn on Trigger で複雑な花火(例えばよくある朝顔の形をした花火のような、中心部分と周辺部分で全く挙動が異なるもの)を出現させる方法も、研究せねばなりませんなあ。



Randomize Color by Gradientでは、グラデーションの中間マーカは隣り合う色のどっちかにグイっと寄せて、半端な色は発生しないようなグラデーションになっています。上の ICETree 画像を見ると、6色発生させているようですね。 

このグラデーションのインターフェースを使って、スカラ値を発生させられるかしら? 可能なら、上で書いた、中間の値が出てこない、ステップ飛び飛びのランダム値ができそうですよね。





・Rate にアニメーション

エミッションの PPG を見ると Rate にアニメーションが入っていますが、こんなFカーブが入ってました。↓

03_emissionfcurve

ランダムな上下をしつつ、後半に行くほど Rate が上がっていってますね。 おそらくは、最初に noise のエクスプレッションを設定して、それを Plot し、Plot後にFカーブエディタの HLE で全体が右肩上がりになるよう調整したのだと思います。 そしてFカーブはゼロ以下にもなっているので、その時はパーティクルが発射されません。 


つまりこのFカーブは、「ずっと発射しっぱなしだと数が多過ぎてよろしくないが、だからと言って単に Rate を低くするだけだと少ない発射がダラダラ続いてしまいこれもよろしくない。なので多く出る時と全く出ない時のメリハリをつけよう。そのために、エミッションがゼロ以下になる時間も作ろう」 という意図でやっていることになります。 


また、このカットはサビの前なので、次に来るサビの盛り上がりを自然に導くためには、このカットの後半で花火が盛り下がってはいけません。なので HLE で右肩上がりにして、後半に行くほど Rate が上がる(=花火の数が多くなる)ことにしています。まあ、ただの気分です。

1フレごとにキーがあるFカーブに Plot してさらに HLE でいじるなんて、なんだか ICE の良い部分を全く使ってないような気がしませんか。こうやって決め打ちFカーブを焼き付けてしまうより、ICE ノードの組み合わせでプロシージャルにやるアプローチを探りたいものです。 でも、往々にして、手でFカーブ描いちまった方が早かったりするんですよねー orz





●花火パーティクル( State 1 )

11_icetree_state1
クリックするとでかい画像。

花火本体です。あまり特筆すべきことはありませんね。


花火の寿命は、Randomize の結果と Turbulize の結果を Add してますね。俺、なにをやりたかったのでしょう? さっぱりわかりません。

Spawn Trails でトレイルを生み出し続けています。毎フレ50個のパーティクルを、0.02という遅い速度で、20度という比較的狭い範囲の角度に射出しています。 つまり「空間に置いていってる」感じが強いわけで、まさに軌跡=トレイルですね。

後は、毎度のようにサイズが1フレごとにちかちか変わるようにしています。






●トレイル( State 2 )

12_icetree_state2
クリックするとでかい画像。

上記の花火パーティクル( State 1 )から毎フレ Spawn されたトレイルです。




・マテリアル分岐用IsThisFuckinTrail

Aの部分ですが、Get Particle State ID でパーティクル1粒1粒の State ID を取得し、それが 2 とイコールだったら IsThisFuckinTrail という独自アトリビュートに true をセットしています。

これは後ほど説明しますが、RenderTree 上で、メインの花火の光球(つまり先頭弾=上記の State 1 のパーティクル)とトレイルで違う質感を持たせたかったからこうしています。 先頭弾なのかトレイルなのかは、State ID を取得すればわかるじゃないですか。 このトレイルの State ID は2なんだから、2とイコールならそのパーティクルはトレイルであると判断できます。 そしてその結果を元に、RenderTree 上で分岐させています。





・トレイルの色変化

B1でトレイルのパーティクルに新たな色を設定していますね。 その上流にあるB2から流れを見ると、何をしているのかわかります。



B2は Get Particle Color なので、まずそのフレームにおけるパーティクルの色をゲットしてますね。 先述のように、もともと State 0 のトリガパーティクルに与えられた6色のうちのどれかが引き継がれていて、ここで取得されます。

そして Color to HSVA で分解されます。 Saturation と Alpha はそのままいじらずにスルーさせてますが、Hue と Value はランダムな値を加算しています。

Hue を見ると、-0.005 から 0.005 までの範囲のランダム値を、元の Hue の値に加算していますね。つまり、元の Hue プラスマイナス 0.005 という値になります。 多少色相を回している=違う色にしているということです。

Value を見ると、-0.065 から -0.015 の値を加算してますね。最小も最大もマイナスの値です。つまり、元の Value の値にマイナスの値を足してやることによって、より小さい数値にするということです。マイナスを加算しているわけだから、減算(引き算)をしているのと同じことですね。 結果、Value(明度) の値が小さくなるということは、色が暗くなるということです。



こうして元のパーティクルの色から、色相を少し変え、明度を少し下げた色が、再度 HSVAtoColor で Color 情報に変換され、B1の Set Particle Color でセットし直されます。

その接続先が大事なわけですが、Execute ノードのポートに入り、最終的には State2 の Execute Every Frame ポートに入っていってますね。つまり、上記の一連の色操作は、毎フレーム行われるということです。

次のフレームでは、また B2 の Get Particle Color から始まるわけですが、そこで取得される色は、前のフレームで一度この処理を通った色なわけです。 なので、生まれた最初の色から計算をし直すのではなく、色相をちょっとずらして明度をちょっと下げた結果の色が再び同じ処理にかかるわけなので、そしてランダムの範囲が狭いため、前のフレームからある程度連続性のある色になります。 前のフレームと比べて急にとんでもなく違う色になったり、急にズドンと暗くなったりはしないということです。


色相の場合はプラマイ幅が均等なので、どっちに転んでいくかはわかりません。ランダムです。 一方明度の方は、ランダム幅があるとは言え必ず値はマイナス方向へ向かうので、1フレ進むごとにどんどん暗くなります。


ということで、その結果がこんな感じです。

13_hanabicolor1

中心部分が暗いですよね。 中心部分のパーティクルは、より早く生まれたトレイルパーティクルですので、先頭弾付近よりも長いフレームを経過しています。上記のように1フレ進むごとに明度が落ちるようにしてあるので、画像のように中心部分が暗い状態の見栄えになります。 色相の方は、ちょっとしか回してないので、そんなに違いはわからないですかね。 まあ気分でやっただけです。


このように、トレイルの色を経過時間で変えていくという方法の実験のつもりでやってみました。 素直に Age とか Age% を取得してそれを元に色を変える方式の方が楽かもしれません。 今回の方式の場合は、1フレ進むごとにどれだけ色相や明度が変わるのかという 「ステップ値」 を決めているということになりますね。1フレごとのステップ値を毎フレ重ねたらこれくらい色が変化しましたよ、というイメージです。 これに対し、Age や Age% などで変える方法は、全体のカーブを決めるというイメージになるかと思います。1フレごとのステップ値は知らないけど、全体ではこれくらい色が変わってくださいよ、と指定しているとでも言うか。




ちなみにですね、このツリーの接続先を変えると結果が全然違うというのを、例示しておきます。

14_icetree_state2once
クリックするとでかい画像。

B1の Set Particle Color を、Execute Once on Enter State ポートに繋ぎ直しました。もともとは Execute Every Frame に入っていたので、毎フレ計算されていたわけですが、Execute Once on Enter State ポートにつなぐということは、この State に突入した瞬間に1回だけ計算されて、以降は値が変わらないということになります。


あと、結果が分かりやすく出るように Value のランダムに Multiply by Scalar を挟んで、ランダムの振れ幅を3倍だか4倍に拡大しています。 これは視覚的に分かりやすくしたというだけで、今説明しようとしている「接続先で結果が違う」という話とは本質的に関係はありません。


これがその結果です。

15_hanabicolor2

トレイルの色の変化に連続性が無いのがわかると思います。 先ほどのやつは先頭弾から花火の中心に向かってだんだん暗くなっていったのに対し、今回は脈略無く明るい色と黒い色が混じっています。


これは色の決定が1回しか計算されないからです。 トレイルは State 2 なわけですが、State2 のパーティクルが生成される瞬間にこの色のランダム化(色相を回し、明度を下げる)が1回だけ行われ、その時点でパーティクルの色は固定されます。以降のフレームでは再計算されないので、このような結果になります。 これは今回の花火で望んだ結果ではありません。 だんだん暗くなっていって欲しいですからね。


ということで、毎フレ計算されるのか、1回だけなのか、いつもそこらへんを気にして接続先を選ぶという話でした。






●水面 ICE

水面オブジェクトはただのポリゴングリッドですね。 エミッタと同様、カメラに入らない部分はメッシュ分割の重さが惜しいので、末広がりな形にしています。 さらにカメラに近い部分のみ分割数が多くしてありますね。 この記事の最初の画像参照。



水面のうねうねは、ICE デフォーメーションでやっています。

その ICETree。

20_waterturb

おおう、スヴァらしくシンプル(゚∀゚)



Turbulize Mesh なんてコンパウンド、いつからあったんでしょうかね? 俺は今回初めて知りました。 中身を見てみると、PointPosition を Turbulize しているだけなので、まあ、今まで手で組んできたツリーをちょっと簡単に構築できるコンパウンドって感じですかね。


2種類の大きさの違うタービュランスを重ねています。常套手段ですね。 あとは、Animated チェックボックスをオンにすることによってタービュランスが発生させるパターンもアニメーションさせていますが、Turbulence Center にもキーを打って手動アニメーションを入れています。


Turbulence Centerを動かすと、タービュランスのパターンが変化するのではなく、現在のパターンのまま XYZ にシフトするという効果があり、結果的に「全体の流れ」を作ることができます。 タービュランスのパターンがその場でうねうねしていてもあんまり水面っぽくないんですよね。やはり、ちょっとでも 「方向性のある流れ」 を感じないと、水面っぽくならないと俺は感じていますが、どうですか。


タービュランスの大きさによって微妙に流れる方向やスピードを変えてやって、良さそうなところを探ります。かなり微妙な調整であり、しかもレンダしないと具合がよくわからなかったりするので、このモーション調整は意外と手間のかかる作業になりますね。


それともう一つ、いつも水面で思うのが、フラクタル(タービュランス)のパターンが XYZ で均一だと水面っぽくないということです。 例えば Photoshop の雲模様フィルタを使ってフラクタル模様を出し、その画像を Bump や Displacement で使って水面をレンダにしても、あまり水面っぽく見えません。 これを、マッピングしたグリッドをヨコに数倍引き延ばすだとか、もしくはテクスチャ画像の方をヨコに引き延ばしてからマッピングするだとかすると、意外と水面っぽくなることが多いと感じています。

21_frac

これはやはり、水面というものは流れがあることが多く、タテヨコ比率1:1の起伏パターンが現れることが少ないからなのではないかという気がするのですが、どうですか。デタラメ言ってたらすいません。


ということで、テクスチャでやる場合は上記のようにあらかじめ引き延ばしたテクスチャを作成するか、マッピング後にオブジェクトをスケールで引き延ばすか、あるいは UV をいじって引き延ばしてしまうのですが、今回の場合はマッピングではないし、末広がりの形を先に決めてしまっていたのでオブジェクトにスケールをかけるやり方も避けたいところです。 なので、グリッドのタテヨコの分割数を変えることによって結果的に同じ効果を狙いました。

上の ICETree画像を見るとわかるように、Turbulize Mesh で発生させたタービュランスパターンは Y のみに適用されています。つまり PointPositon の Y 方向だけの変異量として使っています。 その上で、 X と Z でメッシュの分割数が違えば、この Y の変異量への敏感さというか、メッシュ解像度による追随性に差を付けられるので、結果的に上記の「引き延ばした」ような効果になります。


ICE は以上。たぶん。





### RenderTree編



●花火の RenderTree


花火の PointCloud の RenderTree はこれです。

30_rt_p
クリックするとでかい画像。


花火のみをレンダする Pass で使っています。



・IsThisFuckinTrail で分岐



Aの Color_Switch ですが、上記 ICETree のところで説明した 「そのパーティクルはメインの光球なのか、それともトレイルなのかを判断して RenderTree を分岐する」 という部分です。 

Boolean_Attribute を使ってまず IsThisFukinTrail の値をゲットし、Boolean_LogicInput1 にぶち込みます。 Boolean_Passthrough では 1 (つまり True)を設定しておき、先ほどの Boolean_Logic の Input2 にぶち込みます。 これがイコールかどうか、つまり現在評価しているパーティクルの IsThisFuckinTrail が True かどうかの結果を、A の Color_Switch にブチ込みます。

True だった場合(そのパーティクルがトレイルだった場合)、そのパーティクルは Color_Switch の input2 の方でシェーディングされます。 input2 には B1 の Color_Atta_ICETreeが突っ込まれてますね。これはただの Color_Attribute ノードです。つまり、トレイルは、ICETreeで決定された色を単色で塗りつぶすだけのシェーディングになります。陰影がないのだからシェーディングとすら言わないかも知れないな。

False だった場合(そのパーティクルがトレイルじゃなかった場合=メインの光球だった場合)は、input1 の方でシェーディングされます。 input1 の先には B2 以下のツリーがありますね。ここが使われます。 中身はどうというほどのことでもないです。Incidence を使って、中心部分は光の芯があるかのごとく明るく、周辺部分は比較的暗い上に透明度が高くて奥が透けて見えているというシェーディングです。


こんな感じ。

31_cam_p

先頭弾はB2以下のマテリアル(光の芯があり、ボケ足もある)が適用され、トレイルはB1のマテリアル(単色)が適用されているのがわかります。





ICETree では、Get Particle State ID を使って State を取得し、2だったらそれはトレイルだから IsThisFuckinTrail を true にする、なんていうめんどくさいことをやっていますが、RenderTree から直接 Particle State ID を取得することもできるので、そのやり方にすれば IsThisFuckinTrail なんていう下品なカスタムアトリビュートは不要になり、ICETree はよりシンプルになり得ます。

しかし RenderTree には if ノードなどの直感的に扱える便利な条件分岐のノードがないため、今回の場合は 0, 1, 2 の3種類の値をとり得る State ID を RenderTree 上で取得しても、その後の分岐を作るのがめんどくさいです。っていうかわかりにくいです。 

なので StateID を取得してトレイルかどうかを判断するのは if だとかが使える ICETree の時点で終わらせておいて、RenderTree の段階では 「こいつトレイルなの? 違うの?」 という質問への答えだけを渡すというしくみにしたつもりです。 こっちの方が俺にはわかりやすいです。



・直接カメラから見える場合と反射で見える場合

最後にマテリアルノードに入る前に、Ray_Type_Switch に入ってますね。 これは、パーティクルが直接カメラから見えている場合と、水面の反射で見えている場合とで、見え方を変えたかったからです。

A以下のツリーは eyerefraction に入っているので、直接カメラから見たり、何かの透明部分越しに見えた場合はこのA以下のツリーが適用されます。

しかし、RenderTreeの右上部分=Group Comment で囲った部分は reflection ポートに刺さっていますね。つまり反射して見えている場合は、この質感を使えということです。B2の結果を Add したりして明るくしています。つまり、水面に映る花火は、直接カメラから見る花火よりも明るくなるというインチキなことをやっています。水面に映り込む花火を強調したくて、このようにしています。

実際のレンダの時は花火と水面を別レンダリングするつもりなので、水面 Pass では花火のマテリアルを Partitionマテリアルで変えちまえば良く、このように Ray_Type_Switch を使う意味はそんなにありません。にもかかわらず使ったのは、久しぶりに手順を確認しておきたかったというだけです。 もし花火と水面を一緒にレンダする必要があって、かつカメラから見た場合と反射越しに見た場合で質感を変えたい時などは、この Ray_Type_Switch が活躍するわけです。





●水面の RenderTree


水面の RenderTree はこれです。別Passでレンダしてます。

32_rt_oceansurface
クリックするとでかい画像。

Architectural を使っていますね。フレネル効果のあるリフレクションを簡単にやりたかったのだと思います。カメラから見て水平に近い部分ほど、背景や花火をよく映し込みます。


Incidence を使って、カメラから見て水平に近い部分だけを取り出し、それをブレンドマスクにして何度か Add してますね。水平線の近くがより明るい色になっているのがそれです。

33_cam_oceansurface
そして、花火は別レンダするので、この Pass では Primary Ray をオフにしています。カメラからは見えないのに、水面に映り込んだ花火は見えているという状態です。空をマッピングしたグリッドも同様に Primary Ray オフです。


そして水面に映り込んだ花火は、先ほどの花火 Pass でカメラから直接見えている花火よりも明るいものです。上記、Ray_Type_Switch でそうしているからです。







●水面デプス Pass



水面のみ、Depth Pass を用意しており、こんなマテリアルになっています。

34_rt_oceandepth
Scalar_StateRay Length を拾っています。Ray Length = レイの長さってのはつまり、カメラからの距離です。 正確に言えば、カメラから発射された Primary Ray がジオメトリと交差した地点( Intersection Point )における、そのレイの長さということになると思います。 ともかく、この方法でカメラからの距離が、オブジェクト単位ではなく、ピクセル単位でゲットできます。Primary Ray 専用ということになるので透明のブツを透過した距離には使えませんが。


こうして得られた距離を Scalar Change Rance にブチ込んでいますね。そして Old Range Start100Old Range End0 になっていますから、Ray Length の結果を、100 から 0 のレンジだと見なしていることになります。 そしてそのレンジを New RangeStartEnd0 から 1 にリマッピングしたスカラ値を吐き出しています。 結果、オブジェクト表面の、カメラから距離が 100 の部分は 0 で、距離が 0 の部分は 1 になります。


この 0 から 1 のスカラ値を Scalar to Color でそのままカラーに変換してやれば、0 = 黒、1 = 白というグラデーションができあがり、普通にリニアなデプス画像になります。 が、今回の場合は、Gradient Mixer のインプットにブチ込んで、グラデーションを調節していますね。黒のレンジを圧倒的に大きくしています。 

レンダするとこうなってます。

35_cam_depth

今回は水面の奥行きがかなり広く、リニアなデプスにするとカメラから見えている範囲にグラデーションが発生しなかったのでしょう。水平線間際でしかグラデーションが無かったのでしょう。 なので、見える部分で奥行きのグラデーションになるように、Gradient Mixer を使って調整したということだと思います。






・・・・と、水面のデプスマテリアルの作り方を全力解説したのはいいのですが、今、AfterEffects のコンポジションを見てみたら、この水面デプス素材、使ってませんでした orz


たぶん使うだろうなーと思ってレンダしておいたはいいが、実際のコンポ時に出番がなかったのか、デプスな処理を入れるのを忘れていたか、時間がなかったのか。 いずれにせよ無駄な Pass になりました。本当にありがとうございました。








●リフレクションのみ Pass


水面のシェーディングは除去し、水面に映る花火しか見えていないという Pass もレンダリングしてました。

36_ref

水面の Pass の Arc Mat を複製してリフレクションなどの値はそのままに、色を真っ黒にして、ライトもこの Pass ではオフにし、結果、水面に映り込んでいる花火以外は見えないという Pass になっています。


コンポ時に花火 Pass の方は Starglow で光芒を入れるのですが、ここが2D処理の弱点で、水面と花火が一緒にレンダされているだけだと、水面に映り込む花火の方には Starglow が入れられなくなっちゃうじゃないですか。 空にはキラキラ光芒付きの花火が上がっているのに、水面に映っている方はキラキラ光芒無しという、インチキ状態になってしまいます。


まあ、どのみちインチキなことしかやるつもりないし、現象として正しい状態にしようなんてつもりはサラサラ無いのですが、調整に便利だろうと思ってこの素材を用意したわけです。実際にコンポで使ってますね。水面に映る花火により強く Starglow をかけて、これ見よがしにキラキラ感を強調しているようです。助平なコンポです。



ちなみに黒い部分はヌケているわけではない(アルファチャネルは白)なので、Add するか UmMult して抜くことが前提の素材になりますね。




●カメラ


テキトーに、気分でティルトアップなアニメーションをしているだけです。

40_camanim

わははー カメラとインタレストの posY が動いているだけだー しかもなんの工夫もないイーズインイーズアウトだー ( ^∀^)ゲラゲラ


まあ、そのイーズっぷりは調整してますがね。こういうゆっくりなカメラアニメーションは特に、そのフェアリング加減で簡単に気持ち悪くなっちゃいますからね。









XSI 上での解説はこれくらいかしら。
ううむ。しんどい。


たぶんコンポ編に続く。たぶん。




.

|

« Making of 花火。 c03。 Comp。 | トップページ | Making of 花火。 c04。 Comp。 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: Making of 花火。 c04。 ICE / RenderTree。:

« Making of 花火。 c03。 Comp。 | トップページ | Making of 花火。 c04。 Comp。 »