Multiplying Matrices

In which you learn how to consolidate multiple transformation matrices into a single matrix.

The benefit of matrices is realized when you consolidate a long sequence of them into a single matrix. The matrices are consolidated by multiplying them together. How exactly do you multiply two rectangular grids of numbers?

GLSL has a native matrix type in mat4, and the * operator is overloaded to support matrix multiplication:

mat4 chain = scaleMatrix * rotateMatrix * translateMatrix;

However, usually you will consolidate the matrices on the CPU, where GLSL's matrix multiplication routine is out of reach. JavaScript doesn't have a native matrix type. Suppose you write your own Matrix4 class and give it a multiplyMatrix method. You'd then multiply the matrices together with code like this:

const chain = scaleMatrix.multiplyMatrix(rotateMatrix).multiplyMatrix(translateMatrix);

How would you implement the multiplyMatrix method?

You've seen how matrix-vector multiplication works. Each row of the matrix gets dotted with the vector to produce the components of the product vector. Matrix-matrix multiplication is an extension of this idea.

The product of multiplying two 4x4 matrices is itself a 4x4 matrix. Each component of this new matrix is computed by dotting a row from the left operand matrix and a column from the right operand matrix. Get a visceral feel for what vectors are involved by hovering your mouse over or tapping a component in one of the right-hand side matrices in this multiplication:


When you hover your mouse over the component in the first row and first column, which vector from the left operand is dotted with which vector from the second operand? What changes when you move to the second column? The third column? The fourth column? The second row?

Based on your exploration, you compose this pseuocode formula for calculating the component at row r and column c of the product matrix:

product[r, c] = dot(row r of left, column c of right)

Computing all 16 components is tedious to do by hand. You will let the computer do the work. To eliminate the slight overhead of loops and function calls, graphics developers will often write out the dot products. These four equations, for example, compute the components in the top row of the product matrix:

$$ \begin{aligned} p_{00} &= l_{00} \times r_{00} + l_{01} \times r_{10} + l_{02} \times r_{20} + l_{03} \times r_{30} \\ p_{01} &= l_{00} \times r_{01} + l_{01} \times r_{11} + l_{02} \times r_{21} + l_{03} \times r_{31} \\ p_{02} &= l_{00} \times r_{02} + l_{01} \times r_{12} + l_{02} \times r_{22} + l_{03} \times r_{32} \\ p_{03} &= l_{00} \times r_{03} + l_{01} \times r_{13} + l_{02} \times r_{23} + l_{03} \times r_{33} \\ \end{aligned} $$

This notation follows the convention of listing first the row and then the column in the subscripts. For example, \(p_{02}\) refers to the component at row 0 and column 2.

The remaining rows are computed similarly.