GLSL: ModelView * Проекция или Проекция * ModelView - PullRequest
2 голосов
/ 11 ноября 2011

Я смотрю на пример кода iOS от Apple, который демонстрирует функциональность 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? Может ли быть так, что этот простой маленький вращающийся квадрат, который рисует пример кода Apple, не настолько сложен, чтобы ошибка появилась на свет?

1 Ответ

5 голосов
/ 11 ноября 2011

Матричное умножение ассоциативно справа, т. Е. Выражение вычисляется справа налево.Таким образом, правильное умножение действительно

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
...