Multiplying Matrices
The benefit of matrices is realized when we concatenate or multiply a long sequence of them into a single matrix, but how exactly do we multiply two rectangular grids of numbers?
In GLSL, we can just use the native matrix type mat4
and the *
operator:
mat4 chain = scale * rotate * translate;
mat4 chain = scale * rotate * translate;
In JavaScript, we don't have a native matrix type, but we can write our own Matrix4
class and define a multiplyMatrix
method. We'd then multiply the matrices together with code like this:
const chain = scale.
multiplyMatrix(rotate).
multiplyMatrix(translate);
const chain = scale. multiplyMatrix(rotate). multiplyMatrix(translate);
How do we implement matrix-matrix multiplication in the multiplyMatrix
method? Matrix-vector multiplication is a good place to start our thinking. To multiply a matrix and a vector, we dot each row of the matrix with the vector. To multiply a matrix by another matrix, we treat the columns of the second matrix as four vectors. We dot each row of the first matrix with each column of the second.
The product of two 4×4 matrices is itself a 4×4 matrix. The component at row r
and column c
in the product is the dot product of row r
of the first matrix with column c
of the second matrix. Get a visceral feel for this operation by hovering your mouse over or tapping a component in one of the product matrices in this multiplication:
We compose this pseudocode 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)
product[r, c] = dot(row r of left, column c of right)
Computing all 16 components by hand is tedious. We will let the computer do the work. To eliminate the slight overhead of loops and function calls, graphics developers often write out the 16 dot products with 16 assignments. These four equations, for example, compute the components in the top row of the product matrix:
This notation follows the mathematical convention of listing the row first and the column second in the subscripts. For example, \(p_{02}\) refers to the component at row 0 and column 2.
The remaining rows are computed similarly.
Understanding how transformation matrices combine into a single matrix takes practice. To get some practice, check out Transformula, a sandbox for sequencing tranformations and examining their matrix representations.