The simplest of the four 3D matrix types is the Scaling matrix.

In this context, “scaling” means to make a shape larger or smaller by multiplying a vector by a scalar value.

Given a data type Vector4:

`struct Vector4`

{

float X;

float Y;

float Z;

float W;

};

A simple way to scale a vector might be:

Vector4 Scale(const Vector4& v, const float uniformScale)

{

return Vector4(v.x * uniformScale, v.y * uniformScale, v.z * uniformScale, v.w);

}

However, if we plan on performing this operation on lots of data points – say, in a vertex shader which operates on every vertex in our model, we’d like to use a matrix so that the scale operation can be combined with our rotation, translation and projection operations. Given an identity matrix:

\(\begin{bmatrix}

1 & 0 & 0 & 0 \\

0 & 1 & 0 & 0 \\

0 & 0 & 1 & 0 \\

0 & 0 & 0 & 1 \\

\end{bmatrix} \\

\)

and remembering that in a row-major matrix such as this, each row represents a basis vector of a transformed coordinate system. The values on the diagonal of an identity matrix represent a coordinate system that has a scale of 1. Not very exciting.

To create a scaling matrix, we’ll multiply the values on the diagonal with our scale vector

\(\vec{s} = (s_x, s_y, s_z, 1)\)

which gives us:

\begin{bmatrix}

s_x & 0 & 0 & 0 \\

0 & s_y & 0 & 0 \\

0 & 0 & s_z & 0 \\

0 & 0 & 0 & 1 \\

\end{bmatrix}

\)

**Notes:**

- The the W component of the last row (bottom right corner of the matrix) is NOT modified, as we are only concerned with scaling in X, Y and Z. Scaling W leads to interesting side effects.
- Although this example allows for \(\vec{s}\) to have different values for its \((s_x, s_y, s_z)\) components, we will usually want these all to be the same number for uniform scaling.