简体   繁体   English

QMatrix4x4模型视图投影OpenGL无法获得要渲染的场景

[英]QMatrix4x4 Model View Projection OpenGL Can't Get Scene to Render

Given this vertex shader: 鉴于此顶点着色器:

attribute vec3 vertex;
uniform mat4 mvp;

void main() {
    gl_Position = mvp * vec4(vertex, 1.0);
}

And this fragment shader: 这个片段着色器:

void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Which is able to render the data below, when the mvp matrix is the identity or if the model matrix is a scale, rotate, or tranlate transform: mvp矩阵为单位或模型矩阵为缩放,旋转或平移变换时,可以渲染以下数据:

GLfloat values[] = {
    -1.0, -1.0, +0.0,
    +1.0, -1.0, +0.0,
    +0.0, +1.0, +0.0,
};

Why does the following usage of Qt's QMatrix4x4::lookAt and QMatrix4x4::perspective cause the scene to be rendered as if no object is there? 为什么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);

What I am looking for is not only how to fix the code but by which means I can attempt to debug these things in the future. 我寻找的不仅是如何修复代码,而且还希望通过这种方式将来可以调试这些东西。


Just on a hunch I changed mvp to p * v * m and it fixed the issue. 只是预感,我将mvp更改为p * v * m并解决了该问题。 Why is it mvp if you have to do the multiplication in the opposite order? 如果必须以相反的顺序进行乘法运算,为什么它是mvp? I know matrix multiplication is not transitive. 我知道矩阵乘法不是可传递的。 That is if A and B are matrices, A * B != B * A if A and B are not I. 也就是说,如果A和B是矩阵,则A * B!= B * A如果A和B不是I。

It's called MVP because... somebody named it that way. 之所以称为MVP,是因为……有人这样称呼它。 ;) ;)

It makes some sense, though. 不过,这是有道理的。 It basically lists the transformations in the order they are applied. 它基本上按转换顺序列出了它们的应用顺序。 You first apply the Model matrix to your vertices, then the View matrix to the result of that, then the projection matrix to the result of both. 首先,将模型矩阵应用于顶点,然后将视图矩阵应用于顶点,然后将投影矩阵应用于两者。

Or mathematically, for an input vertex vObj , you could write: 或者在数学上,对于输入顶点vObj ,您可以编写:

vWorld = M * vObj
vEye = V * vWorld
vClip = P * vEye

If you substitute the equations, you get: 如果替换方程式,则会得到:

vClip = P * vEye = P * (V * vWorld) = P * (V * (M * vObj))

Matrix multiplications are associative, so this can be rewritten as: 矩阵乘法是关联的,因此可以重写为:

P * (V * (M * vObj)) = (P * V * M) * vObj

Therefore, the combined matrix is calculated as P * V * M . 因此,组合矩阵计算为P * V * M

Reto Koradi is right. Reto Koradi是正确的。 And it's not because of memory layout or something, it's because OpenGL uses column vectors - matrix with four rows and one column or 4x1 matrix. 这不是因为内存布局或其他原因,而是因为OpenGL使用列向量-具有四行和一列的矩阵或4x1矩阵。 Transformations are Matrix4x4 * Vector to meet criteria for matrix multiplications (result is column vector again). 转换为Matrix4x4 *向量,以满足矩阵乘法的标准(结果再次为列向量)。

Another approach is to define vector as row (1x4 matrix) and then all transformations are vWorld = vObj * M etc to meet criteria for matrix multiplication resulting in row vector. 另一种方法是将向量定义为行(1x4矩阵),然后所有转换为vWorld = vObj * M等,以满足矩阵乘法的标准,从而得出行向量。 Out of sudden, last row is rewritten as vClip = vObj * M * V * P . 突然,最后一行被重写为vClip = vObj * M * V * P

Matrix multiplication is always the same, you should not need to care how matrices are stored in the memory (well, unless it's linear array and you need to address element at row/column), but transform matrices are different depending on definition of vector. 矩阵乘法始终是相同的,您不必关心矩阵在内存中的存储方式(好吧,除非它是线性数组,并且您需要在行/列中寻址元素),但是根据向量的定义,变换矩阵是不同的。

In OpenGL always compose transforms from right to left. 在OpenGL中,总是从右到左组成变换。 Remember that left-most matrix is applied last. 请记住,最左边的矩阵最后应用。

For some reason (history?), vectors are usually considered column vectors and transform matrices are applied from right to left, but as noted in the comment below, it's possible to use both approaches in GL Shading Language (GLSL). 出于某种原因(历史?),通常将向量视为列向量,并从右向左应用变换矩阵,但是正如下面的注释所指出的,可以在GL Shading Language(GLSL)中使用这两种方法。

It's to do with the dimensionality of matrices and mathematical notation. 这与矩阵的维数和数学符号有关。 The dimensions of a matrix are defined as rows x columns. 矩阵的尺寸定义为行x列。 So a 1x3 matrix is M = [abc]. 因此1x3矩阵为M = [abc]。 Then a 4x4 matrix is as expected. 然后是一个4x4矩阵,如预期的那样。

Multiplying two matrices of dimension AxB and CxD can only be done if B=C (row into column and sum the result). 仅当B = C(排入列并将结果求和)时,才能将维AxB和CxD的两个矩阵相乘。

A list of N vertices with XYZW coordinates can be defined as a matrix Nx4 or 4xN in size, but only 4xN works with the definition of the multiplication operator if the block of vertices come after the matrix: 可以将具有XYZW坐标的N个顶点的列表定义为大小为Nx4或4xN的矩阵,但是如果顶点的块位于矩阵之后,则只有4xN可以与乘法运算符一起使用:

V' (4xN) = M (4x4) x V (4xN) V'(4xN)= M(4x4)x V(4xN)

So vertices are considered as column vectors to make this notation work. 因此,顶点被视为使此符号起作用的列向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM