DirectXとOpenGLのビューポート行列の違い

投稿日: 更新日:

はじめに

こんにちは!
3DCGの再勉強中のなたでです!

今まで、次の変換行列の違いをみてきました。

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

本日は変換の最後のビューポート行列の違いを調べてみましょう。
といっても、ここまでくると右手座標系・左手座標系という話はなくなっているので、
DirectX と OpenGL とで、きっと同じだと思いますが……。

おさらいですが、ビューポート変換は
正規化デバイス座標系から、スクリーン座標系への変換となります。

関連記事です。もし読んでないなら下から上に読んでいくといいよ!
DirectXとOpenGLの射影トランスフォーム行列の違い
DirectXとOpenGLのビュートランスフォーム行列の違い
3DCGの座標系の紹介
DirectXとOpenGLの回転行列、回転軸、回転方向


数式の比較

.

DirectX

D3DVIEWPORT9構造体でビューポートの定義をして、
SetViewportで設定できるようです。

行列というよりは設定値ですね。
ちなみにデフォルト値は次のようです。

D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = RenderTarget.Width;
vp.Height = RenderTarget.Height;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;

vp.X, vp.Y が描写する左上の座標
vp.Width, vp.Height が描写幅
vp.MinZ, vp.MaxZ が深度値の変換です

なお、実際の行列自体は、ビューポートとクリッピング (Direct3D 9)に記載されています。

.

OpenGL

OpenGLでも行列というより関数になっています。
glViewportglDepthRangeで直接設定する形です。

void glViewport( GLint x, GLint y, GLsizei width, GLsizei height);
これの注意点として、ウィンドウで設定している場合は、左下が原点になります。
Windowsの原点は右上で、下に行けばy+にいくのに対して、
glViewportの原点は左下で、上に行けばy+になるわけです。

void glDepthRange( GLdouble nearVal, GLdouble farVal);
描写先の深度値変換の設定です。
0 – 1が初期値です。
※参考 [DEV][CG]DirectXのPerspectiveとOpenGL Frustumの違い

なお、行列は次のようになります。

※参考 ビューポート変換行列 – code snippets

行列は何を表しているのでしょうか

これまでのおさらいをしましょう。
カメラ座標系から射影トランスフォームをしたものがクリッピング座標系になり、
クリッピング座標系から x, y, zw で割った遠近除算したものが
正規化デバイス座標系です。この正規化デバイス座標系から、スクリーン座標系へ変換します。

この正規化デバイス座標系は、次の値の範囲に収まります。
-1 <= x <= 1
-1 <= y <= 1
-1 <= z <= 1 (IF OpenGL)
0 <= z <= 1 (IF DirectX)

これらをふまえて、まず DirectX の行列

この式が実際にどのようなことをしているか考えてみましょう。
実際に計算すると次のようになります。

行列の計算は次のようになるので、

ベクトルに行列を掛け算して、式変形すると次のようになります。

同じく、OpenGLの行列も計算してみましょう。

さきほどのおさらいで x, y,がとる範囲(-1~1)をみるとわかるように、
行列の計算によりオフセットの位置から、ウィンドウの幅分へ引き延ばしていることが分かります。
ここで、ウィンドウの大きさに引き延ばすからこそ、前回の 射影トランスフォーム行列 にて、
ウィンドウのアスペクト比を使用して補正していたのですね。

1つ気になるところといえば、DirectXでは が反転している点があります。
これはDirectXの出力先のスクリーン画面では、yが大きいほど下方向に描写されるためです。
3D空間上ではもちろん上がプラスため、ビューポート変換で反転しているわけです。

OpenGLの場合は、そもそも出力先のスクリーン画面が上がプラスの設計のため
行列を作っても y の反転は不要となっております。

z については、0がMinZ に 1がMaxZ になるような式になることが分かります。

DirectXとOpenGLとで、射影トランスフォーム後の 値の範囲が異なるため
微妙に式が違っています。実際に計算してあてはめると次のようになります。

OpenGLでも結局、最終的なz値は 0 <= z <= 1 の範囲に収めているようですね。

なお、この MinZMaxZ の設定を利用すると、たとえば、
1度目の描写は、MinZ = 0.0, MaxZ = 0.5
2度目の描写は、MinZ = 0.5, MaxZ = 1.0
のように、1度目の描写の後ろ面に、2度目の描写を行うといったことができます。


おわりに

ここまでのいくつかの回で、
3DCGに必要な座標系と、その座標系への変換をまとめました。
そして、右手系と左手系、OpenGLとDirectXとで
数式のどこに差が表れてくるのかが分かりました。

これまでDirectXを使っていた方が、WebGL(OpenGL)を始めたい。
逆に、WebGLを使っていた方が左手座標系のUnityを使いたいなどがあるかもしれません。
そんな時に、これらのまとめを見て、座標系や、
DirectX/OpenGLの各変換のこと動きを知っておくと
理解が進みやすいのかなと思います。

以上、ありがとうございました。

広告

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

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

WordPress.com ロゴ

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

Twitter 画像

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

Facebook の写真

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

Google+ フォト

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

%s と連携中