了解 glm::ortho() 的参数如何影响投影后的顶点位置

Understanding how glm::ortho()'s arguments affect vertex location after projection

在搜索了很多页面、glm 文档、教程等之后,我仍然对某些事情感到困惑。

我试图理解为什么我需要应用以下转换来让我的 800x600(全屏正方形,对于这个最小示例,假设用户的屏幕是 800x600)图像来绘制所有内容。假设我只画逆时针三角形。在我的代码中一切都很好,但我必须执行以下操作:

// Vertex data (x/y/z), using EBOs
  0.0f, 600.0f, 1.0f,
800.0f,   0.0f, 1.0f,
  0.0f,   0.0f, 1.0f,
800.0f, 600.0f, 1.0f

// Later on...
glm::mat4 m, v, p;
m = scale(m, glm::vec3(-1.0, 1.0, 1.0));
v = rotate(v, glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
p = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, 0.5f, 1.5f);

(请注意,仅仅因为我使用了变量名称 mvp 并不意味着它们实际上是该名称的正确转换,上面只是做我想做的事)

我对以下内容感到困惑:

这里是参数三和参数四:

                              _____________
                             |  These two  |
p1 = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, 0.5f, 1.5f);
p2 = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.5f, 1.5f);

此示例中提供的代码(减去变量名称)是我唯一使用的东西,而且渲染效果非常好...只是我不了解它为什么起作用,这让我很不满意。

编辑:试图通过使用网站上的图像和描述作为参考示例从 here 中理解它。我可能错过了重点。

EDIT2:作为一个随机问题,因为我总是在 z = 1.0 处绘制我的平面,我是否应该限制我的正交投影 near/far 平面尽可能接近 1.0(例如:0.99、1.01)出于什么原因?假设没有绘制或将绘制任何其他内容。

您可以假设正射投影中的可见区域是视图中给定的立方体 space。然后将这个立方体映射到 NDC 坐标中的 [-1,1] 立方体,这样立方体内部的所有内容都是可见的,外部的所有内容都将被剪掉。一般情况下,观看者的视线方向为负Z-axis,而+x为右,+Y为上。

如何将正字法边界映射到 NDC space?

立方体的边长由传递给 glOrtho 的参数给出。在第一个示例中,左右参数为 [0, 800],因此沿 X 轴从 0 到 800 的 space 映射到沿 NDC X 轴的 [-1, 1]。类似的逻辑发生在其他两个轴上(top/bottom 沿 y,near/far 沿 -z)。

交换top和bottom参数会发生什么?

互换,例如top和bottom,相当于沿着这个轴镜像场景。如果您查看 orthographic matrix 的第二个对角线元素,它被定义为 2 / (top - bottom)。通过交换顶部和底部,只有这个元素的符号会改变。这同样适用于交换左与右或近与远。有时当 screen-space 原点应该是左下角而不是左上角时使用。

为什么要把四边形旋转180°镜像呢?

如上所述,近值和远值沿 负值 Z-axis。 [0.5, 1.5] 沿 -Z 的值表示世界 space 坐标中的 [-0.5, -1.5]。由于平面定义为 z=1.0,因此它位于可见区域之外。通过将它围绕原点旋转 180 度,将它移动到 z=-1.0,但现在你从后面看它,这意味着 back-face 剔除罢工。通过沿 X 镜像它,缠绕顺序发生变化,因此背面和正面发生变化。

因为我总是在 Z = 1.0 绘制平面,我是否应该限制我的正投影 near/far 平面尽可能接近 1.0?

只要不画别的,基本可以随便选。当绘制多个对象时,远近之间的范围定义了深度差异的存储精度。