opengl - 使用 glOrtho 时相机无法看到对象

opengl - camera cannot see object when glOrtho is used

我是 OpenGL 的新手,我正在尝试了解投影矩阵在其中的工作原理。

为了创建一个简单的案例,我在世界中定义了一个三角形space,它的坐标是:

(0,1,0), (1,0,0), (-1,0,0)

我将模型视图矩阵和投影矩阵设置如下:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    0, 0, 2,
    0, 0, 0,
    0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // does not work
// glOrtho(-2, 2, -2, 2, 0.1, 2.0); // works

根据我的理解,gluLookAt()用于设置观察矩阵。由于OpenGL并没有"camera"的概念,所以将整个世界进行了变换,达到了相机的效果。在上面的代码中,我假设 "camera" 位于 (0,0,2),查看 (0,0,0)。所以 OpenGL 在内部沿 z 轴将三角形向后移动到 z=-2.

定义一个视锥体,glOrtho()得到6个参数。为了使三角形在视锥体中可见,我将 nearfar 值分别设置为 -0.1-2.0,这应该表明视锥体包括 [-0.1, -2.0]z 轴上。


我搜索了类似的问题,发现有人说glOrtho()的最后两个参数实际上是-near-far。但是如果这是正确的,下面的代码应该可以工作(但它不会):

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
    0, 0, -2, // changed 2 to -2, thus the triangle should be transformed to z=2?
    0, 0, 0,
    0, 1, 0);
glMatrixMode(GL_PROJECTION);
glOrtho(-2, 2, -2, 2, -0.1, -2.0); // -near=-0.1, -far=-2.0, thus the frustum should include [0.1, 2.0], thus include the triangle

如果我是对的,三角形应该画在屏幕上,所以我的代码一定有问题。有人可以帮忙吗?

首先请注意,固定功能管道矩阵堆栈和按 glBegin/glEnd 序列绘制已弃用 10 多年。 阅读 Fixed Function Pipeline and see Vertex Specification 了解最先进的渲染方式。


如果你使用这样的视图矩阵:

gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);

然后在设置投影矩阵时,近平面和远平面的值必须为正值,

glOrtho(-2, 2, -2, 2, 0.1, 2.0);

因为,gluLookAt 将顶点转换为视图 space(在视图 space 中,z 轴指向视口外),但是投影矩阵反转了 z 轴。

但是要小心,因为三角形在 z=0

(0,1,0), (1,0,0), (-1,0,0)

并且从相机到三角形的距离为2,因为视图矩阵,三角形正好位于远平面上(也是2.0)。我建议将到远平面的距离从 2.0 增加到(例如)3.0:

glOrtho(-2, 2, -2, 2, 0.1, 3.0);

如果改变视图矩阵,

gluLookAt(0, 0, -2, 0, 0, 0, 0, 1, 0);

然后 (view space) z 轴仍然指向视口外,但是您看的是三角形的 "back" 侧。三角形仍在视图的中心 (0, 0, 0),但相机位置已更改。三角形还在镜头前。

如果你愿意

gluLookAt(0, 0, 2, 0, 0, 4, 0, 1, 0);

那么你的视线就会从三角形上移开。您必须将视图的背面投影到视口 "see" 三角形 (glOrtho(-2, 2, -2, 2, -0.1, -3.0);)。


进一步注意,glOrtho 将当前矩阵乘以正交投影矩阵。这意味着您应该在使用 glOrtho 之前设置单位矩阵,就像您对模型视图矩阵所做的那样:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, 0.1, 2.0);

说明

投影、视图和模型矩阵一起交互以在视口上呈现场景的对象(网格)。 模型矩阵定义了场景世界space中单个对象(网格)的位置方向和比例。 视图矩阵定义了场景中观察者(观察者)的位置和观察方向。 投影矩阵定义了相对于投影到视口上的观察者(观察者)的区域(体积)。

在正交投影中,该区域(体积)由到观察者位置的 6 个距离(左、右、下、上、近、远)定义。

查看矩阵

视图坐标系描述了观察场景的方向和位置。视图矩阵从世界 space 转换为视图(眼睛)space。

如果视图space的坐标系是Right-handed系统,则X轴指向左侧,Y轴指向上方,Z轴指向视图外(请注意,在右手系统中,Z 轴是 X 轴和 Y 轴的叉积)。

投影矩阵

投影矩阵描述了从场景视图的 3D 点到视口上的 2D 点的映射。它从眼睛 space 变换到剪辑 space,并且剪辑 space 中的坐标通过除以剪辑坐标。 NDC 的范围为 (-1,-1,-1) 到 (1,1,1)。
超出剪辑 space 的每个几何图形都被剪辑。

在正交投影中,视图中的坐标 space 线性映射到剪辑 space 坐标,剪辑 space 坐标等于标准化设备坐标,因为 w分量为1(对于笛卡尔输入坐标)。
left、right、bottom、top、near 和 far 的值定义了一个框。盒子体积内的所有几何体在视口上都是 "visible"。

正交投影矩阵如下所示:

r = right, l = left, b = bottom, t = top, n = near, f = far 

2/(r-l)         0               0               0
0               2/(t-b)         0               0
0               0               -2/(f-n)        0
-(r+l)/(r-l)    -(t+b)/(t-b)    -(f+n)/(f-n)    1

z轴被投影矩阵反转。