OpenGL坐标系是左手系还是右手系?


84

我正在尝试了解OpenGL坐标系。但是,有些教程说默认坐标系是左手的(请参见http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx),而其他教程则说它是右手的(请参见http:// www .falloutsoftware.com / tutorials / gl / gl0.htm)。哪个是对的?我知道我们可以通过镜像将一个变换为另一个,但是我想知道默认坐标。



2
这不完全取决于您如何在着色器中编写变换,因此完全取决于您吗?
编码器

只有我的两分钱evl.uic.edu/ralph/508S98/coordinates.html,上面有一些自我解释的图像。
rraallvv 2013年

我不认为您会考虑更新接受的答案吗?
乔纳森·米

Answers:


131

这里有些混乱。

在此处输入图片说明

OpenGL在对象空间和世界空间中都是右撇子

但是在窗口空间(又称屏幕空间)中,我们突然惯用了左手

这是怎么发生的

从右手到左手的方式是在glOrthoglFrustum投影矩阵中输入负的z缩放比例。将z缩放为-1(同时保持x和y不变)具有更改坐标系的手性的效果。

对于glFrustum,

在此处输入图片说明 在此处输入图片说明

farnear应该是正数,far > near。说= 1000,= 1。然后C =-(1001)/(999)= -1.002。

这里更多详细信息和图表,。

正交角度看,glOrtho生成如下矩阵:

在此处输入图片说明

在这里,离开rightbottomtop只是左垂直右垂直底部水平顶部水平剪切平面(resp)的坐标

的飞机,然而,在不同的规定。的邻近参数定义为

  • Near:到更近的深度裁剪平面的距离。如果平面要在查看器后面,则此距离为负。

远:

  • zFar到更远的深度裁剪平面的距离。如果平面要在查看器后面,则此距离为负。

这里我们有一个典型的规范视图

典范

因为z乘数是(-2 /(far-near)),所以负号有效地将z缩放为-1。这意味着“ z”是左旋的在视图转换过程中的,对于大多数人而言并不为人所知,因为他们只是在OpenGL中作为“右手”坐标系工作。

所以,如果你打电话

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

然后NEAR PLANE在你前面10个单位。你在哪?为什么在原点处将x轴向右,将y轴置于头顶上,而将鼻子指向负z轴(这是默认设置,“默认情况下,摄像头位于原点,指向负z轴,并且具有(0,1,0)的向上矢量。”)。因此,近平面位于z = -10。远平面在您身后10个单位处,z = + 10


1
“在gluLookAt中否定了前向矢量”-您可以确认是否是这种情况吗?不是gluPerspective或glFrustum或glOrtho?
科斯2012年

1
我们突然从剪辑空间向左转,而不仅仅是窗口空间。
legends2k 2013年

3
整个答案为+1,“我们从惯用右手变成惯用左手的方式是-1(等待,而不是-2 ),这是因为在函数gluLookAt()的标准实现中否定了前向矢量每个人都可以使用它来创建视图矩阵。对正向向量求反时,会改变坐标系的惯性。” ,那不过是垃圾而已...
Christian Rau

2
...在gluLookAt计算中取反正向向量与更改坐标空间的惯用度无关,这就是该矩阵的计算方式(实际上+ z实际上在惯用右手空间中是“向后”)。gluLookAt除了在右手空间中计算普通的刚体变换(旋转+平移)外,别无其他。正如您在答案中已经指出的那样,固定功能管线(通常也包括着色器)使用的投影矩阵在对z分量取反时执行实际的手形改变。
克里斯汀·劳

2
@bobobobo您的说法是,如果仅使用旋转和平移函数来计算视图矩阵(我想您不会指责改变惯性),而不是gluLookAt,则不会改变基准gluLookAt吗?绝对不是(因为你可能知道,并不是“人人”的用途gluLookAt为视图矩阵计算),因为你应该知道gluLookAt做什么比一堆旋转和平移电话(被他们甚至伪装成其他“高层”一词的“变化基础”),完全不涉及任何思考。
克里斯汀·劳

26

默认情况下,“标准化设备坐标”是左手的。

默认情况下,glDepthRange为[0,1](近,远),使+ z轴指向屏幕,并向右+ x,向上+ y是左手系统。

将深度范围更改为[1,0]将使系统成为惯用右手。

引用Nicol的先前答案:(删除线是我的工作,下面说明)

我很惊讶没有人提及:OpenGL也可以在左手坐标系中工作。至少在使用着色器并使用默认深度范围时,它才起作用。

一旦淘汰了固定功能管道,就可以直接处理“剪贴空间”。OpenGL规范将剪辑空间定义为4D同构坐标系。当您通过归一化的设备坐标进行转换时,一直到窗口空间,您都可以找到。

窗口空间等于窗口像素的空间。原点在左下角,+ Y向上,+ X右侧。这听起来很像一个右手坐标系。但是Z呢?

默认深度范围(glDepthRange)将Near Z值设置为0并将far Z值设置为1。所以+ Z消失了观看者。

那是左手坐标系。是的你可以将深度测试从GL_LESS更改为GL_GREATER并将glDepthRange从[0,1]更改为[1,0]。但是OpenGL的默认状态是在左手坐标系中工作。从剪贴空间进入窗口空间的任何变换都不需要Z。很难确定惯用的惯用语)。

从右手空间中固定功能流水线,标准投影矩阵(由glOrtho,glFrustum等产生的)中的所有变换到左手之一。他们翻转了Z的含义;只需检查它们生成的矩阵即可。在眼睛空间中,+ Z向观察者移动;在投影后空间中,它会移开。

我怀疑微软(和GLide)根本没有理会在他们的投影矩阵中进行取反。

因为它与我的发现有出入,所以我确实做了一部分。

更改DepthRangeDepthFunc并使用ClearDepth(0)都可以,但是当同时使用它们时,它们会互相抵消,返回左手系统。


深度范围不能为[1,-1]。我认为您的意思是[1,0]。另外,之前已经指出了这一点
Nicol Bolas 2012年

您的答案很好,对于DirectX问题来说太糟糕了,您应该在这里重新发布!
hultqvist 2012年

3
@SigTerm为什么您认为更正错误的陈述不值得?我花了几个小时对顶点坐标和矩阵旋转生成进行故障排除,只是为了发现默认坐标系实际上不是惯用右手的。
hultqvist 2012年

1
问题是这是左撇子还是右撇子系统。这个答案的细节要多得多,解释了另外两种获得右手的方法,在矩阵转换中添加-1是另一种实现方法。但是,如果您认为系统默认情况下是右手操作,那么这一切都没有关系,只有知道更改的内容后才能进行更改。仍然
hultqvist 2012年

1
我发现答案非常有启发性,它出现在搜索中,因此对我来说是值得的。
2012年

13

仅NDC

您应该只注意到OpenGL只知道NDC!那是左手坐标系。

无论使用哪种坐标系-左手坐标系或右手坐标系-都需要镜像到NDC。如果愿意,可以将世界空间完全作为左手坐标系处理。

为什么我们通常在世界空间中使用右手坐标系?

我认为这很传统。就是这样。也许它只是想区别于DirectX。


3
我认为这还不够重复。所有这些显示“建模变换”,“视图变换”,“透视变换”的图都无法表明它们不是OpenGL的固有部分。您甚至可以在有或没有着色器,有或没有矩阵的情况下手动进行所有变换。
汤姆(Tom)

3
但是,如果重复它以包括“标准化设备坐标”一词,可能会更好。
汤米”,

6
OpenGL比DirectX早了几年,因此OpenGL当然不会试图将自己与DirectX区分开。DirectX的主要开发人员Alex St. John已表示,微软选择左手坐标系的决定“部分出于个人喜好”和“任意选择”。
克里斯·诺莱特

这并不完全正确。OpenGL也知道剪切坐标系,因为剪切发生在其中。剪辑坐标系与NDC坐标系tho具有相同的惯用性。
plasmacel

7

松田刚一(Kouichi Matsuda)撰写的《 WebGl编程指南》一书在“ WebGl / OpenGl:左手还是右手?”上花费了将近十页。

根据这本书:

  • 实际上,大多数人使用右手系统

  • 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 '18

3

Opengl绝对是左撇子。您会看到很多教程都相反,因为它们在投影矩阵中取反了z值。当在顶点着色器中计算最终顶点时,它将把您从客户端(右手坐标)传递的顶点转换为左手顶点,然后将这些顶点传递到几何体着色器和片段着色器。如果在客户端使用右手坐标系,则Opengl不在乎。它只知道左手的归一化坐标系。

编辑:如果您不信任我,只需在顶点着色器中进行实验即可,添加一个转换矩阵,您可以轻松查看Opengl是否为左撇子。


0

通过使用OpenGL内置的投影和变换功能,在屏幕上观察运动遵循右手坐标系的规则。例如,如果视图前面的对象沿z轴正方向平移,则该对象将向您移动。

深度缓冲区恰好相反,这就是NDC(标准化设备坐标)起作用的地方。如果将GL_LESS传递给glDepthFunc意味着像素比深度缓冲区中的像素更接近您时将进行绘制,则认为像素位于左手坐标系中。

还有一个坐标系,那就是视口!视口的坐标系是+ x指向右侧,+ y指向下方。我认为到此为止,习惯性尚无定论,因为我们此时仅处理x,y。

最后,引擎盖下的gluLookAt必须否定查找向量。由于数学假设矢量正指向其所看物体的正方向,并且照相机向下看-z,因此必须对视向量进行取反以使其与照相机对齐。

嚼点东西。将右手坐标系的z方向称为正向向量是没有意义的。我认为Microsoft在设计Direct3D时意识到了这一点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.