为什么z坐标没有被glm::ortho()投影归一化
Why z-coordinate is not normalized by glm::ortho() projection?
我试图更好地理解glm::ortho是如何工作的,源代码(v 0.9.7)看起来像这样:
template <typename T>
GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> ortho
(
T left,
T right,
T bottom,
T top,
T zNear,
T zFar
)
{
tmat4x4<T, defaultp> Result(1);
Result[0][0] = static_cast<T>(2) / (right - left);
Result[1][1] = static_cast<T>(2) / (top - bottom);
Result[2][2] = - static_cast<T>(2) / (zFar - zNear);
Result[3][0] = - (right + left) / (right - left);
Result[3][1] = - (top + bottom) / (top - bottom);
Result[3][2] = - (zFar + zNear) / (zFar - zNear);
return Result;
}
一切都很好,工作很完美,但有一件事让我担心。为什么得到的矩阵将坐标'x'和'y'归一化为[-1,1](它涉及视图区域内的点),而不是'z'(深度)?我们可以去掉Result[3][2]语句前面的减号,然后我们也会得到范围[-1,1]的z值(维基百科中的正交投影)。
相反,相机前面的所有点的z值都低于-1,但为什么?这是因为一些优化问题吗?还是有其他原因让事情变得不那么直观?
它确实映射到z的[- 1,1]区间。但是,映射到该区间的值介于-zNear
和-zFar
之间。
提取z
的部分变换:
z --> -2 * z / (zFar - zNear) - (zFar + zNear) / (zFar - zNear) =
(-2 * z - zFar - zNear) / (zFar - zNear)
,插入-zNear
和-zFar
:
-zNear --> (2 * zNear - zFar - zNear) / (zFar - zNear) =
(zNear - zFar) / (zFar - zNear) =
-1
-zFar --> (2 * zFar - zFar - zNear) / (zFar - zNear) =
(zFar - zNear) / (zFar - zNear) =
1
为什么要映射负z值?OpenGL的通用策略是,在模型/视图转换被应用后,你处于"眼睛坐标"系统中。在这个坐标系中,"相机"位于原点,并指向负 z轴。因此可见的z值为负,距离视点(原点)zNear
和zFar
的点位于-zNear
和-zFar
。
现在,特别是在使用可编程管道时,没有什么强制您遵循此策略。你可以以任何你想要的方式定义和应用你的转换,只要它们最终在正确的范围内产生NDC(归一化设备坐标)。许多人仍然使用与固定管道中使用的坐标系相似的坐标系,而GLM就是为了支持这一点而编写的。
更进一步,你可能想知道为什么眼睛坐标系统是这样定义的,相机向下指向负z轴。主要原因是这给了你一个右手坐标系。右手坐标系在许多应用中是相当标准的,在几何中也是如此。因此,大多数人更喜欢使用右手坐标系。
一旦你决定使用一个右手坐标系,很多事情就会迎刃而解。让x轴从左到右几乎是人们想要使用的任何坐标系的标准。y轴更加模糊,在一些图形系统/库中是从上到下,在另一些中是从下到上。在数学/几何中,y轴主要是从下向上绘制的,这就是OpenGL所使用的。
随着x轴从左到右,y轴从下到上,z轴必须指向屏幕上的,以便x/y/z形成右手坐标系。正z轴向屏幕外,当你看向屏幕时,你看向负z轴的方向。
有另一种方式来解释同样的事情:原生OpenGL坐标系统(NDC)是左手的。如果您想在右手坐标系中指定坐标,则必须在管道中的某个地方翻转手性。常见的方法是将坐标系翻转作为投影变换的一部分。这就是为什么在投影变换中,z坐标与x、y坐标的处理方式不同。反转z坐标将坐标系统从右手坐标系翻转为原生的左手OpenGL坐标系。
- 应用投影矩阵后对象消失
- 在其特征向量上投影点云
- 在 OpenGL 中使用透视与正交投影时的光线投射(鼠标拾取)
- 正交投影设置
- 使用 CGAL 将多面体投影到 xy 平面
- 将粒子投影到立方体的表面
- 缩小在正交投影中不起作用
- OpenGL在Ortho和特点问题之间切换
- 使用 GDAL/OGR C++将 GeoTiff 的 XY 点重新投影到纬度/经度
- OpenGL 透视投影裁剪多边形与顶点在视锥体之外 = 错误的纹理映射?
- OPENCV球形投影:翘曲和不折磨
- 3D透视图投影,带有摄像头旋转
- 将投影转换为正交光线投射
- GLSL:如何使用投影矩阵计算射线方向
- 了解 glm::ortho() 的参数如何影响投影后的顶点位置
- 从正交投影平滑过渡到透视投影
- 现代Opengl:同时正投影和透视投影
- OpenGL,具有正交投影的几何着色器
- 如何在不使用透明胶片的情况下创建Qt投影?(因为窗口管理器不支持)
- 为什么z坐标没有被glm::ortho()投影归一化