我试图了解OpenGL坐标系。但是,一些教程说默认坐标系是左撇子(见http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx),其他人说它是右撇子(见http://www.falloutsoftware.com/tutorials/gl/gl0.htm)。哪个是对的?我知道我们可以通过镜像将一个转换为另一个,但我想知道默认坐标。
答案 0 :(得分:121)
这里有一些混乱。
OpenGL在对象空间和世界空间中是右手。
但是在窗口空间(又名屏幕空间)中,我们突然左撇子。
这是怎么发生的??
我们从右手到左手的方式是glOrtho
或glFrustum
投影矩阵中的负z缩放条目。将z缩放-1(同时保留x和y)可以改变坐标系的旋向性。
对于glFrustum,
远和在附近应该是正面的,远> 近。说远 = 1000且接近 = 1。然后C = - (1001)/(999)= -1.002。
有关详细信息和图表,请参阅here。
从正交视角,glOrtho生成如下矩阵:
此处,左,右,底部和顶部仅为the coordinates for left vertical, right vertical, bottom horizontal, top horizontal clipping planes (resp)。
近和远平面,但的指定方式不同。 near 参数定义为
远:
这里我们有一个典型的规范视图卷
因为z乘数是(-2 /(远近)),减号有效地将z缩放-1 。这意味着在观看转换期间“z”是左手转动,大多数人都不知道,因为他们只是在OpenGL中作为“右手”坐标系工作。
所以,如果你打电话
glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,
然后,NEAR PLANE 超过10个单位。你在哪?为什么,在原点,右边的x轴,头顶的y轴,你的鼻子指向负的z轴(这是默认的{{3} })。所以近平面在z = -10。远的平面比你强10个单位,z = + 10 。
答案 1 :(得分:24)
默认情况下,规范化设备坐标是左撇子。
glDepthRange默认为[0,1](近,远),使+ z轴指向屏幕,+ x向右,+ y向上是左手系统。
将深度范围更改为[1,0]将使系统右手。
引用之前的answer from Nicol :(罢工是我的工作,如下所述)
我很惊讶没有人提到过:OpenGL也适用于左手坐标系。至少,当您使用着色器并使用默认深度范围时,它会发生。
一旦你抛出固定功能管道,你就直接处理“剪辑空间”。 OpenGL规范将剪辑空间定义为4D齐次坐标系。当您通过规范化的设备坐标和向下到窗口空间进行变换时,您会发现这一点。
窗口空间位于窗口像素的空间中。原点位于左下角,+ Y向上,+ X向右。这听起来非常像右手坐标系。但是Z怎么样?
默认深度范围(glDepthRange)将近Z值设置为0,将远Z值设置为一。所以+ Z正从观众那里远离。
这是一个左手坐标系。是的,您可以
将深度测试从GL_LESS更改为GL_GREATER,并且将glDepthRange从[0,1]更改为[1,0]。但是,OpenGL的默认状态是在左手坐标系中工作。从剪辑空间到达窗口空间所需的变换都没有否定Z.所以剪辑空间,顶点(或几何)着色器的输出是一个左手空间(有点。它是一个4D均匀空间,所以很难确定用手。)在固定功能管道中,标准投影矩阵(由glOrtho,glFrustum等产生)都从右手空间转换为左手。他们颠覆了Z的意思;只需检查它们产生的矩阵。在眼睛空间中,+ Z向观察者移动;在后投影空间中,它会移开。
我怀疑微软(和GLide)根本没有在他们的投影矩阵中执行否定。
由于它与我的发现不同,我确实打了一部分。
更改DepthRange 或 DepthFunc并使用ClearDepth(0)可以正常工作,但是当使用它们时,它们会相互抵消回到左手系统。
答案 2 :(得分:10)
你应该只注意到 OpenGL only knows NDC!!
,它是一个左手坐标。
无论你使用什么坐标,左手,右手轴坐标等都需要镜像到NDC。
如果你愿意,你可以用左坐标完全写出世界空间。
我认为这是传统的。它就是这样。也许它只是想与DirectX区别开来。
答案 3 :(得分:7)
本书" WebGl编程指南"作者:Kouichi Matsuda花了将近十页的篇幅来自" WebGl / OpenGl:左手或右手?"
根据这本书:
在实践中,大多数人使用右手系统
OpenGl实际上是一个内部左手系统
在内部,更深层次,它实际上都没有。在最底层,OpenGl并不关心z值。绘制图形的顺序决定了在顶部绘制的内容(首先绘制一个三角形,然后绘制一个四边形,四边形覆盖三角形)。
我并不完全同意"它不是"但无论如何,这可能是一个哲学问题。
答案 4 :(得分:3)
Opengl绝对是左撇子。你会看到许多教程说明相反的原因,因为它们否定了投影矩阵中的z值。当在顶点着色器内计算最终顶点时,它将您从客户端(右手坐标)传递的顶点转换为左手,然后将顶点传递给几何着色器和片段着色器。如果您在客户端使用右手坐标系,Opengl并不关心。它只知道左手的标准化坐标系。
编辑:如果你不相信我,只需通过添加翻译矩阵在你的顶点着色器中进行实验,你就可以很容易地看出Opengl是否是左撇子。
答案 5 :(得分:0)
通过使用OpenGL内置的投影和变换功能,观察屏幕上的运动遵循右手坐标系的规则。例如,如果视图前面的对象沿z轴正方向平移,则该对象将向您移动。
深度缓冲区正好相反,这就是NDC(标准化设备坐标)起作用的地方。如果将GL_LESS传递给glDepthFunc意味着像素比深度缓冲区中的像素更接近您时将进行绘制,则认为像素位于左手坐标系中。
还有一个坐标系,那就是视口!视口的坐标系是+ x指向右侧,+ y指向下方。我认为到此为止,习惯性尚无定论,因为我们此时仅处理x,y。
最后,引擎盖下的gluLookAt必须否定查找向量。由于数学假设矢量朝着它所看着的对象指向一个正方向,并且照相机向下看-z,因此必须取反向量,使其与照相机对齐。
需要咀嚼的东西。将右手坐标系的z方向称为前向矢量:)并没有多大意义。我认为Microsoft在设计Direct3D时意识到了这一点。