Rays and Parametric Lines

A ray tracer asks one question, millions of times a second: starting here, looking that way, what do I hit? The "here" and the "that way" together are a ray — the single atom every other raytracing idea is built from. Before we can intersect a ray with a sphere, a plane, or a triangle, we need a way to name every point along it with one tidy formula. That formula is the parametric line, and it is almost embarrassingly simple.

Building the ray, line by line

A ray has two ingredients: a place to start and a direction to walk. Call the start the origin O (a point) and the direction D (a vector). We want a single point-valued function of one knob, t, that slides along the ray as we turn it.

Step 1 — start at the origin. When the knob is at zero, we have not moved at all, so we are sitting on the origin:

P(0) = O.

Step 2 — take one step in the direction. Turning the knob to t = 1 should walk us exactly one copy of D forward from O. Point plus vector is a point:

P(1) = O + D.

Step 3 — scale the step by the knob. Half a turn, t = \tfrac12, should land us halfway; two turns, t = 2, twice as far. So we scale the direction by t before adding it. That single line is the whole idea:

P(t) = O + t\,D.

Every point on the ray is some value of t, and every value of t is a point on the ray. To find where you are, plug a number in; to find which number a point is, that is exactly what an intersection test solves for.

Step 4 — keep t \ge 0 to look forward. A negative t walks backwards, behind the camera — light that never reached the lens. A ray, unlike an infinite line, is a one-way street: we only ever want t \ge 0. Negative solutions to an intersection are discarded as "behind me".

Step 5 — make D a unit vector and read off distance. If we normalise the direction so \lVert D\rVert = 1, then walking t copies of a length-one step covers exactly t units of ground. The parameter is the distance travelled:

\lVert P(t) - O\rVert = \lVert t\,D\rVert = t\,\lVert D\rVert = t \qquad (\text{when } \lVert D\rVert = 1).

That is why t is the prized quantity in a ray tracer: with a unit direction it is the literal depth of whatever you hit, and the closest hit is simply the smallest positive t.

A ray with origin O and direction D is the set of points P(t) = O + t\,D.

The same formula P(t) = O + tD describes three different objects; the only difference is which values of t you allow.

One equation, three jobs, picked apart purely by the interval you let t roam over.

Solving an intersection test hands you a value of t — and it is tempting to treat any solution as a hit. It isn't. The formula P(t) = O + t\,D describes the whole infinite line; only the half with t \ge 0 is the actual ray. A perfectly valid-looking root, say t = -3.2, is a real point on the line — it is just behind the origin, on the side the ray never travels.

This is one of the most common ray-intersection bugs: a sphere or plane test returns a mathematically correct t, the code forgets to check its sign, and the renderer "sees through" the camera to geometry that is physically behind it. The fix is a single guard clause — discard any root with t < 0 before it is ever treated as a hit. When two roots come back (as with a sphere), keep only the smallest non-negative one, not just the smallest.