DirectXとOpenGLの射影トランスフォーム行列の違い

投稿日: 更新日:

はじめに

こんにちは!

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

前回の関連記事(予備知識として下から上に読んでおきましょう)
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までに正規化されるため
微妙に行列が違っているということが分かりました。

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

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

広告

コメントをどうぞ(承認された後に公開されます。メールアドレスの記入は自由ですが、記入した場合でも一般公開されることはありません)

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中