[英]QMatrix4x4 Model View Projection OpenGL Can't Get Scene to Render
鉴于此顶点着色器:
attribute vec3 vertex;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(vertex, 1.0);
}
这个片段着色器:
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
当mvp
矩阵为单位或模型矩阵为缩放,旋转或平移变换时,可以渲染以下数据:
GLfloat values[] = {
-1.0, -1.0, +0.0,
+1.0, -1.0, +0.0,
+0.0, +1.0, +0.0,
};
为什么Qt的QMatrix4x4::lookAt
和QMatrix4x4::perspective
的以下用法导致场景呈现为好像没有对象存在?
QMatrix4x4 model;
QMatrix4x4 view;
view.lookAt(
QVector3D(0.0, 0.0, 10.0), // Eye
QVector3D(0.0, 0.0, 0.0), // Focal Point
QVector3D(0.0, 1.0, 0.0)); // Up vector
QMatrix4x4 proj;
// Window size is fixed at 800.0 by 600.0
proj.perspective(45.0, 800.0 / 600.0, 1.0, 100.0);
QMatrix4x4 mvp = (model * view * proj);
我寻找的不仅是如何修复代码,而且还希望通过这种方式将来可以调试这些东西。
只是预感,我将mvp更改为p * v * m并解决了该问题。 如果必须以相反的顺序进行乘法运算,为什么它是mvp? 我知道矩阵乘法不是可传递的。 也就是说,如果A和B是矩阵,则A * B!= B * A如果A和B不是I。
之所以称为MVP,是因为……有人这样称呼它。 ;)
不过,这是有道理的。 它基本上按转换顺序列出了它们的应用顺序。 首先,将模型矩阵应用于顶点,然后将视图矩阵应用于顶点,然后将投影矩阵应用于两者。
或者在数学上,对于输入顶点vObj
,您可以编写:
vWorld = M * vObj
vEye = V * vWorld
vClip = P * vEye
如果替换方程式,则会得到:
vClip = P * vEye = P * (V * vWorld) = P * (V * (M * vObj))
矩阵乘法是关联的,因此可以重写为:
P * (V * (M * vObj)) = (P * V * M) * vObj
因此,组合矩阵计算为P * V * M
Reto Koradi是正确的。 这不是因为内存布局或其他原因,而是因为OpenGL使用列向量-具有四行和一列的矩阵或4x1矩阵。 转换为Matrix4x4 *向量,以满足矩阵乘法的标准(结果再次为列向量)。
另一种方法是将向量定义为行(1x4矩阵),然后所有转换为vWorld = vObj * M
等,以满足矩阵乘法的标准,从而得出行向量。 突然,最后一行被重写为vClip = vObj * M * V * P
矩阵乘法始终是相同的,您不必关心矩阵在内存中的存储方式(好吧,除非它是线性数组,并且您需要在行/列中寻址元素),但是根据向量的定义,变换矩阵是不同的。
在OpenGL中,总是从右到左组成变换。 请记住,最左边的矩阵最后应用。
出于某种原因(历史?),通常将向量视为列向量,并从右向左应用变换矩阵,但是正如下面的注释所指出的,可以在GL Shading Language(GLSL)中使用这两种方法。
这与矩阵的维数和数学符号有关。 矩阵的尺寸定义为行x列。 因此1x3矩阵为M = [abc]。 然后是一个4x4矩阵,如预期的那样。
仅当B = C(排入列并将结果求和)时,才能将维AxB和CxD的两个矩阵相乘。
可以将具有XYZW坐标的N个顶点的列表定义为大小为Nx4或4xN的矩阵,但是如果顶点的块位于矩阵之后,则只有4xN可以与乘法运算符一起使用:
V'(4xN)= M(4x4)x V(4xN)
因此,顶点被视为使此符号起作用的列向量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.