Wat*_*ter 4 c++ opengl rendering orthographic glm-math
在搜索了许多页面、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);
Run Code Online (Sandbox Code Playgroud)
(请注意,仅仅因为我使用了变量名称m, v,p并不意味着它们实际上是该名称的正确转换,以上只是我想要的)
我对以下内容感到困惑:
正交边界在哪里?我假设它指向负 z 轴,但是左/右边界在哪里?这是否意味着 x 轴上的 [-400, 400] 映射到 [-1.0, 1.0] NDC,或者 [0, 800] 映射到它?(我假设这里的任何答案都适用于 y 轴)。然后文档只是说Creates a matrix for an orthographic parallel viewing volume.
如果你翻转下面的第三个和第四个参数会发生什么(我问是因为我看到人们这样做,我不知道这是一个错误/错字还是侥幸……或者它是否正常工作):
这里的参数三和四:
_____________
| 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);
Run Code Online (Sandbox Code Playgroud)
这个例子中提供的代码(减去变量名)是我唯一使用的东西,渲染工作得很好......只是我缺乏关于它为什么工作的知识,我不满意。
编辑:试图通过使用网站上的图像和描述作为参考的单个示例从这里理解它。我可能没有抓住重点。
EDIT2:作为一个随机问题,由于我总是在 z = 1.0 处绘制我的平面,我是否应该出于任何原因将我的正投影近/远平面限制为尽可能接近 1.0(例如:0.99、1.01)?假设没有绘制或将绘制任何其他内容。
您可以假设正交投影中的可见区域是在视图空间中给定的立方体。然后将该立方体映射到 NDC 坐标中的 [-1,1] 立方体,这样立方体内部的所有内容都是可见的,而外部的所有内容都将被剪掉。通常,观察者沿负 Z 轴看,而 +x 是右,+Y 是上。
正交边界如何映射到 NDC 空间?
立方体的边长由传递给 的参数给出glOrtho。在第一个示例中,left 和 right 的参数是 [0, 800],因此沿 X 轴从 0 到 800 的空间映射到沿 NDC X 轴的 [-1, 1]。类似的逻辑沿其他两个轴发生(沿 y 的顶部/底部,沿 -z 的近/远)。
当顶部和底部参数交换时会发生什么?
例如,上下互换相当于沿此轴镜像场景。如果查看正交矩阵的第二个对角线元素,则将其定义为2 / (top - bottom)。通过交换顶部和底部,仅此元素的符号会发生变化。这同样适用于交换左与右或近与远。有时当屏幕空间原点应该在左下角而不是左上角时使用。
为什么你必须将四边形旋转 180° 并镜像它?
如上所述,near 和 far 值沿负Z 轴。[0.5, 1.5] 沿 -Z 的值在世界空间坐标中表示 [-0.5, -1.5]。由于平面定义为 z=1.0,因此它在可见区域之外。通过将其绕原点旋转 180 度,将其移动到 z=-1.0,但现在您是从背面看它,这意味着背面剔除发生了。通过沿 X 镜像它,绕组顺序发生变化,从而改变了背面和正面。
由于我总是在 Z = 1.0 处绘制我的平面,我是否应该将我的正投影近/远平面限制为尽可能接近 1.0?
只要你不画别的东西,你基本上可以选择你想要的任何东西。当绘制多个对象时,near 和 far 之间的范围定义了可以存储深度差异的精确程度。