首页 > 解决方案 > opengl - 使用 glOrtho 时相机看不到物体

问题描述

我是OpenGL的新手,我试图了解投影矩阵是如何在其中工作的。

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

(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没有“照相机”的概念,因此它改造了整个世界,达到了照相机的效果。在上面的代码中,我假设“相机”在 (0,0,2),看着 (0,0,0)。因此OpenGL在内部将三角形沿z轴向后移动到z=-2.

要定义视锥,请glOrtho()获取 6 个参数。为了使三角形在截锥体中可见,我设置了nearandfar值分别设置为-0.1and-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

如果我是正确的,应该在屏幕上绘制三角形,所以我的代码一定有问题。任何人都可以帮忙吗?

标签: c++openglcoordinate-transformationorthographic

解决方案


首先请注意,固定函数管道矩阵堆栈和按glBegin/glEnd序列绘图已被弃用超过 10 年。阅读Fixed Function Pipeline并查看Vertex Specification了解最先进的渲染方式。


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

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

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

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

因为,gluLookAt将顶点转换到视图空间(在视图空间中,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);

然后(视图空间)z 轴仍然指向视口之外,但您会看到三角形的“后”侧。三角形仍位于视图的中心 (0, 0, 0),但相机位置已更改。三角形仍然在镜头前。

如果你愿意

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

然后你会远离三角形。您必须将视图的背面投影到视口才能“看到”三角形 ( glOrtho(-2, 2, -2, 2, -0.1, -3.0);)。


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

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

解释

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

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

查看矩阵

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

如果视图空间的坐标系是右手系,那么 X 轴指向左侧,Y 轴向上,Z 轴在视野外(注意右手系中的 Z 轴是 X 轴和 Y 轴的叉积)。

在此处输入图像描述

投影矩阵

投影矩阵描述了从场景上的 3D 点到视口上的 2D 点的映射。它从眼睛空间变换到剪辑空间,剪辑空间中的坐标通过除以w剪辑坐标的分量被变换为归一化设备坐标(NDC)。NDC 在 (-1,-1,-1) 到 (1,1,1) 范围内。
每个超出裁剪空间的几何图形都被裁剪。

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

在此处输入图像描述

正交投影矩阵如下所示:

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 轴被投影矩阵反转。


推荐阅读