GLSL:ModelView * Projection或Projection * ModelView

时间:2011-11-11 10:21:47

标签: opengl-es glsl linear-algebra

我正在查看Apple的一些iOS示例代码,它展示了GLES2的功能,我看到他们这样做了:

mat4f_MultiplyMat4f(proj, modelview, modelviewProj);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_PROJECTION_MATRIX], 1, GL_FALSE, modelviewProj);

根据mat4f_MultiplyMat4f函数的定义,它们看起来像是将模型视图矩阵预先乘以投影矩阵并将结果存储到modelviewProj中。虽然我还很新,但这对我来说并不合适;不应该是mvp = mv * p,而不是mvp = p * mv就像他们在做什么?

这是他们的mat4f_MultiplyMat4f函数粘贴以验证:

void mat4f_MultiplyMat4f(const float* a, const float* b, float* mout)
{
    mout[0]  = a[0] * b[0]  + a[4] * b[1]  + a[8] * b[2]   + a[12] * b[3];
    mout[1]  = a[1] * b[0]  + a[5] * b[1]  + a[9] * b[2]   + a[13] * b[3];
    mout[2]  = a[2] * b[0]  + a[6] * b[1]  + a[10] * b[2]  + a[14] * b[3];
    mout[3]  = a[3] * b[0]  + a[7] * b[1]  + a[11] * b[2]  + a[15] * b[3];

    mout[4]  = a[0] * b[4]  + a[4] * b[5]  + a[8] * b[6]   + a[12] * b[7];
    mout[5]  = a[1] * b[4]  + a[5] * b[5]  + a[9] * b[6]   + a[13] * b[7];
    mout[6]  = a[2] * b[4]  + a[6] * b[5]  + a[10] * b[6]  + a[14] * b[7];
    mout[7]  = a[3] * b[4]  + a[7] * b[5]  + a[11] * b[6]  + a[15] * b[7];

    mout[8]  = a[0] * b[8]  + a[4] * b[9]  + a[8] * b[10]  + a[12] * b[11];
    mout[9]  = a[1] * b[8]  + a[5] * b[9]  + a[9] * b[10]  + a[13] * b[11];
    mout[10] = a[2] * b[8]  + a[6] * b[9]  + a[10] * b[10] + a[14] * b[11];
    mout[11] = a[3] * b[8]  + a[7] * b[9]  + a[11] * b[10] + a[15] * b[11];

    mout[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14]  + a[12] * b[15];
    mout[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14]  + a[13] * b[15];
    mout[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
    mout[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
}

我猜这是一个错误,但我不知道。不执行Proj * Modelview * Vert首先应用投影矩阵,然后在模型视图之上?根据投影的纵横比,这会不会产生奇怪的结果,比如翻译在某些方向上移动的东西比它们应该更多?不是你想要的Modelview * Proj * Vert,并不是因为它被称为MVP矩阵而不是PMV矩阵吗?难道只是这个简单的小旋转方格,苹果样本代码所描绘的并不复杂,足以让错误曝光吗?

1 个答案:

答案 0 :(得分:5)

矩阵乘法是右关联的,即表达式从右到左评估。所以正确的乘法确实是

MVP = P * MV

通过记住要将列向量与矩阵相乘,可以很容易地推导出这一点,从而产生另一个列向量。根据矩阵乘法的定义

v'_j = \sum_i M_ij * v_i

或短

v' = M * v

您可以将整个转换重写为

v_eye = MV * v

v_clip = P * v_eye

代替v_eye

v_clip = P * (MV * v) = P * MV * v