我是 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个参数。为了使三角形在视锥中可见,我将near
和far
的值分别设置为-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
如果我是正确的,则应该在屏幕上绘制三角形,因此我的代码一定有问题。有人可以帮忙吗?
答案 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轴的叉积。
投影矩阵
投影矩阵描述从场景中的视图的3D点到视口上的2D点的映射。它从眼睛空间转换为剪辑空间,并且通过除以剪辑坐标的w
分量,将剪辑空间中的坐标转换为归一化设备坐标(NDC)。 NDC的范围是(-1,-1,-1)到(1,1,1)。
裁剪出clippspace之外的每个几何。
在正交投影上,由于w
分量为1(对于笛卡尔输入坐标),视图空间中的坐标线性映射到剪辑空间坐标,并且剪辑空间坐标等于规范化的设备坐标。
左,右,下,上,近和远的值定义一个框。盒子体积内的所有几何图形在视口上都是“可见的”。
正交投影矩阵如下:
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轴被投影矩阵反转。