我正在尝试了解OpenGL坐标系。但是,有些教程说默认坐标系是左手的(请参见http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx),而其他教程则说它是右手的(请参见http:// www .falloutsoftware.com / tutorials / gl / gl0.htm)。哪个是对的?我知道我们可以通过镜像将一个变换为另一个,但是我想知道默认坐标。
我正在尝试了解OpenGL坐标系。但是,有些教程说默认坐标系是左手的(请参见http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx),而其他教程则说它是右手的(请参见http:// www .falloutsoftware.com / tutorials / gl / gl0.htm)。哪个是对的?我知道我们可以通过镜像将一个变换为另一个,但是我想知道默认坐标。
Answers:
这里有些混乱。
OpenGL在对象空间和世界空间中都是右撇子。
但是在窗口空间(又称屏幕空间)中,我们突然惯用了左手。
这是怎么发生的?
从右手到左手的方式是在glOrtho
或glFrustum
投影矩阵中输入负的z缩放比例。将z缩放为-1(同时保持x和y不变)具有更改坐标系的手性的效果。
对于glFrustum,
far和near应该是正数,far > near。说远= 1000,近= 1。然后C =-(1001)/(999)= -1.002。
看这里更多详细信息和图表,。
从正交角度看,glOrtho生成如下矩阵:
在这里,离开,right,bottom和top只是左垂直,右垂直,底部水平,顶部水平剪切平面(resp)的坐标。
在近及远的飞机,然而,在不同的规定。的邻近参数定义为
远:
这里我们有一个典型的规范视图
因为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。
gluLookAt
计算中取反正向向量与更改坐标空间的惯用度无关,这就是该矩阵的计算方式(实际上+ z实际上在惯用右手空间中是“向后”)。gluLookAt
除了在右手空间中计算普通的刚体变换(旋转+平移)外,别无其他。正如您在答案中已经指出的那样,固定功能管线(通常也包括着色器)使用的投影矩阵在对z分量取反时执行实际的手形改变。
gluLookAt
,则不会改变基准gluLookAt
吗?绝对不是(因为你可能知道,并不是“人人”的用途gluLookAt
为视图矩阵计算),因为你应该知道gluLookAt
做什么比一堆旋转和平移电话(被他们甚至伪装成其他“高层”一词的“变化基础”),完全不涉及任何思考。
默认情况下,“标准化设备坐标”是左手的。
默认情况下,glDepthRange为[0,1](近,远),使+ z轴指向屏幕,并向右+ x,向上+ y是左手系统。
将深度范围更改为[1,0]将使系统成为惯用右手。
我很惊讶没有人提及: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)根本没有理会在他们的投影矩阵中进行取反。
因为它与我的发现有出入,所以我确实做了一部分。
更改DepthRange或DepthFunc并使用ClearDepth(0)都可以,但是当同时使用它们时,它们会互相抵消,返回左手系统。
您应该只注意到OpenGL只知道NDC!那是左手坐标系。
无论使用哪种坐标系-左手坐标系或右手坐标系-都需要镜像到NDC。如果愿意,可以将世界空间完全作为左手坐标系处理。
我认为这很传统。就是这样。也许它只是想区别于DirectX。
松田刚一(Kouichi Matsuda)撰写的《 WebGl编程指南》一书在“ WebGl / OpenGl:左手还是右手?”上花费了将近十页。
根据这本书:
实际上,大多数人使用右手系统
OpenGl实际上是内部的左手系统
在内部,更深层次的实际上两者都不是。在最底层,OpenGl不在乎z值。绘制顺序决定了在顶部绘制的内容(先绘制一个三角形,然后绘制一个四边形,然后四边形覆盖该三角形)。
我并不完全同意“两者都不是”,但无论如何这可能是一个哲学问题。
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值与深度缓冲区中的值进行比较,如果片段未通过深度测试,则将其丢弃,因此,根据三角形的深度和使用的深度函数。
通过使用OpenGL内置的投影和变换功能,在屏幕上观察运动遵循右手坐标系的规则。例如,如果视图前面的对象沿z轴正方向平移,则该对象将向您移动。
深度缓冲区恰好相反,这就是NDC(标准化设备坐标)起作用的地方。如果将GL_LESS传递给glDepthFunc意味着像素比深度缓冲区中的像素更接近您时将进行绘制,则认为像素位于左手坐标系中。
还有一个坐标系,那就是视口!视口的坐标系是+ x指向右侧,+ y指向下方。我认为到此为止,习惯性尚无定论,因为我们此时仅处理x,y。
最后,引擎盖下的gluLookAt必须否定查找向量。由于数学假设矢量正指向其所看物体的正方向,并且照相机向下看-z,因此必须对视向量进行取反以使其与照相机对齐。
嚼点东西。将右手坐标系的z方向称为正向向量是没有意义的。我认为Microsoft在设计Direct3D时意识到了这一点。