glFrustumの解読
追記: 2010/3/24
書いたときの理解が足りないため意味不明なところがある。
少し書き直した。
http://gunload.web.fc2.com/opengl/tutorial/glfrustum.html
glFrustumが何をしているかというと
View座標(視点を原点として視線方向がz軸の負の方向を向いている右手系の座標系)に
おいて指定された視錘台(frustum)を正規Device座標に変換している。
(left, bottom, near)->(-1, -1, -1) (right, top, far)->(1, 1, 1)
ここで正規Device座標ではZ軸が反転されて左手系になっていることに注意が必要。
(near -> far がZ軸の負の方向だったのが、正の方向になっている)
単純な形からglFrustnumの行列を合成していこうと思う。
あとright+left=0かつtop+bottom=0の場合限定。
同次座標を使った投影行列
ビュー座標(まだ右手系)で、z=d(d<0)の平面を投影面とすると
投影面の向こう(z
Z軸を[-1, +1]に収まるようにする
つまり(x, y, near)を変換するとzが+1になるように
(x, y, far)を変換するとzが-1になるようにする。
(まだZを反転しておらず右手系)
Z軸のみの問題なので関係部分A(スケール), B(移動)とおいておく。
ここでz=nearのとき
BをAとnの式に置き換えることができる。
z=farのとき
A、Bをnearとfarの式で置き換えることができた。
Z軸の反転
以降左手系となる。
x, yのスケーリング
x, yともに[-1, +1]におさまるようにスケーリングする。
実際にはz=nearの地点で[-near, +near]になるようにスケーリングする。
最後に
ここで最後の関門。
glFrustumの定義と比べると第3行第4列の符号が合いません。
何故かというと引数のnear, farは視点からの距離をあらわしていて
視点座標では負の値になるところを正の値をとっているからです。
そこでnear=-near'、far=-far'と置き換えます。
これでglFrustumの式になりました。
(right+left=0かつtop+bottom=0の時限定)
以上でglFrustumの解読完了。
right+left!=0やtop+bottom!=0の歪んだ投影は必要になったときにまた考えるとしよう。
参考リンク
http://angra.blog31.fc2.com/blog-entry-114.html
今回のはこちらに書いてあるもの(DirectX仕様の行優先)を
ベースにOpenGL風味(列優先)に解読したものであります。