The Dot Product in Games

If you learn one operation in game math, learn the dot product. It is a single multiply-and-add that secretly measures the angle between two directions, and that one number answers a startling range of in-game questions: is the enemy in front of me? how long is this vector's shadow on that one? how bright is this surface? Its whole power flows from one identity,

\vec{a} \cdot \vec{b} = \lVert \vec{a}\rVert\,\lVert \vec{b}\rVert\,\cos\theta,

where \theta is the angle between \vec{a} and \vec{b} (see dot product and angle). Because \cos rides along, the dot product is really an angle-meter in disguise. Here are its three workhorse jobs.

Three jobs, line by line

Step 1 — (i) Facing: the sign tells you in front or behind. The lengths in \lVert\vec{a}\rVert\lVert\vec{b}\rVert are always positive, so the sign of \vec{a}\cdot\vec{b} is exactly the sign of \cos\theta:

\operatorname{sign}(\vec{a}\cdot\vec{b}) = \operatorname{sign}(\cos\theta) = \begin{cases} +\ & \theta < 90^\circ \ \ (\vec{b} \text{ is in front of } \vec{a}) \\ 0\ & \theta = 90^\circ \ \ (\text{exactly beside}) \\ -\ & \theta > 90^\circ \ \ (\vec{b} \text{ is behind } \vec{a}). \end{cases}

Point \vec{a} the way the guard faces and let \vec{b} be the direction to the player: one dot product, read its sign, and you know whether the player is ahead, beside, or behind.

Step 2 — (ii) Projection: the shadow length. Take \vec{b} and a unit direction \hat{a} (so \lVert\hat{a}\rVert = 1). Then the identity collapses to the length of \vec{b}'s shadow cast along \hat{a} — its projection:

\vec{b}\cdot\hat{a} = \lVert\vec{b}\rVert\cos\theta = (\text{how far } \vec{b} \text{ reaches in the } \hat{a} \text{ direction}).

This is "how much of my speed is forward?", "how far up the ramp did I climb?", "what's my component toward the goal?" — all one dot with a unit vector.

Step 3 — (iii) Lighting: brightness is a cosine. A matte (diffuse) surface with unit normal \hat{N} lit from unit direction \hat{L} is brightest face-on and dims as it tilts away — exactly \cos\theta. Clamp the back side to dark (no negative light):

\text{brightness} = \max\!\big(0,\; \hat{N}\cdot\hat{L}\big).

This single line — Lambert's cosine law — runs for every lit pixel in the frame. Face the light: \hat{N}\cdot\hat{L} = 1, full bright. Turn edge-on: 0. Turn away: clamped to 0, dark.

For vectors \vec{a}, \vec{b} at angle \theta, \vec{a}\cdot\vec{b} = \lVert\vec{a}\rVert\lVert\vec{b}\rVert\cos\theta, and three jobs follow:

"Can the guard see the player?" is a dot product. Let \hat{f} be the unit direction the guard faces and \hat{d} the unit direction to the player. The player is inside a vision cone of total angle \text{fov} exactly when the angle between them is at most half the cone — i.e. when the cosine is large enough:

\hat{f}\cdot\hat{d} \;>\; \cos\!\Big(\frac{\text{fov}}{2}\Big).

One dot, one precomputed constant \cos(\text{fov}/2), one comparison — no inverse cosine, no square roots, no branches. That is why stealth games can afford to ask it for hundreds of enemies every single frame. Narrow the cone and the threshold rises toward 1; widen it toward 180^\circ and the threshold falls toward 0, "anything not behind me".