要在屏幕上看到一个对象,您需要它落在标准视图体积内,对于 OpenGL,在所有三个维度上都为 [−1, 1]。要转换一个对象,你大致做
P' = 投影 × 视图 × 模型 × P
其中P' 是需要在规范视图体积中的最终点,P 是模型空间中的初始点。 P由模型矩阵变换,然后是视图,然后是投影。
我遵循的顺序是基于列向量的,其中每个进一步的变换都是预/左乘。读取相同公式的另一种方法是从左到右读取它,而不是转换点,而是转换坐标系并在转换后的系统中解释 P 在空间上表示原始系统中的 P'。这只是另一种看待它的方式,两者的结果是相同的;在数字和空间上。
为什么我们必须在 gluLookAt 之前执行 gluPerspective?
较旧的固定功能管道OpenGL 后/右乘,因此需要颠倒顺序以获得相同的效果。因此,当我们首先需要 LookAt 并且接下来需要 Perspective 时,我们执行相反的操作以获得预期的结果。
以正确的顺序给出这两个会导致
P' = 视图 × 投影 × 模型 × P
由于矩阵乘法是反交换的,所以您不会得到正确的P',它属于规范视图体积,因此会出现黑屏。
参见Chapter 3, Red Book,在通用转换命令部分下,它解释了 OpenGL 遵循的顺序。摘录:
注意:所有与OpenGL的矩阵乘法都发生如下:假设当前矩阵是C并且用glMultMatrix*()指定的矩阵或任何转换命令是M。乘法后,最终的矩阵总是CM。由于矩阵乘法通常不是可交换的,因此顺序会有所不同。
我想知道为什么第一个案例有效,而第二个无效。
要了解由错误顺序形成的矩阵究竟会发生什么,让我们在 2D 中做一个小练习。假设规范视图 region 在 X 和 Y 中都是 [−100, 100] ;这之外的任何东西都被剪掉了。这个假想的方形屏幕的原点在中心,X 向右,Y 向上。当没有应用转换时,调用DrawImage 在原点绘制图像。你有一个 1 × 1 的图像;它的模型矩阵按200 缩放,使其成为200 × 200 图像;一个填满整个屏幕的。由于原点位于屏幕的中心,要绘制图像以使其充满屏幕,我们需要一个将图像平移(移动)(-100,-100)的视图矩阵。制定这个
P' = 视图 × 模型 = 平移-100, -100 × 比例200, 200
[ 200, 0, −100 ]
[ 0, 200, −100 ]
[ 0, 0, 1 ]
然而,
的结果
模型 × 视图 = S200, 200 × T-100, -100
[ 200, 0, −20000 ]
[ 0, 200, −20000 ]
[ 0, 0, 1 ]
将前一个矩阵与点 (0, 0) 和 (1, 1) 相乘将得到预期的 (-100, -100) 和 (100, 100)。图像角将与屏幕角对齐。但是,将后一个矩阵与它们相乘会得到 (-20000, -20000) 和 (-19800, -19800);远在可视区域之外。这是因为在几何上,后一个矩阵首先平移然后缩放,而不是缩放然后平移。转换后的比例会导致一个完全偏离的点。