умножение матрицы на вектор в glsl

#webgl

#webgl

Вопрос:

Ссылка http://webglfundamentals.org/webgl/lessons/webgl-3d-orthographic.html В векторном шейдере происходит умножение mat4 и vec4 .

 attribute vec4 a_position;

uniform mat4 u_matrix;

void main() {

  // Multiply the position by the matrix.

  gl_Position = u_matrix * a_position;

}
  

Как возможно умножить матрицу 4 * 4 на матрицу 1 * 4?
Не должно ли это быть gl_Position = a_position * u_matrix;

Кто-нибудь может это объяснить?

Комментарии:

1. Я в замешательстве, потому что это обратная сторона математического формализма. Невозможно умножить на векторную строку с правой стороны. Таким образом, v * m считается более соответствующим алгебраическому соглашению, нет?

Ответ №1:

Из спецификации GLSL 1.017

5.11 Векторные и матричные операции

За несколькими исключениями, операции выполняются по компонентам. Когда оператор работает с вектором или матрицей, он работает независимо над каждым компонентом вектора или матрицы, в зависимости от компонентов.

…матрица, умноженная на вектор, вектор, умноженный на матрицу, и матрица, умноженная на матрицу. Они не работают по компонентам, а скорее выполняют правильное линейное алгебраическое умножение. Они требуют, чтобы размер операндов совпадал.

 vec3 v, u;
mat3 m;

u = v * m;
  

эквивалентно

 u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
  

И

 u = m * v;
  

эквивалентно

 u.x = m[0].x * v.x   m[1].x * v.y   m[2].x * v.z;
u.y = m[0].y * v.x   m[1].y * v.y   m[2].y * v.z;
u.z = m[0].z * v.x   m[1].z * v.y   m[2].z * v.z;
  

или также

 u = v.x * m[0]   v.y * m[1]   v.z * m[2];
  

Ответ №2:

http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf
https://en.wikibooks.org/wiki/GLSL_Programming/Vector_and_Matrix_Operations#Operators

Предположим, что матрица 3×3:

 m_of_math = 
    m11, m12, m13
    m21, m22, m23
    m31, m32, m33
  

а вектор — это вектор столбца:

 v = [x
     y
     z]
  

glsl хранит матрицу как основной столбец, поэтому инициализирует как:

 mat3 m = mat3(m11, m21, m31, 
              m12, m22, m32,
              m13, m23, m33)
  

доступ в виде столбца:

 m[0] = (m11, m21, m31)
       //first column of matrix
       //first row of stored memory
  

при выполнении операций забудьте порядок сохранения,
например:

m * v:

 m * v => matrix of math * vector
  

v * m:

 v * m => v^T * m = (M^T * v)^T
      => transpose of matrix of math * vector
  

m1 * m2:

 m1 * m2 = matrix 1 of math * matrix 2 of math