QMatrix4x4模型视图投影OpenGL无法获取场景渲染

时间:2015-03-07 17:07:51

标签: c++ qt opengl

鉴于此顶点着色器:

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::lookAtQMatrix4x4::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不是I,则A * B!= B * A.

3 个答案:

答案 0 :(得分:5)

它被称为MVP,因为......有人以这种方式命名。 ;)

但是,这是有道理的。它基本上按照它们应用的顺序列出转换。首先将模型矩阵应用于顶点,然后将View矩阵应用于其结果,然后将投影矩阵应用于两者的结果。

或者在数学上,对于输入顶点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

答案 1 :(得分:1)

Reto Koradi是对的。这不是因为内存布局或其他原因,而是因为OpenGL使用列向量 - 具有四行和一列或4x1矩阵的矩阵。转换是Matrix4x4 * Vector,以满足矩阵乘法的标准(结果再次是列向量)。

另一种方法是将向量定义为行(1x4矩阵),然后所有变换都是vWorld = vObj * M等,以满足矩阵乘法的标准,从而得到行向量。突然之间,最后一行被重写为vClip = vObj * M * V * P

矩阵乘法总是相同的,你不需要关心矩阵如何存储在内存中(好吧,除非它是线性数组,你需要在行/列处寻址元素),但是变换矩阵根据定义而有所不同矢量。

在OpenGL中,总是从右到左组成变换。请记住,最左边的矩阵最后应用。

由于某种原因(历史记录?),向量通常被认为是列向量,变换矩阵从右到左应用,但如下面的注释中所述,可以在GL着色语言(GLSL)中使用这两种方法。 / p>

答案 2 :(得分:0)

它与矩阵的维数和数学符号有关。矩阵的尺寸定义为行x列。所以1x3矩阵是M = [a b c]。然后4x4矩阵如预期的那样。

只有当B = C(行到列并对结果求和)时,才能将两个维度AxB和CxD的矩阵相乘。

具有XYZW坐标的N个顶点的列表可以定义为矩阵Nx4或4xN的大小,但如果顶点块位于矩阵之后,则只有4xN与乘法运算符的定义一起使用:

V' (4×N)= M(4×4)×V(4×N)

因此顶点被视为列向量,以使此表示法有效。