はじめに

こんにちは!

引き続いて座標変換の話をします。
本日は射影トランスフォーム行列を覗いてみましょう。

前回の関連記事(予備知識として下から上に読んでおきましょう)
DirectXとOpenGLのビュートランスフォーム行列の違い
3DCGの座標系の紹介
DirectXとOpenGLの回転行列、回転軸、回転方向


数式の比較

.

DirectXとOpenGLのヘルパー関数

これまでと同様、行列作成用の関数が用意されています。

DirectX
matrix *D3DXMatrixPerspectiveFovLH( matrix *pOut, float fovy, float Aspect, float zn, float zf );
左手座標系のパースペクティブ射影行列を作成
matrix *D3DXMatrixPerspectiveFovRH( matrix *pOut, float fovy, float Aspect, float zn, float zf );
右手座標系のパースペクティブ射影行列を作成

OpenGL
void gluPerspective( double fovy, double aspect, double zNear, double zFar);

.

ヘルパー関数を使用したときに作成される行列

DirectXは、マイクロソフトのページの行列
OpenGLは、OpenGLプログラミングメモの「gluPerspectiveを置き換える」の行列を参考にします。

式は、DirectXのD3DXMatrixPerspectiveFovLHをベースにして、
ゲーム3D数学完全ホワイトボックスなパースペクティブ射影変換行列
を参考にしつつ、式変形したものを示します。

引数は次の通り
fovY  視体積の上下方向の視野角(0度から180度)
Aspect 近平面、遠平面のアスペクト比(Width / Height
Far  カメラから遠平面までの距離(ファークリッピング平面)
Near  カメラから近平面までの距離(ニアークリッピング平面)

一度これらを次のようにまとめます。
zoomYの逆関数、Aspectの求め方を補足で書きました。

上記の変数を使用して、DirectXとOpenGLの各行列を書くと次のようになります。

.

右手系と左手系の違い

D3DXMatrixPerspectiveFovLHとD3DXMatrixPerspectiveFovRHを比較すると分かりやすいのですが、
行列の3行目の正負が反転しています。
D3DXMatrixPerspectiveFovRHと同じ右手系のOpenGLのgluPerspectiveの3行目の正負が等しいです。
この正負の反転により、掛け算の最終結果のZ値の値を反転させています。

これまで右手座標系の計算では手前をZ値のプラスとして考えていましたが、
この反転の計算により、奥をプラスに変換させます。
つまり左手座標系へ変換させているわけです。
.

行列は一体何をしているのか

一度、このプロジェクショントランスフォーム行列の式を実際に使用した場合を少し考えてみましょう。
行列は、ベクトルに掛け算して使用します。

掛け算した結果は、クリッピング座標系・クリップ座標系と呼ばれます。そして、この座標系から、wで割ったものが正規化デバイス座標系と呼ばれます。

上記の式からx値とy値については、簡単に何をしているのか想像がつくようになります。ABzoomXzoomYですので、アスペクト比に関わる値を掛けて縦と横幅を調整することに繋がっています。

z値に関しては、上記の式変形ではまだ分かりにくいので、さらに値を代入して数式を変形していきましょう。
今回は、分かりやすくD3DXMatrixPerspectiveFovLHの値を代入しました。

このようにすると、zの値が、NearからFarまでの値をとると、0~1の結果になることが分かるかと思います。

さらにイメージしやすくなるように、1と10の値を代入してみましょう。

これをグラフに書くと次のようになります。

xが1から10をとると、f(x)が0から1までをとることが分かります。

射影行列を位置ベクトルに掛け算した結果のz値の値を、0未満と1以上の場合を表示させないと作ることで、
NearからFarまでにある座標のデータを表示させるという作りが可能となります。
なお空間のNearからFarまでを切り出すため、クリッピング座標系と呼ばれていると思われます。

ところで、数式から分かるように Near = Far と設定してしまうと、0割り算エラーが発生してしまいます。
ある程度値を持ったうえで、 Far > Near となるような値を設定する必要があります。

DirectXとOpenGLの式の違いの理由

右手系の行列を作成するD3DXMatrixPerspectiveFovRHと
右手系のOpenGLのgluPerspectiveとの式が微妙に異なることにお気づきでしょうか。
本来同一になるはずなのに、Near Far が関係するZ値の計算部分が少し違います。

なぜ、このようになっているのでしょうか。

先ほどと同じようにグラフを作ってみましょう。

さらに、NearFarの値を適当に決めてグラフを描きます。

なんと、OpenGLでは、xが1から10をとると、f(x)が-1から1までをとります。
OpenGLの射影変換後のz値は正負をとるということになります。

DirectXではz値が0から1なので、このような違いが行列に現れてきたのです。


おわりに

今回は、座標系の変換の中で最も?よくわからない
プロジェクショントランスフォーム行列をとりあげました。

右手座標系だったものはこの変換により左手座標系になることが分かりました。

DirectXの右手座標系のD3DXMatrixPerspectiveFovRHと
OpenGLの右手座標系のgluPerspectiveは基本的に同じですが、
DirectXのZ値は0~1までに正規化されるのに対して、
OpenGLのZ値は-1~1までに正規化されるため
微妙に行列が違っているということが分かりました。

よくわからない式もグラフをかくと、分かりやすくてよいですね。

以上。おつかれさまでした!

関連記事

  • DirectXとOpenGLのビュートランスフォーム行列の違いDirectXとOpenGLのビュートランスフォーム行列の違い はじめに こんこん! 今回は、前回に引き続き座標変換の話をします。 特に、ビュートランスフォームの部分の計算式を見てみましょう。 気になっていたのは、DirectXとOpenGLとで違いがあるのかという点です。 おそらく違いはないはずですが、 前回の関連記事 ・3DCGの座標系の紹介 ・DirectXとOpenGLの回転行列、回転軸、回転方向 数式の比較 . Dir […] Posted in アルゴリズム
  • DirectXとOpenGLのベクトル/行列演算の違いDirectXとOpenGLのベクトル/行列演算の違い はじめに こんにちー。 なたでです。 今日も引き続き勉強会です。 これまで、座標系とその変換を学んできました。 今回、実際にその計算を行うため、 具体的にはベクトルや行列演算について どのようにソースコード上で書けばいいか学んでいきましょう。 ということで・・・ DirectX、OpenGL、各シェーディング言語の型や計算の特徴をまとめるぞー!( […] Posted in アルゴリズム
  • DirectXとOpenGLのカリングの設定方法の違いDirectXとOpenGLのカリングの設定方法の違い はじめに こんにちはー! 今日は、3D描写するときのテストの話をします。 テストと聞いて何を思い浮かびますでしょうか。 試験とか、勉強とかそんなことをきっと思い浮かべるでしょう。 作成した3Dポリゴンの頂点を描写するときも、 本当に描写していいのか、無駄ではないのか試験をしています。 いくつかテスト方法を紹介しましょう。 ・背面カリング(裏面カ […] Posted in アルゴリズム
  • DirectXとOpenGLのビューポート行列の違いDirectXとOpenGLのビューポート行列の違い はじめに こんにちは! 3DCGの再勉強中のなたでです! 今まで、次の変換行列の違いをみてきました。 ・DirectXとOpenGLのビュートランスフォーム行列の違い ・DirectXとOpenGLの射影トランスフォーム行列の違い 本日は変換の最後のビューポート行列の違いを調べてみましょう。 といっても、ここまでくると右手座標系・左手座標系という話はなくなっているので、 […] Posted in アルゴリズム
  • DirectXとOpenGLの回転行列、回転軸、回転方向DirectXとOpenGLの回転行列、回転軸、回転方向 はじめに こんにちは! ハンドスピナーを最近買ったなたでです! 今日も勉強会をしましょう。 本日は、DirectXとOpenGLの軸の違いに焦点をあてて 回転行列をおさらいしてみましょう。 掛ける順序 3D環境といえば、DirectX、OpenGLです。 今回、回転用の標準関数を調査して比較していきたいと思います。 比較する前に基本的な掛 […] Posted in アルゴリズム
  • 3DCGの座標系の紹介3DCGの座標系の紹介 はじめに こんにちは! 今日は、3DCGにかかせない座標系の話をするよ! 座標系の種類 では、オブジェクトから画面まで、どのような座標系があるか紹介します。 . 座標系一覧 呼び方が変わりますが、細かく分けると次のような流れになっています。 各々の変換とよばれている部分が行列を掛け算することに相当します。 座標はベクトルとし、このベクトルに座標を掛け算して、次の座標系 […] Posted in アルゴリズム