在opengl中,为什么我们必须在gluLookAt之前进行透视?
所以在GL_的预测下我做到了在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]在所有三个维度中。要变换对象,大致需要执行以
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);