最後の映り込み

・映り込み第三弾

 「映り込み・床編」「映り込みと床と影と」に続いて、床への映り込み最終回です。いい加減これで床への映り込みは最後にします。初めは1回で終わらせるつもりだったんですけどね。

 今回は、前回言った「加算合成を使わない映り込み」と「光源とモデル(物体)の反転」の2つについてです。

 

・加算合成を使わない映り込み

 解説の前に、映り込みの手順のおさらいをしましょう。これを書いている自分が覚えてないですし。

 まず移りこむ位置に物体を描画します。この時明度は床の映り込む割合、つまり鏡面反射率の分だけ落とすんでしたね。25%映り込むなら明度も25%に。次に床を加算合成で描画。床の明度は移りこまない割合、拡散反射率の分落とします。最後に物体を普通に描画します。


映り込んだ物体を
明度を落として描画
…よく見えないけど

  


床を加算合成で描画

  


そして物体を
普通に描画

 今回は、説明しなければいけないことが増えるので影は使いません。影を使うことで発生する問題と、その解決の方法は加算合成を使う場合も使わない場合も同じです。問題と解決方法については前回の「映り込みと床と影と」を参照のこと。

 補足。影を使う場合の描画順は床→映り込み物体加算→物体でしたが、こうすると前回説明したとおり映り込んだ物体のオーバードロー問題をなんとかしないといけません。前々回や今回のように映り込み物体→床加算→物体とすると床のオーバードローを解決する必要がありますが、平面の床ならオーバードローはほとんど無いので気にせずに済みます。


 加算合成による映り込みは、映り込む物体を明度を落として描画し、床も明度を落として描画します。それなら、映り込む物体は普通の明度で描画して、床を描画する時に一緒に明度を落としても同じことができます。それが加算合成を使わない映り込み、つまり半透明を使った映り込みです。

 拡散反射率が75%、鏡面反射率が25%の場合、映り込む物体を明度25%で描画して、床を明度75%で加算合成します。これを半透明でやるなら、映り込む物体の明度はそのままで、床を不透明度75%にすると、映り込み25%床75%になります。


映り込んだ物体を
普通の明度で描画

  


床を半透明で描画
この画像では87.5%
(7/8)の不透明度

  


そして物体を
普通に描画

 物体の光源処理がリアルタイムじゃない場合、物体の明度を一つ一つ落とす処理が必要ですが、この方法なら物体の明度は気にする必要が無いです。

 その代わり、この方法には欠点もあります。それは、物体を先に描画するため、明度のクリッピングを先にしてから明度を落とすということです。と言われても何が何やら。

 通常、明度1.0(表示できる最大明度)以上の明度の色を描画しようとした時は、明度を1.0にして描画します(クリッピング処理)

 クリッピング処理は描画する時に実行します。加算合成を使った映り込みでは、物体は明度を下げてから描画します。半透明を使った映り込みでは、物体は描画してから明度を下げます。例として、rgb( 0.5, 2.0, 3.0 )の色の物体が鏡面反射率25%の床に映り込む時の、映り込んだ物体の色を比べてみます。

加算合成:明度を25%[rgb( 0.5, 2.0, 3.0 ) → rgb( 0.125, 0.5, 0.75 )] → 1.0でクリッピング・描画[rgb( 0.125, 0.5, 0.75 ) → rgb( 0.125, 0.5, 0.75 )] こんな色→

半透明:1.0でクリッピング・描画[rgb( 0.5, 2.0, 3.0 ) → rgb( 0.5, 1.0, 1.0 )] → 明度を25%[rgb( 0.5, 1.0, 1.0 ) → rgb( 0.125, 0.25, 0.25 )] こんな色→


上が黒からrgb(0.5,2.0,3.0)のグラデーション(クリッ
ピングあり)、下が加算合成の場合の映り込み

  


上は同じで、下は半透明による映り込み
上のグラデーションをそのまま25%にした感じ

 このとおり、半透明では明度1.0を超える部分が加算合成よりも暗くなってしまいます。床の鏡面反射率が25%なので、明度の最大も25%(0.25)になっています。この画像を見ると半透明のほうが正しいようにも見えますが、実際には加算合成の例の方が正確だし色も鮮やかです。

 使い方によっては明度が1.0を超えることもそうないですけど、スペキュラー(鏡面反射)を使うと簡単に超えてしまいます。あとエフェクトのためにやたら強い光源を使ってみたり。

 

 ……加算合成を使わない映り込みについて説明してみましたが、これって何の役に立つんですかね?スターフォックス64(任天堂)でやってたので書いてみたんですが、N64は加算合成が使えないから半透明を使ってるんですけどね。あとセガのMODEL3のレースゲーム(名前忘れた。セガラリー2ではない)でもやってたような。

 半透明しかできないハードとか、加算より半透明がかなり速いハードとかなら役に立つかもしれませんけど。

 

・お手軽反転

 映り込んだ物体の位置を求めるには、床について反転させるんでしたね。


物体を反転させる

 光源の位置や方向も反転させます。

 この場合光源はもちろん、Direct3Dでいうワールド行列(オブジェクト座標系からワールド座標系へ変換するための行列)もすべて反転させなければいけなくなり、手間と計算量が増えてしまいます。この方法よりは計算量と手間を少なくできる方法があります。

 物体も光源もすべて反転している。目に見えるものはすべて反転している。でも、1つだけ反転していないものがある。それはカメラ。目に見えるものは反転しても、カメラ(視線の元)の位置や方向は変わっていない。だったら、目に見えるものは反転しないで、カメラを反転させれば良いということになる。これなら手間も計算量も最初の方法に比べれば減少する。

 では実際にやってみましょう。この例では、前半で説明した半透明による映り込みを使ってみます。


最初にカメラだけを反転。
物体や光源はそのまま


普通に描画。床は裏面
除去で描画されない

 


カメラを元に戻して

  


床を半透明で描画

  
物体を普通に描画

 ご覧のとおりちゃんと映り込んでます。半透明を使う方法だと、反転だけではなく描画も普通にできて手間が省けます(明度を指定しなくていい)。もちろんこの反転方法は半透明専用ではないので、床に加算合成を使う方法と組み合わせて使うこともできます。

 反転については以上。なんだか短く終わってしまいましたね。

 

・映り込み完結

 当初1回で済ませるはずが、3回に渡ってやることになってしまった床への映り込みも、ひとまずこれで終了ということにさせていただきます。映り込んだ時の明度についてはあまり自身が無いですが……。

 次回の更新については、まったく目処が立っておりません。4/1に就職するため、それからは暇ができるかわからないので。一応目標はsubject z まで行くことなんですが……。ちなみに今回はsubject u なので、v w x y zで残り5回ですね(この後subjecttopicとに分けました)。

 最近実験してみたいことは、フィードバックエフェクト。FF7をやった時に、戦闘に入る時のエフェクトの真似をDirectDrawでやったんですけど、それをDirect3Dでやりたいなぁと前々から(1年前以上?)思っています。それがFF8をやったら再燃してきました。

 

written by Y.Ohde  e-mail : oode@alles.or.jp

back