OpenGL的NDC坐标形成了一个立方体,它的-Z
边压在屏幕上,而它的+Z
边离屏幕最远。
当我使用...
// ortho arguments are: left, right, bottom, top, near, far
pos = pos * glm::ortho<float>(-1, 1, -1, 1, -1, 1);
... pos
的z
分量被反射;-1变为1,10变为-10,以此类推。
persp做了类似的事情,这有点奇怪。如果一个位置的z
等于near
,我希望它停留在NDC立方体面向屏幕的平面上,但相反,它的符号被任意翻转;它甚至不会落在最远的那一面。
这是为什么呢?
1条答案
按热度按时间zphenhs41#
OpenGL的NDC坐标形成了一个立方体,它的-Z面压在屏幕上,而它的+Z面离屏幕最远。
我看了一下Song Ho Ahns关于OpenGL转换的教程,以确保不会说一些愚蠢的事情。
在透视投影中,截棱锥体中的3D点(视点坐标)被Map到立方体(NDC);x坐标的范围为[l,r]到[-1,1],y坐标的范围为[b,t]到[-1,1],z坐标的范围为[-n,-f]到[-1,1]。
注意,视点坐标在右手坐标系中定义,但NDC使用左手坐标系。也就是说,原点处的相机在视点空间中沿-Z轴观看,但在NDC中沿+Z轴观看。
(强调是我的意思。)
他提供了下面这个很好的说明:
所以我得出结论
不应生成单位矩阵,而应生成镜像z轴的单位矩阵,例如
由于手头没有
glm
,我从github(glm)上的源代码中取出了相关代码行,在源代码中挖掘了一会儿,终于找到了glm::ortho()
在orthoLH_ZO()
中的实现:我对这段代码进行了一些转换,生成了下面的示例:
编译并启动后,它提供以下输出:
Live Demo on coliru
Huh! z按-1缩放,即z值在x-y平面上镜像(如预期)。
因此,OP的观察是完全正确和合理的:
......反映pos的z分量;-1变为1,10变为-10,以此类推。
最难的部分:
这是为什么呢?
我个人猜测:一个SGI大师发明了所有这些GL的东西,他/她很聪明。
另一种猜测:在眼睛空间中,x轴指向右侧,y轴指向上方。将其转换为屏幕坐标,y轴应该指向下方(因为像素通常/技术上从左上角开始寻址)。因此,这引入了另一个镜像轴,它(再次)改变了坐标系的手性。
这是一个有点不满意,因此我谷歌,发现这(重复?):
SO: Why is the Normalized Device Coordinate system left-handed?