映り込み・床編
![]()
![]()
![]()
・映り込み第二弾
今回は平面に対する映り込みの話をします。だから床編。物体への映り込みである環境マッピングはまた次の機会という事で。環境マッピングなら他のホームページでも解説されてますし。環境マッピングをやる時は、応用の(簡易)屈折マッピングもやってみたいなぁ。
・映り込み、それ即ち反射である
ここで言う、床への映り込みというのはこんな感じです。
影は省略。いかにもDoGA-L2な絵
映り込みは、反射によってできます。
(悪い意味で)シンプルな図例えば、色がrgb( 0.5, 0.75, 1.0)の床を見た時に視線の25%が反射、75%が反射しなかったとしましょう。反射した先には色がrgb( 1.0, 0.75, 0.25)の箱があります。「視線の〜%」っていうのがわかりにくいですが、まあ読むだけ読んでみてください。理解できなくても何とかなりますし。
まず反射しなかった75%から。反射しなかった分はそのまま床の色を見る事になります。でも75%しかその床の色を見ていないので、床の色×0.75がまず床の色です。
次に反射した25%を考えましょう。視線が反射した先には立方体があります。視線の25%はその立方体を見ているので、立方体の色は立方体の色×0.25となります。
意味がよくわからない計算でしたが、この次がポイント。この2つの計算で出てきた色を加算すると、映り込みのある床を見た時の床の色が算出できます。床の色×0.75 = rgb( 0.5*0.75, 0.75*0.75, 1.0*0.75 ) = rgb( 0.375, 0.5625, 0.75 )
立方体の色×0.25 = rgb( 1.0*0.25, 0.75*0.25, 0.25*0.25 ) = rgb( 0.25, 0.1875, 0.0625 )
床の色×0.75+立方体の色×0.25 = rgb( 0.375, 0.5625, 0.75 ) + rgb( 0.25, 0.1875, 0.0625 )
= rgb( 0.625, 0.75, 0.8125 )
(悪い意味で)意味のわからない図これで映り込みの計算は終わりです。床の色×0.75+反射先の色×0.25。つまり、床の映り込みは簡単な掛け算と足し算で表現できるものなのです。
……これであってます?>レイトレーシング関連の書籍を読んだ事のある方
レイトレーシングの本とかって読んだ事無くて、これは全て自分の想像なんで。あと、わかりにくすぎてすいません、なんとか解読して理解してください。それなりの理解でもなんとかなります。
・ポリゴンに映り込みを使ってみよう
以上はちょっとレイトレーシングな観点から映り込みを説明しましたが(そうか?)、だからってリアルタイムにレイトレーシングなんて実用的な速度で動くはずもありません。別にムービー作るわけじゃないし。
そこで、この簡単な掛け算と足し算をDirect3Dに応用して、ポリゴンを映り込ませてみましょう。まず問題になるのが、平面に映り込んだ物体の位置はどう算出するのか?
この、映り込んだドラム缶の位置 →
これはとっても簡単。床を元に位置と向きを反転させればいいだけです。言葉だとわかりにくいですが、つまりこういうことです。
これを、→
こうする。気を付けてほしい事は、回転ではなく反転だという事です。この絵では、180度回転では間違いで、正しくは上下反転です。反転じゃないと元の物体と映った物体が食い違う場合が出てきます。
床がXZ平面(法線がY軸と同じ)ならば、物体の3つの軸(X軸・Y軸・Z軸)のYの成分を反転させるだけでいいです。XZ平面・XY平面の場合も同様です。
例) 床はXZ平面(床の法線ベクトルはvector( 0.0, 1.0, 0.0)かvector( 0.0,-1.0, 0.0) )
X軸 vector( 1.0, 0.0*-1.0, 0.0 ) → vector( 1.0, 0.0, 0.0 )
Y軸 vector( 0.0, 1.0*-1.0, 0.0 ) → vector( 0.0,-1.0, 0.0 )
Z軸 vector( 0.0, 0.0*-1.0 1.0 ) → vector( 0.0, 0.0, 1.0 )まぁこの場合はわざわざ掛け算使わなくてもvector.y=-vector.yとするでしょうが。
斜めの平面については各自考えてみてください、自分も考えます(すぐには思い付かなかった)。もう一つ気を付ける事。反転させたらポリゴンの表裏が逆になるので、裏面除去(Culling)する時は注意。軸が2つ反転するなら害はないんですが、1つしか軸が反転しないためこうなります。右手を上げて鏡に映ると、映った方は左手を上げてるのと同じです(…違うか)。
普通の鏡に向かって右手上げてるのに映った方も右手上げてたら怖いですね。先ほどの床を元にした反転を回転で済ませると、そういうことが起こりかねません(物体が線対称や点対称の物ならなんともない)。
ついでにもう一つ。反転させる時にモデルだけではなく全ての光源の位置と向きも平面を元に反転させる事。まぁこれはそれほど目立たないので処理しなくても良いかもしれませんが。
それにしても、全てのモデルの軸を反転させないといけないとはなんて大変なんだ。その上光源まで反転させないといけないなんて!(←和訳した文章に見られる"!"の使い方)
でもここまでしなくても、もっと楽な方法があります。全てのモデルと光源を反転させる方法、と言えばわかるでしょうか。
わからない人は自分なりに考えて見てください。答えは番組の後半で(?)。
位置と向きを反転させたら、それを描画しましょう。次に床を描画、そして最後に物体を描画します。
描画する時の色が問題ですね。掛け算と足し算を思い出してください。まず映り込んだ物体の明るさについて考えてみましょう。例えば、床は25%を反射するので、映り込んだ物体の明るさを1/4にしたい。どうしたらいいか?
全てのモデルの明るさを1/4にする。でもそれだと無駄が多くなります。せっかく光源使ってるんだから、光源の明るさを1/4にするという方法を使いましょう。
光源処理してない場合はおとなしくモデルの明るさを1/4にしてください……。
光源の明るさがrgb( 1.0, 1.0, 1.0 )なら、素直にそれぞれに0.25掛けてrgb( 0.25, 0.25, 0.25 )で大丈夫です。
まず普通の状態の物体→
反転させて映り込んだ位置へ→
明度を落とす位置を反転して、明るさを落として描画。これで映り込んだ物体の描画はできました。
次に床。これも光源かモデル(床)の明るさを落とすのを忘れずに。25%反射する床だったから、反射しないのは75%か。ということで床の明るさは3/4。
そして描画。が、そのまま描画では映り込んだ物体に上書きしてしまうことになります。これでは床しか表示されません。加算合成で描いてください。これ重要。
明るさを落とした床を→
加算合成で描画それっぽく見えるでしょ。加算合成で映り込んだ物体を書くのではなく、映り込んだ物体の上に加算合成で床を書いてください。
最後に、物体を書きます。これは普通でいいです。光源の明るさを元に戻すのと、ブレンディングを加算合成から元に戻すのを忘れずに。
この上に→
普通に物体描画終了。意外と簡単でしたね。
映り込みの過程の絵が、減色の影響でちょっと説明と色が一致してません。あと影も省略してます。DoGA-L2は影作れないんですよね〜(自前でなら可能だけど)。照明も反転してませんが、これはそれほど目立ちませんね。でも動くと問題あるかもしれません。
・以上、基本編でした。
まだ終わりじゃないです。影を作ると新たな問題が出てきたりするんですが、加算合成とα合成についてちょっと知っておかなければいけない事もあるし、いい加減長くなったんで続きは別のページにしておきます。光源とモデルについての反転もその時にしましょう。
もうファイルが17KBになってしまいました。「グローと言えば」は9KBなのに。基本はできたので、あとは応用だけです。前半のあのわかりにくい文章が理解できれば、応用編を見なくても自分で応用できるでしょう。もう応用編のための大したネタもないですし。
![]()
![]()
![]()
written by Y.Ohde e-mail : oode@alles.or.jp