Repeated lerp: de Casteljau, line by line
Step 1 — start with three control points. Take
P_0, P_1, P_2 (a quadratic Bézier). For a given
t \in [0, 1], lerp along the two edges of the control polygon:
A = \operatorname{lerp}(P_0, P_1, t) = (1 - t)P_0 + t P_1, \qquad B = \operatorname{lerp}(P_1, P_2, t) = (1 - t)P_1 + t P_2.
Step 2 — lerp the lerps. Now blend those two moving points by the same
t. This second-level lerp is the curve point:
B(t) = \operatorname{lerp}(A, B, t) = (1 - t)A + t B.
That nested-lerp recipe — lerp the edges, then lerp the results — is
de Casteljau's algorithm. It is numerically rock-solid and generalises to any
degree just by adding more levels.
Step 3 — expand to the closed form. Substitute
A and B and collect terms:
B(t) = (1 - t)\big[(1 - t)P_0 + t P_1\big] + t\big[(1 - t)P_1 + t P_2\big].
B(t) = (1 - t)^2 P_0 + 2(1 - t)t\,P_1 + t^2 P_2.
Those three coefficients (1-t)^2,\; 2(1-t)t,\; t^2 are the
Bernstein polynomials of degree 2 — and notice they are exactly
\big[(1-t) + t\big]^2 expanded, so they always sum to
1. The curve is a moving weighted average of the control points.
Step 4 — add a point for the cubic. One more control point
P_3 and one more level of de Casteljau gives the cubic Bézier,
the one tools actually ship:
B(t) = (1 - t)^3 P_0 + 3(1 - t)^2 t\,P_1 + 3(1 - t)t^2 P_2 + t^3 P_3.
Same pattern: the coefficients are degree-3 Bernstein polynomials (the binomial
1, 3, 3, 1 weights of
\big[(1-t) + t\big]^3), and again they sum to 1.
Step 5 — the endpoints are exact. Plug in t = 0: every
term with a t dies, leaving B(0) = P_0. At
t = 1 every (1 - t) term dies, leaving
B(1) = P_3. The curve passes through its first and last control
points — those are the anchors you place.
Step 6 — the interior points only pull. The curve does not pass through
P_1 and P_2; their Bernstein weights never
reach 1 on their own, so they act as handles that
pull the curve toward themselves without touching it. And because every point is a weighted
average with non-negative weights summing to 1, the whole curve stays
inside the convex hull of the control points — it can never wander outside the
polygon you drew. That is what makes Béziers so tame to edit: drag a handle, the curve leans that
way, and it never escapes the cage.
A Bézier curve is built from its control points by repeated lerp:
-
de Casteljau: lerp adjacent control points by t, then
lerp the results, repeating until one point remains — that point is
B(t).
-
Quadratic (Bernstein form):
B(t) = (1-t)^2 P_0 + 2(1-t)t\,P_1 + t^2 P_2.
-
Cubic:
B(t) = (1-t)^3 P_0 + 3(1-t)^2 t\,P_1 + 3(1-t)t^2 P_2 + t^3 P_3.
-
It passes through the endpoints (B(0) = P_0,
B(1) = P_n) and is only pulled toward the interior
control points (the handles).
-
The Bernstein weights are non-negative and sum to 1, so the curve
stays inside the convex hull of its control points.
Open a vector editor, a font, or an animation timeline and you will find Bézier handles
everywhere. Fonts — TrueType outlines are quadratic Béziers, PostScript/OpenType
CFF outlines are cubic; every glyph you read is a chain of these curves. Vector art
— the pen tool in Illustrator, Inkscape, or any SVG editor places anchor points
(P_0, P_3) and drags their handles (P_1, P_2),
which is literally Step 6. Animation — the ease curves of the previous page are
usually authored as cubic Béziers (CSS cubic-bezier(.25,.1,.25,1) is four control-point
coordinates), so a motion designer shapes timing by dragging the same handles. They are popular for
the exact reasons in the theorem: endpoints are honoured, the convex-hull property keeps them
predictable, and de Casteljau makes them cheap and stable to evaluate and subdivide. The polynomial
shapes themselves are studied as
cubic graphs.