Chapter 05

Matrices and Linear Transformations

Rotation, scale, projection, reflection, and shear — and how to combine them.

In this chapter

  1. Linear vs Affine Transformations
  2. Rotation
  3. Scale
  4. Orthographic Projection
  5. Reflection
  6. Shearing
  7. Combining Transformations (TRS)
  8. Exercises
1

Linear vs Affine Transformations

Linear Transformation
  • Preserves straight lines and parallelism
  • Does not include translation
  • Represented by 2D or 3D square matrices
  • Allows: rotation, scale, reflection, shear, orthographic projection
Affine Transformation
  • Linear transformation plus translation
  • Requires a 4×4 matrix in 3D (homogeneous coordinates)
  • The w-component (1 for points, 0 for directions) enables translation
  • Used for: the full model/view matrix in a render pipeline
Translation cannot be expressed as a 3×3 linear transformation because linear maps must send the origin to itself. Adding a homogeneous fourth coordinate (the "w" in XYZW vectors) extends the math to support translation within a matrix multiply.

2

Rotation

2D Rotation About the Origin

Rotates a 2D vector by angle θ counter-clockwise. The columns are the transformed basis vectors:

R(θ) = ┌ cos θ sin θ ┐ └ -sin θ cos θ ┘ cos(θ) = adj/hyp = x / ‖v‖ sin(θ) = opp/hyp = y / ‖v‖

3D Rotation About Cardinal Axes

Keep one basis vector fixed and apply 2D rotation to the other two. Use the left-hand rule to determine the +/- direction for a left-handed system.

Rx(θ) = ┌ 1 0 0 ┐ │ 0 cos θ sin θ │ └ 0 -sin θ cos θ ┘ Ry(θ) = ┌ cos θ 0 -sin θ ┐ │ 0 1 0 │ └ sin θ 0 cos θ ┘ Rz(θ) = ┌ cos θ sin θ 0 ┐ │ -sin θ cos θ 0 │ └ 0 0 1 ┘

Note: Rz matches 2D rotation. Ry has its sin terms negated (because Y is the "up" axis and the rotation crosses the Z-X plane in the opposite sense).

3D Rotation About an Arbitrary Axis

Given unit axis n̂ = (nx, ny, nz) and angle θ, decompose the vector being rotated into a component parallel to n̂ (unchanged) and perpendicular (rotated). The resulting matrix is:

R(n̂, θ) = ┌ nx²(1-c)+c nx·ny(1-c)+nz·s nx·nz(1-c)-ny·s ┐ │ nx·ny(1-c)-nz·s ny²(1-c)+c ny·nz(1-c)+nx·s │ └ nx·nz(1-c)+ny·s ny·nz(1-c)-nx·s nz²(1-c)+c ┘ where c = cos θ, s = sin θ
This general form subsumes all cardinal-axis rotations. Setting n̂ = (1,0,0) recovers Rx, (0,1,0) gives Ry, (0,0,1) gives Rz. In game engines, this formula is often derived from quaternions.

3

Scale

Uniform Scale

Applies the same factor k to all axes. Preserves angles and proportions. Lengths scale by k, areas by k², volumes by k³.

Non-Uniform Scale

Different factors per axis. Does not preserve angles or proportions.

Scaling Along Cardinal Axes

S₂D(kx, ky) = ┌ kx 0 ┐ └ 0 ky ┘ S₃D(kx, ky, kz) = ┌ kx 0 0 ┐ │ 0 ky 0 │ └ 0 0 kz ┘

Scaling in an Arbitrary Direction

Given unit axis and scale factor k, decompose the vector into parallel and perpendicular parts. The perpendicular part is unchanged; the parallel part is scaled:

v' = v + (k - 1)(v · n̂)·n̂ S₂D(n̂, k) = ┌ 1+(k-1)nx² (k-1)nx·ny ┐ └ (k-1)nx·ny 1+(k-1)ny² ┘ S₃D(n̂, k) = ┌ 1+(k-1)nx² (k-1)nx·ny (k-1)nx·nz ┐ │ (k-1)nx·ny 1+(k-1)ny² (k-1)ny·nz │ └ (k-1)nx·nz (k-1)ny·nz 1+(k-1)nz² ┘

4

Orthographic Projection

Also called parallel projection. Any dimension-reducing operation. In practice: dropping one coordinate by scaling it to 0.

Projecting onto a Cardinal Axis or Plane

Use a scale factor of 0 for the axis you want to "discard":

Pxy = ┌ 1 0 0 ┐ Pxz = ┌ 1 0 0 ┐ Pyz = ┌ 0 0 0 ┐ │ 0 1 0 │ │ 0 0 0 │ │ 0 1 0 │ └ 0 0 0 ┘ └ 0 0 1 ┘ └ 0 0 1 ┘

Projecting onto an Arbitrary Plane Through the Origin

Given a unit normal to the plane, apply scale factor 0 in the n̂ direction (and 1 perpendicular to it):

P(n̂) = S(n̂, 0) = ┌ 1-nx² -nx·ny -nx·nz ┐ │ -nx·ny 1-ny² -ny·nz │ └ -nx·nz -ny·nz 1-nz² ┘

5

Reflection

Also called mirroring. Flips the object about a line or plane. is perpendicular to the axis/plane of reflection. Perform a scale of −1 in the n̂ direction:

R₂D(n̂) = S(n̂, -1) = ┌ 1-2nx² -2nx·ny ┐ └ -2nx·ny 1-2ny² ┘ R₃D(n̂) = S(n̂, -1) = ┌ 1-2nx² -2nx·ny -2nx·nz ┐ │ -2nx·ny 1-2ny² -2ny·nz │ └ -2nx·nz -2ny·nz 1-2nz² ┘
Reflection changes the handedness of a coordinate system. After reflecting, back-face culling and normal directions are flipped. Games often handle this by negating the scale in the material (setting a negative determinant flag) and flipping the face winding order.

6

Shearing

Shear skews coordinate space non-uniformly — parallel lines remain parallel but are no longer perpendicular. It adds a multiple of one coordinate to another:

x' = x + s·y (shear x by s times y)

As y increases, x is pushed further by the factor s. The 3D shear matrices:

Hxy(s, t) = ┌ 1 0 0 ┐ Hxz(s, t) = ┌ 1 s t ┐ Hyz(s, t) = ┌ 1 s t ┐ │ 0 1 0 │ │ 0 1 0 │ │ 0 1 0 │ └ s t 1 ┘ └ 0 0 1 ┘ └ 0 0 1 ┘
Shear rarely appears directly in game object transforms, but it arises from non-uniform scale followed by rotation — the composed matrix is effectively a shear. This is why applying non-uniform scale to a rotating object requires care, and why game engines often decompose TRS separately rather than concatenating arbitrary matrices.

7

Combining Transformations (TRS)

Game engine scene objects are almost always described by a TRS transform: Translation, Rotation, and Scale. To build the final model matrix:

M = T · R · S (column-vector convention: applied right to left) 1. Scale the mesh vertices 2. Rotate them into orientation 3. Translate them into world position
Order matters. TRS is the standard order because it gives the most natural behavior: scale happens in local object space, rotation is around the object's center, and translation moves the object in world space. Any other order produces unexpected results.

In a 4×4 homogeneous matrix, the full TRS can be stored in a single matrix and applied in one multiply per vertex in the vertex shader — this is the purpose of the model matrix (also called the world matrix in DirectX terminology).

Inverse of a TRS Matrix

The inverse undoes the transform. For TRS: first undo T, then R, then S:

M⁻¹ = S⁻¹ · R⁻¹ · T⁻¹ S⁻¹ = S(1/kx, 1/ky, 1/kz) R⁻¹ = Rᵀ (orthonormal, so inverse = transpose) T⁻¹ = T(-tx, -ty, -tz)

8

Exercises

1. 2D Rotation

Write the 2D rotation matrix for θ = 90°. Apply it to the vector (1, 0) and verify the result is (0, 1).

R(90°) = [[cos90°, sin90°], [-sin90°, cos90°]] = [[0, 1], [-1, 0]]. Result: (1·0 + 0·(-1), 1·1 + 0·0) = (0, 1). ✓

2. Scale Matrix

An object is scaled by 2 in X and 0.5 in Y. Write S, then apply it to vertex (4, 6, 0).

S = diag(2, 0.5, 1). Result: (8, 3, 0).

3. TRS Composition

An object is at position (10, 0, 5), rotated 90° around Y, and scaled uniformly by 2. In what order do you multiply T, R, S to form the model matrix?

M = T · R · S (right to left in column-vector convention). Scale first, then rotate, then translate. Reversing scale and rotation would cause the scale to apply in world space, stretching the object unintentionally along world axes.

Interview Question

What is the difference between a linear transformation and an affine transformation?

A linear transformation maps the origin to itself and preserves addition and scalar multiplication — it can rotate, scale, reflect, shear. An affine transformation also allows translation. Translation requires homogeneous coordinates (4×4 matrices in 3D) because it cannot be expressed as a 3×3 linear map.

Interview Question

You have an object with non-uniform scale S=(2,1,1) and a rotation R of 45° around Y. Why does S·R produce a shear, and how would you avoid it in practice?

Non-uniform scale followed by rotation distorts axis directions — the scaled axis no longer aligns with the rotation axis, introducing a shear. In practice, game engines avoid concatenating arbitrary scale+rotation matrices. Instead they store TRS as separate components and re-derive the matrix only at render time, keeping scale in object space before rotation.

Interview Question

How do you construct a "look-at" matrix for a camera?

1. Compute forward = normalize(target - eye). 2. Compute right = normalize(forward × worldUp). 3. Compute up = right × forward (re-orthogonalize). 4. Build the view matrix from these three vectors and the eye position. This is a rotation + translation in camera space and is used directly as the view matrix in the render pipeline.
← Chapter 4 ↑ Index Chapter 6 →