In which you learn how translation can be expressed in terms of dot products.
Earlier you translated by adding offsets to a position. In scalar form, translation looks like this:
$$ \begin{aligned} p'_x &= p_x + \textrm{offset}_x \\ p'_y &= p_y + \textrm{offset}_y \\ p'_z &= p_z + \textrm{offset}_z \end{aligned} $$
Those right-hand sides don't look like dot products at all. Nevertheless, as with scaling and rotation, you want to rewrite the equations above to use dot products. They will have this form:
$$ \begin{aligned} p'_x &= \mathbf{a} \cdot \mathbf{p} \\ p'_y &= \mathbf{b} \cdot \mathbf{p} \\ p'_z &= \mathbf{c} \cdot \mathbf{p} \end{aligned} $$
You expand out these equations to see how the dot products might be constructed:
$$ \begin{aligned} p'_x &= a_x \times p_x + a_y \times p_y + a_z \times p_z \\ p'_y &= b_x \times p_x + b_y \times p_y + b_z \times p_z \\ p'_z &= c_x \times p_x + c_y \times p_y + c_z \times p_z \\ \end{aligned} $$
Neither \(p_y\) nor \(p_z\) are involved in the scalar definition of \(p'_x\), so you zero out their coefficients in \(\mathbf{a}\). The coefficient for \(p_x\) is an implicit 1. That leads you to this possible definition:
$$ \begin{aligned} p'_x &= \begin{bmatrix}1 & 0 & 0\end{bmatrix} \cdot \mathbf{p} \end{aligned} $$
But that can't be right. There's no mention of \(\textrm{offset}\) anywhere. There's not even a place to introduce it. Each term in a dot product is a multiplication of two associated components, but \(\textrm{offset}_x\) has no coefficient from \(\mathbf{p}\). Perhaps translation cannot be recast as a dot product?
Do not despair. To make translation fit in the dot product machinery, you get to bend the rules. You get to add 1 as a fourth component of \(\mathbf{p}\):
$$ \mathbf{p} = \begin{bmatrix}p_x & p_y & p_z & 1\end{bmatrix} $$
This special fourth component is called the homogeneous coordinate. You've seen it at work already in vertex shaders when you turn the 3-vector position
into the 4-vector gl_Position
:
gl_Position = vec4(position, 1.0);
The 1 serves as a coefficient for \(\textrm{offset}_x\). That means you can write \(p'_x\) as this dot product:
$$ \begin{aligned} p'_x &= 1 \times p_x + 0 \times p_y + 0 \times p_z + \textrm{offset}_x \times 1 \\ &= \begin{bmatrix}1 & 0 & 0 & \textrm{offset}_x\end{bmatrix} \cdot \begin{bmatrix}p_x & p_y & p_z & 1\end{bmatrix} \\ &= \begin{bmatrix}1 & 0 & 0 & \textrm{offset}_x\end{bmatrix} \cdot \mathbf{p} \end{aligned} $$
Components \(p_y\) and \(p_z\) are expressed similarly. Altogether, translation has this dot product form:
$$ \begin{aligned} p'_x &= \begin{bmatrix}1 & 0 & 0 & \textrm{offset}_x\end{bmatrix} \cdot \mathbf{p} \\ p'_y &= \begin{bmatrix}0 & 1 & 0 & \textrm{offset}_y\end{bmatrix} \cdot \mathbf{p} \\ p'_z &= \begin{bmatrix}0 & 0 & 1 & \textrm{offset}_z\end{bmatrix} \cdot \mathbf{p} \end{aligned} $$
You've recast all three transformations as dot products. The next step is to get the GPU to perform dot product transformations quickly in shader programs.