OpenGL座標系は左利きですか、それとも右利きですか?


85

OpenGL座標系を理解しようとしています。ただし、一部のチュートリアルでは、デフォルトの座標系が左利きであると述べており(http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspxを参照)、他のチュートリアルでは、右利きであると述べています(http:// www .falloutsoftware.com / tutorials / gl / gl0.htm)。どちらが正しい?ミラーリングによって一方を他方に変換できることは理解していますが、デフォルトの座標を知りたいです。



2
これは、シェーダーでの変換の記述方法に完全に依存しているのではないので、完全にあなた次第です。
jcoder 2013年

私の2セントevl.uic.edu/ralph/508S98/coordinates.htmlだけで、いくつかの自明の画像があります。
rraallvv 2013

受け入れた回答を更新することを検討するとは思いませんか?
ジョナサンミー

回答:


131

ここにはいくつかの混乱があります。

ここに画像の説明を入力してください

OpenGLは、オブジェクト空間とワールド空間で右利きです。

しかし、ウィンドウスペース(別名スクリーンスペース)では、突然左利きになります。

これはどのように起こりましたか?

右手から左手に移動する方法は、glOrthoまたはglFrustum射影行列の負のzスケーリングエントリです。zを-1でスケーリングすると(xとyはそのまま)、座標系の利き手を変更する効果があります。

glFrustumの場合、

ここに画像の説明を入力してください ここに画像の説明を入力してください

farnearは正であると想定され、far > nearです。遠い= 1000と近い= 1と言います。次に、C =-(1001)/(999)=-1.002。

参照してくださいここに詳細と図について。

正投影視点、glOrthoは、このような行列を生成します。

ここに画像の説明を入力してください

ここで、左垂直右垂直下水平上水平クリッピング平面(または)の座標です

近く遠くのプレーンは、しかし、別々に指定されています近くのパラメータは以下のように定義されます

  • 近く:より近い深さのクリッピング平面までの距離。平面が視聴者の後ろにある場合、この距離は負になります。

そしてはるかに:

  • zFarより遠い深度クリッピング平面までの距離。平面が視聴者の後ろにある場合、この距離は負になります。

ここに典型的な標準的なビューボリュームがあります

カノニカル

z乗数は(-2 /(far-near))であるため、マイナス記号はzを-1だけ効果的にスケーリングします。これは、表示変換中に「z」が左利きになることを意味します。OpenGLで「右利き」の座標系として機能するだけなので、ほとんどの人には知られていません。

だから、あなたが呼ぶなら

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

次に、NEARPLANEはあなたの10ユニット先にあります。どこにいますか?なぜ、原点で、x軸が右に、y軸が頭の上にあり、鼻が負のz軸を下に向けているのですか(これがデフォルトです。デフォルトでは、カメラは原点にあります。 、は負のz軸を下向きで、上向きベクトルは(0、1、0)です。 ")。したがって、近平面はz = -10にあります。遠方の平面は、z = +10で10ユニット後ろにあります


1
「前方ベクトルはgluLookAtで否定されます」-これが事実であることを確認できますか?gluPerspectiveまたはglFrustumまたはglOrthoではありませんか?
コス2012

1
ウィンドウスペースだけでなく、クリップスペースから突然左利きになりました。
legends2k 2013

3
答え全体の場合は+1、「右利きから左利きへの移行方法は、関数であるgluLookAt()の標準実装で順方向ベクトルが否定されるためです。誰もがビューマトリックスを作成するために使用します。順方向ベクトルを否定すると、これは座標系の利き手を変更する効果があります。」、これは単なるゴミです...
クリスチャンラウ2013年

2
...gluLookAt計算で前方ベクトルを否定することは、座標空間の利き手を変更することとは何の関係もありません。これが、この行列の計算方法です(実際、+ zは右利き空間では実際に「後方」です)。gluLookAt右手空間で通常の剛体変換(回転+平行移動)を計算する以外に何もしません。すでに回答で述べたように、zコンポーネントの否定で実際の利き手変更を実行するのは、固定関数パイプライン(および通常はシェーダーでも)によって使用される射影行列です。
クリスチャンラウ2013年

2
@bobobobo回転関数と平行移動関数のみを使用してビュー行列を計算する場合(利き手を変更したと非難することはないと思います)、代わりgluLookAtに基底変換はありgluLookAtませんか?絶対にそうではありません(「誰もが」gluLookAtビューマトリックスの計算に使用しないことをおそらく知っているので)、なぜならあなたが知っgluLookAtているはずのように、回転と平行移動の呼び出しの束以外の何もしないからです(それらは「高レベル」の用語「基礎」)、反射はまったく含まれていません。
クリスチャンラウ2013年

26

デフォルトでは、正規化されたデバイス座標は左利きです。

glDepthRangeはデフォルトで[0、1](near、far)であり、+ z軸を画面に向け、+ xを右に、+ yを上にすると左手系になります。

深度範囲を[1、0]に変更すると、システムは右利きになります。

ニコルからの以前の回答を引用する:(取り消し線は私の仕事であり、以下で説明します)

誰も何も言及していないことに驚いています。OpenGLは左手座標系でも機能します。少なくとも、シェーダーを使用していて、デフォルトの深度範囲を使用している場合はそうなります。

固定機能パイプラインを破棄すると、「クリップスペース」を直接処理します。OpenGL仕様では、クリップスペースを4D同次座標系として定義しています。正規化されたデバイス座標を介して、ウィンドウスペースまで変換を追跡すると、これがわかります。

ウィンドウスペースは、ウィンドウのピクセルのスペースにあります。原点は左下隅にあり、+ Yが上に、+ Xが右になります。これは、右手の座標系に非常によく似ています。しかし、Zはどうですか?

デフォルトの深度範囲(glDepthRange)は、近Z値を0に設定し、遠Z値を1に設定します。したがって、+ Zはビューアから遠ざかります。

これは左手座標系です。はい、できます深度テストをGL_LESSからGL_GREATERに変更し、glDepthRangeを[0、1]から[1、0]に変更します。ただし、OpenGLのデフォルトの状態は、左手座標系で機能することです。また、クリップスペースからウィンドウスペースに到達するために必要な変換はいずれもZを否定しません。したがって、クリップスペース、頂点(またはジオメトリ)シェーダーの出力は左利きのスペースです(ちょっと。4Dの同種のスペースなので、利き手を特定するのは難しいです)。

固定関数パイプラインでは、標準の射影行列(glOrtho、glFrustumなどによって生成される)はすべて、右手系の空間から左手系の空間に変換されます。それらはZの意味を反転させます。それらが生成する行列を確認するだけです。目の空間では、+ Zは視聴者に向かって移動します。投影後の空間では、それは離れます。

Microsoft(およびGLide)は、射影行列で否定を実行することを単に気にしなかったのではないかと思います。

それが私の発見から逸脱したので、私は一部を打ちました。

DepthRangeまたはDepthFuncを変更してClearDepth(0)を使用することは機能しますが、両方を使用すると、それらは互いにキャンセルされて左利きのシステムに戻ります。


深度範囲を[1、-1]にすることはできません。[1、0]という意味だと思います。また、これは以前に指摘されています。
ニコルボーラス2012

あなたの答えは素晴らしいですが、DirectXの質問には残念です。ここに再投稿する必要があります!
hultqvist 2012

3
@SigTermなぜ虚偽の陳述を訂正する価値がないと思いますか?デフォルトの座標系が実際には右手ではないことを確認するために、頂点座標と行列回転の生成のトラブルシューティングに数時間を費やしました。
hultqvist 2012

1
問題は、それが左利きのシステムなのか右利きのシステムなのかということでした。この回答にはそれ以上の詳細があり、右利きにするための他の2つの方法を説明しています。行列変換に-1を追加することは、それを行うもう1つの方法です。しかし、システムがデフォルトで右利きであると信じている場合は、それは問題ではありません。何を変更するかを知っている場合にのみ、何かを変更できます。それでも
hultqvist 2012

1
答えは非常に啓発的で、検索結果に出てきたので、それだけの価値がありました。
OpenGLESを学ぶ2012

13

NDCのみ

OpenGLはNDCしか知らないことに注意してくださいそれは左手座標系です。

使用する座標系(左手系または右手系の軸座標系)に関係なく、すべてNDCにミラーリングする必要があります。必要に応じて、ワールドスペースを左手座標系として完全に処理できます。

なぜ私たちは通常、世界空間で右手の座標系を使用するのですか?

従来型だと思います。それだけです。たぶんそれはDirectXと区別したいだけです。


3
これは十分に繰り返されていないと思います。「モデリング変換」、「ビュー変換」、「パースペクティブ変換」を示すこれらの図はすべて、OpenGLの本質的な部分ではないことを示していません。シェーダーの有無にかかわらず、マトリックスの有無にかかわらず、すべての変換を手動で行うこともできます。
トム

3
ただし、「正規化されたデバイス座標」という単語を含めるように繰り返すとよい場合があります。
トミー

6
OpenGLはDirectXより数年前から存在しているため、OpenGLは確かにDirectXとの区別を試みていませんでした。DirectXの主任開発者であるAlexSt。Johnは、左利きの座標系を採用するというMicrosoftの決定は、「部分的には個人的な好みから」であり、「任意の選択」であると述べています。
クリスノレット2017年

これは完全に正しいわけではありません。OpenGLは、クリッピングが発生するため、クリッピング座標系も認識しています。クリップ座標系は、NDC座標系と同じ利き手です。
プラズマセル

7

松田浩一の著書「WebGlプログラミングガイド」は、「WebGl / OpenGl:左利きか右利きか」に約10ページを費やしています。

本によると:

  • 実際には、ほとんどの人は右利きのシステムを使用しています

  • OpenGlは実際には内部的には左利きのシステムです

  • 内部的には、もっと深く、実際にはどちらでもありません。一番下では、OpenGlはz値を気にしません。物を描く順序によって、上に何を描くかが決まります(最初に三角形を描き、次にクワッドを描きます。クワッドが三角形をオーバーライドします)。

私は「どちらでもない」に完全には同意しませんが、それはおそらく哲学的な質問です。


6
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). これは、深度テストがない場合に当てはまります。深度テストが存在する場合、フラグメントのz値が深度バッファーの値と比較され、深度テストに失敗した場合はフラグメントが破棄されるため、クワッドは深度と使用される深度関数。
chrisvarnz 2018

3

Openglは間違いなく左利きです。射影行列のz値を否定しているため、反対のことを述べているチュートリアルがたくさんあります。最終的な頂点が頂点シェーダー内で計算されると、渡された頂点がクライアント側(右側の座標)から左側に変換され、頂点がジオメトリシェーダーとフラグメントシェーダーに渡されます。クライアント側で右側の座標系を使用する場合、Openglは気にしません。左利きの正規化された座標系のみを認識します。

編集:私を信頼していない場合は、変換行列を追加して頂点シェーダーを試してみてください。Openglが左利きであるかどうかを簡単に確認できます。


0

OpenGLに組み込まれている投影および変換関数を使用することにより、画面上の動きを観察することは、右手の座標系の規則に従います。たとえば、ビューの前にあるオブジェクトが正のz方向に移動すると、オブジェクトは手前に移動します。

デプスバッファはまったく逆であり、ここでNDC(正規化されたデバイス座標)が機能します。GL_LESSをglDepthFuncに渡すことで、ピクセルがすでに深度バッファーにあるものよりも近くにあるときに描画されることを意味する場合、ピクセルは左手座標系にあると見なされます。

もう1つの座標系があり、それがビューポートです。ビューポートの座標系は、+ xが右を指し、+ yが下を指すようになっています。この時点ではx、yのみを扱っているので、この時点では利き手は無意味だと思います。

最後に、内部のgluLookAtは、ルックアットベクトルを無効にする必要があります。数学では、ベクトルが見ているオブジェクトに向かって正の方向を向いており、カメラが-zを見下ろしていると想定しているため、カメラと整列するように、ルックアットベクトルを否定する必要があります。

噛むもの。右手の座標系のz方向を順方向ベクトルと呼ぶのはあまり意味がありません:)。MicrosoftはDirect3Dを設計したときにこれを実現したと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.