How Does Smoothstep Work in GLSL?

The smoothstep function in GLSL performs smooth cubic Hermite interpolation between two boundary values, clamping inputs outside the range and eliminating sharp slope transitions. Unlike standard linear interpolation, smoothstep enforces a zero derivative at both endpoints, creating an ease-in, ease-out S-curve that transitions continuously in both value and first derivative. This mathematical property prevents visual creases in procedural textures, lighting models, and shader animations.

Input Normalization and Clamping

The standard signature of the function is smoothstep(edge0, edge1, x). Before evaluating any polynomial curve, the function maps the input parameter \(x\) from the arbitrary interval \([\text{edge0}, \text{edge1}]\) into a normalized unit interval \([0.0, 1.0]\).

To prevent extrapolation beyond the target bounds, the normalized value is clamped:

\[t = \text{clamp}\left(\frac{x - \text{edge0}}{\text{edge1} - \text{edge0}}, 0.0, 1.0\right)\]

If \(x \le \text{edge0}\), \(t\) resolves to \(0.0\). If \(x \ge \text{edge1}\), \(t\) resolves to \(1.0\). For all values in between, \(t\) represents the linear progress across the domain.

The Cubic Hermite Polynomial

Once the value is normalized into the range \([0.0, 1.0]\), GLSL applies a specific third-order polynomial known as a cubic Hermite interpolator:

\[S(t) = 3t^2 - 2t^3 = t^2(3 - 2t)\]

In GLSL source implementations, this is often computed directly as t * t * (3.0 - 2.0 * t).

Evaluating this function at the unit boundaries yields:

Why Zero Derivatives Ensure Smoothness

The defining advantage of cubic Hermite interpolation over linear interpolation (mix) lies in its rate of change. Taking the first derivative of \(S(t)\) with respect to \(t\) gives:

\[S'(t) = \frac{d}{dt}(3t^2 - 2t^3) = 6t - 6t^2 = 6t(1 - t)\]

Evaluating the first derivative at the boundaries reveals why the transition is smooth:

Because the derivative is zero at both \(t = 0.0\) and \(t = 1.0\), the slope of the curve matches the flat slope of the clamped regions outside the interval. This guarantees \(C^1\) continuity (a continuous first derivative) across the entire domain, preventing the visible Mach bands and angular seams that occur when linearly interpolating clamped data.

Higher-Order Continuity: Smootherstep

While smoothstep provides \(C^1\) continuity, its second derivative \(S''(t) = 6 - 12t\) evaluates to \(6\) at \(t = 0\) and \(-6\) at \(t = 1\), causing an instantaneous jump in acceleration at the boundaries.

For scenarios requiring \(C^2\) continuity (continuous second derivative), such as high-order surface normal generation and Perlin noise, Ken Perlin introduced the quintic polynomial known as smootherstep:

\[Q(t) = 6t^5 - 15t^4 + 10t^3 = t^3(t(6t - 15) + 10)\]

The first and second derivatives of \(Q(t)\) are zero at both \(t = 0.0\) and \(t = 1.0\), providing an even gentler transition that eliminates subtle curvature artifacts in graphics rendering.