はじめに

こんにちは!
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の各変換のこと動きを知っておくと
理解が進みやすいのかなと思います。

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

関連記事

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