
I.はじめに
この手法を実験してみようと思ったきっかけは、他ならぬ家のビデオカードがG400で
EnvironmentCubeMappingに対応していないことでした(苦笑)。又、頭文字Pでも
映り込みは適当で、違和感を拭えない状況も多々ありました。それが心残りに
なっていた事もあって、ほぼ自己満足に近い形で自前の実装を行ってみました。実際に
使えるかは分からないですが、ここを見て参考になる方がいらっしゃると幸いです。
II.実装
最初に、通常のSphereMappingの方法を紹介します。この方法では、映り込ませる
絵にその名の通りSphereMap=球面上に映り込んだ絵、を用います。

図1.SphereMappingの概念図
すなわち、視点から鏡面物体が存在する筈の位置に配置してある、鏡面を持つ球を
見た絵です(図2)。

図2.SphereMappingの例
このSphereMapを鏡面物体上の各三角形の頂点が持つ単位化された法線N
(視点座標系で見た物)を用いて
X軸:絵の右方向が正
Y軸:絵の上方向が正
SphereMapの半径:1
以上のように仮定したとき、
X=0.5+Nx×0.5
Y=0.5+Ny×0.5
というUV座標でTextureMappingすると、SphereMappingによる映り込みが実現します。
さてここで気付いたのですが、SphereMapを作るときは、鏡面物体の正面方向から後方
180度までの完全な球の座標系になっており、これをTextureMappinで貼り付けるときは、
正面から90度までの半球の座標系になっています。それ以外に違いはありません。
となると、高校の頃に習った懐かしき三角関数の半角公式を使ってみると簡単に解けそうです。
そこで、SphereMap上に存在するポリゴンの頂点pの座標変換公式は半角公式を使って
以下のようになります。
X軸:SphereMapの横方向(右向きが正)
Y軸:SphereMapの縦方向(上向きが正)
Z軸:SphereMapの鉛直上向き方向(図1の正面方向)
sinXY,cosXY:X軸と原点-頂点pのベクトルが成す角度
Z:Z軸と原点-頂点pのベクトルが成す角度
SphereMapの半径:1
とした時
X=cosXY×cos(Z×0.5)
Y=sinXY×cos(Z×0.5)
非常に単純です。以上の計算により、たった一枚の絵で周囲360度全てを見渡す究極の
魚眼レンズ画像を作り出せます(図3)。

図3.計算して作りだしたSphereMap
そして、こうして出来たSphereMapを前述のUV座標で鏡面物体へTextureMappingしてあげると

図4.動的EnvironmentSphereMappingを施したティーポット
映り込みが表現できました。綺麗です(というかシュールです)。これでめでたしめでたし・・・
で済めばよいのですが、そうは問屋が卸しません。
III.欠陥とそのいい加減な対策
この方法にはいくつか欠点が存在します。
1.EnvCubeMapと違って、絵を歪ませる必要があるため「遠景」が予め用意できない。
2.視点からの光線は全て平行と仮定している。
3.座標変換計算が独自なので、CPUへの負荷が大きくなる。
4.ポリゴンが視点と物体を結ぶベクトル上に並ぶと破綻する。
1は二次元画像で事足りる遠景が、そのままでは用意できないと言うことです。これは絵を
歪めるSphereMappingの原理上、仕方ありません。2はSphereMappingの特徴です。鏡面
物体に極端に近づかなければどうせ分かりません(適当)。3はVertexShaderを使えば多少
改善できるはずです。問題は4です。具体的にどんな問題かというと、正面方向から180度の
直線(要するに真後ろ)と交差するポリゴンが現れた場合、SphereMapの隅にほんの少しだけ
見えるはずが、一気にSphereMap全体を覆ってしまうと言う物です(図5)。

図5.破綻したSphereMap
これを正確に回避するには、直線と交差したポリゴンを適切に分割しなければなりませんが、
そのような条件判定は非常に複雑であり、実際に厳密な判定・ポリゴン分割を行うとに一気
に処理速度が低下します。そこで、現在は
Z>160°くらい(アバウト)
となる頂点を持つポリゴンは省略する、という苦し紛れの方法を採っています。しかし、この
方法だと交差するポリゴンが巨大な場合はやはり駄目です。未だに完全な解決の方法は
見つかりません。意外な落とし穴です。実用では、使い方によってはほとんど目立たないのが
救いと言うところです。
IV.まとめ
以上のように紹介してみましたが、冷静に考えるとこの方法が実用に耐えるかどうかは
微妙な所です。座標変換部分をVertexShaderで記述することで、座標変換による負荷
をHT&Lに任せることは出来ますが、その場合は破綻を防ぐ処理がより難しくなりそうです。
おまけに、(個人的な話ですが)頭文字Pの一部を組み込んで遊んでみようと思っても、DirectX7
ベースだと読めないXファイルもあって使い物になりません(;;)。もし、この先余裕があれば、
DirectX8対応に書き換えてみようと考えていますが、デモ以外にも実用になって欲しいですね。
貧乏ビデオカードユーザーにも、GT3の感動を!(笑)