在opengl中,为什么我们必须在gluLookAt之前进行透视?

在opengl中,为什么我们必须在gluLookAt之前进行透视?,opengl,graphics,3d,matrix-multiplication,perspectivecamera,Opengl,Graphics,3d,Matrix Multiplication,Perspectivecamera,所以在GL_的预测下我做到了 glu.gluPerspective(90,aspect,1,10); glu.gluLookAt(0,0,3,0,0,0,0,1,0); 这很好,但当我切换顺序时,我的屏幕上没有任何对象,我旋转了我的相机,什么都没有 我知道切换这两种情况会改变矩阵乘法的顺序,但我想知道为什么第一种情况有效,而第二种情况无效。感谢要在屏幕上看到一个对象,您需要它位于规范化视图体积内,也就是说,对于OpenGL[−1,1]在所有三个维度中。要变换对象,大致需要执行以

所以在GL_的预测下我做到了

    glu.gluPerspective(90,aspect,1,10);
    glu.gluLookAt(0,0,3,0,0,0,0,1,0);
这很好,但当我切换顺序时,我的屏幕上没有任何对象,我旋转了我的相机,什么都没有


我知道切换这两种情况会改变矩阵乘法的顺序,但我想知道为什么第一种情况有效,而第二种情况无效。感谢

要在屏幕上看到一个对象,您需要它位于规范化视图体积内,也就是说,对于OpenGL[−1,1]在所有三个维度中。要变换对象,大致需要执行以下操作:

p'=投影×视图×模型×p

其中,
p'
是需要位于规范视图体积中的最终点,p是模型空间中的初始点。P由模型矩阵、视图和投影进行变换

我遵循的顺序是基于列向量的,其中每个进一步的变换都是预/左乘法的。读取相同公式的另一种方法是从左到右读取,其中坐标系不是变换点,而是变换,并解释变换系统中的
P
在空间上表示原始系统中的
P'
。这只是另一种看法,两者的结果是一样的;在数量上和空间上

为什么我们必须先做透视,然后再看

旧的、固定的函数管道OpenGL post/right相乘,因此需要颠倒顺序才能获得相同的效果。因此,当我们需要先看,然后透视时,我们会做相反的操作以获得预期的结果

将两者按正确的顺序排列会导致

p'=视图×投影×模型×p

因为矩阵乘法是反交换的,所以不能得到正确的
p'
,它属于规范视图卷,因此会出现黑屏

请参阅“通用转换命令”一节下的,该节解释了OpenGL遵循的顺序。摘录:

注意:使用OpenGL进行的所有矩阵乘法如下:假设当前矩阵为C,并且使用glMultMatrix*()或任何转换命令指定的矩阵为M。相乘后,最终矩阵总是CM。因为矩阵乘法通常不是可交换的,所以顺序会有所不同


我想知道为什么第一种情况有效,而第二种情况无效

为了了解错误顺序形成的矩阵的实际情况,让我们在2D中做一个小练习。假设规范视图区域是[−100,100]在X和Y中;除此之外的任何内容都将被删除。这个假想的正方形屏幕的原点在中心,X向右,Y向上。当未应用任何变换时,调用
DrawImage
在原点绘制图像。你有一个1×1的图像;其模型矩阵按
200
进行缩放,使其成为
200×200
图像;填满整个屏幕的一个。因为原点位于屏幕的中心,所以要绘制图像,使其充满屏幕,我们需要一个视图矩阵,该矩阵可以通过(−100, −100). 制定这个

p'=视图×模型=平移−100, −100×刻度200200

但是,

型号×视图=S200,200×T−100, −一百

将前一个矩阵与点(0,0)和(1,1)相乘将导致(−100, −100)和(100100)如预期。图像角将与屏幕角对齐。但是,将后一个矩阵与它们相乘将导致(−20000, −20000)和(−19800, −19800); 远离可视区域。这是因为,在几何上,后一个矩阵先平移然后缩放,而不是先缩放然后平移。转换后的刻度指向一个完全关闭的点。

中的

glu.gluPerspective(90,aspect,1,10);
glu.gluLookAt(0,0,3,0,0,0,0,1,0);
在这种情况下,第一个模型/世界坐标(在R^3中)将转换为视图坐标(也是R^3)。然后投影将视图坐标映射到透视空间(P^4),然后通过透视分割将透视空间缩小为NDC坐标。这通常是它应该如何工作的

现在看一下:

glu.gluLookAt(0,0,3,0,0,0,0,1,0);
glu.gluPerspective(90,aspect,1,10);
这里,世界坐标直接投影到射影空间(p^4)。因为lookAt矩阵是从R^3->R^3的映射,我们已经在P^4中了,所以这是行不通的。即使可以旋转P^4,gluLookAt的参数也必须调整以适应投影空间的范围


注:一般情况下,不应将gluLookAt添加到GL_投影堆栈中。由于它描述了视图矩阵,因此更适合于GL_MODELVIEW堆栈。仅供参考。

旁白:
GL\u投影
应仅具有投影变换,模型和视图变换应位于
GL\u模型视图
中。尽管它会起作用,但这是正确的做法,是一个需要遵守的惯例。@legends2k说的。此外,将观看变换放入GL_投影会在灯光进入场景时立即导致问题。感谢您的回复,我理解更改顺序会更改矩阵乘法的顺序。有没有可能详细解释一下为什么它不属于规范视图?(我知道PVM是正确的顺序,更改顺序会产生错误的矩阵,但这个错误的矩阵意味着什么?)。
glu.gluPerspective(90,aspect,1,10);
glu.gluLookAt(0,0,3,0,0,0,0,1,0);
glu.gluLookAt(0,0,3,0,0,0,0,1,0);
glu.gluPerspective(90,aspect,1,10);