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

时间:2018-07-04 15:08:02

标签: c++ opengl coordinate-transformation orthographic

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

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

  

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

我将modelview矩阵和投影矩阵设置如下:

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个参数。为了使三角形在视锥中可见,我将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

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

1 个答案:

答案 0 :(得分:1)

首先要注意的是,固定功能流水线矩阵堆栈和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个距离(左,右,下,上,近和远)定义。

查看矩阵

视图坐标系描述了从中查看场景的方向和位置。视图矩阵从世界空间转换为视图(眼睛)空间。

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

enter image description here

投影矩阵

投影矩阵描述从场景中的视图的3D点到视口上的2D点的映射。它从眼睛空间转换为剪辑空间,并且通过除以剪辑坐标的w分量,将剪辑空间中的坐标转换为归一化设备坐标(NDC)。 NDC的范围是(-1,-1,-1)到(1,1,1)。
裁剪出clippspace之外的每个几何。

在正交投影上,由于w分量为1(对于笛卡尔输入坐标),视图空间中的坐标线性映射到剪辑空间坐标,并且剪辑空间坐标等于规范化的设备坐标。
左,右,下,上,近和远的值定义一个框。盒子体积内的所有几何图形在视口上都是“可见的”。

enter image description here

正交投影矩阵如下:

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