固定機能でのスフィアマッピングをやってみました。テカテカ反射するやつです。
固定機能でスフィアマップがサポートされている環境も多いとおもいますが、
今回は仕組みを理解することと、機能がサポートされていない環境のために、
テクスチャマッピングだけでスフィアマッピングを行います。
方法としては、
視線ベクトルのモデルの法線での反射ベクトルを求め、
その後テクスチャ座標に適用します。つまりただのテクスチャマッピングということです。
テクスチャ座標を動的に計算することでスフィアマッピングを実現します。
今回はGame Programming Gems1のスフィアマッピングで、上から見下ろす反射テクスチャを使用しています。
反射ベクトルをテクスチャに適用するだけでなぜスフィアマッピングになるのか?
ここは仕組みはシンプルなのに理解しづらい部分です。というか、よくこの方法を思いついたものです。
まず用意するテクスチャというのは、
ピカピカに磨かれた球体に周りの環境が写っているところを、
XYZどれかの軸から撮影したものを用意します。
この画像の素晴らしい性質は、「向きベクトルを画像の中心と考えると、その写りこみの色が対応している」ということなのです。
今回の場合、xzをuvと対応づけて考えます(今回は上から撮影した反射テクスチャなので[x軸から撮影した場合、xを無視する])
例えばv(0,1,0)つまり上向きの場合、画像の中心点です。
例えばv(1,0,0)つまり右向き(zからみて)の場合、画像の右端です。
結果的に、反射後のベクトルのxzを取り出して、uvに適用するだけで、反射後の色が乗っているテクスチャ座標が決定するのです。
ちなみに法線は各要素が-1~1なのに対して、uvは0~1なので補正する必要があります。
これは線形なので、y = ax + bの式で連立方程式で解きましょう。実際には、
float u = reflectDirection.x * 0.5f + 0.5f;
float v = reflectDirection.z * -0.5f + 0.5f;
ということになります。
なぜyを無視してよいのか? これは反射テクスチャが上から見た景色を撮ったものだからだったのです。
つまり、横からみた景色をとった場合、xかzを無視するわけです。
またこの方法には問題点がいくつかあります。
まず、モデルを移動・回転・拡大する場合に困ります。
頂点と法線をすべてCPUで計算しなければならなくなるからです。これは少々もったいない感じがいたします。
また、この方法だと180度しか写りこみを再現できないのです。
なぜなら今回の場合ですと、yを無視するわけですから、V(0, 1, 0)もv(0,-1,0)も同じテクスチャ座標なのです。
またキューブマッピングとは違い動的に反射テクスチャを生成するのがむずかしいです。
この問題点を背負ってでもこの手法を取るメリット、
それはやはりただのテクスチャマッピングであることからの速度的メリット、
および高度な機能を持っていないハードでの実装が可能であること。
このあたりでしょうか。
おそらくメタルマリオなんかはこの方法でしょう。また水面の反射などにも適しているでしょう(上半分からの反射だけで済むので)。
自分のメモ的要素が強く、非常にわかりずらくて申し訳ないです。もっと文才があれば・・・
これで理解できる方はかなり頭が良いと思います。是非その才を色々な分野に役立てていただきたいとおもいます。
最後にビルド後のバイナリ(windows)とソースコード(vc10)です
モデルはblenderのmonkeyですwavefrontで読んでます。Openglスフィアマッピング
コメントはまだありません。