Astigmatism
Why an off-axis point can focus at two different image distances — and how a field-oriented line spread reproduces the resulting directional blur.
Visible effect
Peripheral points stretch along a field-oriented line
Near the optical axis, a well-corrected lens can bring both principal ray fans to nearly the same image point. Farther into the field, those fans may reach their narrowest focus at different image distances. A flat sensor intersects the evolving point-spread function at one fixed plane, so peripheral detail becomes a short radial or tangential line instead of a point.
The direction changes around the image centre: the same aberration that makes a horizontal line spread at one edge can make a vertical or diagonal spread elsewhere. That field-oriented behaviour distinguishes astigmatism from a uniform directional motion blur.
Physics
Two principal ray fans reach their narrowest focus separately
For an off-axis object point, rays in the tangential plane and rays in the sagittal plane encounter different effective optical power. Their best-focus locations split into two curved focal surfaces. A flat sensor intersects one evolving three-dimensional bundle, not two independent images.
Mathematics
Blur grows with field height and follows a local basis
Third-order astigmatic focal separation grows approximately with squared image height h. The bounded real-time model uses normalized field radius ρ, an adjustable growth powerp, and either the radial unit vectoreᵣ or its perpendicular tangential vectoreₜ:
The approximation deliberately exposes one sensor-plane slice at a time. A physical through-focus model would evolve continuously between the two orthogonal line foci and the circle of least confusion.
Shader
GLSL field-oriented line gather
Each fragment builds an aspect-correct radial/tangential basis around the optical centre, grows its kernel toward the frame edge, and gathers a normalized Gaussian-weighted line in linear light.
// WHAT: Turn an off-axis point into a radial or tangential line blur.
// HOW: Build a field-relative direction, grow the radius toward the frame edge,
// then gather Gaussian-weighted samples along that local line in linear light.
// WHY: Astigmatism separates sagittal and tangential focus; a directional
// footprint communicates that structure more faithfully than an isotropic blur.
const int ASTIGMATISM_MAX_SAMPLES = 49;
float srgbToLinearChannel(float value) {
if (value <= 0.04045) return value / 12.92;
return pow((value + 0.055) / 1.055, 2.4);
}
vec3 srgbToLinear(vec3 value) {
return vec3(
srgbToLinearChannel(value.r),
srgbToLinearChannel(value.g),
srgbToLinearChannel(value.b)
);
}
vec2 astigmatismDirection(
vec2 sourceUv,
vec2 opticalCenter,
float sourceAspect,
bool tangential
) {
vec2 field = sourceUv - opticalCenter;
// Correct x before measuring direction so the field is isotropic on screen.
vec2 isotropicField = vec2(field.x * sourceAspect, field.y);
float fieldLength = length(isotropicField);
vec2 radialIso = fieldLength > 0.000001
? isotropicField / fieldLength
: vec2(1.0, 0.0);
vec2 radialUv = normalize(vec2(
radialIso.x / max(sourceAspect, 0.000001),
radialIso.y
));
return tangential ? vec2(-radialUv.y, radialUv.x) : radialUv;
}
vec3 astigmatismLine(
sampler2D source,
vec2 sourceUv,
vec2 sampleStep,
vec2 opticalCenter,
float sourceAspect,
float maxBlurPx,
float fieldPower,
bool tangential,
int sampleCount
) {
vec2 field = sourceUv - opticalCenter;
float fieldRadius = clamp(
length(vec2(field.x * sourceAspect, field.y)) * 2.0,
0.0,
1.0
);
// fieldPower controls how quickly the aberration appears away from centre.
float blurRadius = maxBlurPx * pow(fieldRadius, max(fieldPower, 0.1));
vec2 direction = astigmatismDirection(
sourceUv,
opticalCenter,
sourceAspect,
tangential
);
float safeCount = float(max(sampleCount, 1));
// Mip prefiltering stabilizes a wide gather when the tap budget stays fixed.
float lod = max(0.0, log2(max(blurRadius, 1.0)) - 2.2);
vec3 accumulated = vec3(0.0);
float totalWeight = 0.0;
for (int index = 0; index < ASTIGMATISM_MAX_SAMPLES; index += 1) {
if (index >= sampleCount) break;
float t = sampleCount <= 1
? 0.0
: float(index) / max(safeCount - 1.0, 1.0) * 2.0 - 1.0;
// Gaussian weights keep the line soft rather than ending as a hard streak.
float weight = exp(-3.2 * t * t);
vec2 offset = direction * sampleStep * blurRadius * t;
accumulated += srgbToLinear(
textureLod(source, sourceUv + offset, lod).rgb
) * weight;
totalWeight += weight;
}
// Weight normalization preserves brightness as radius and sample count vary.
return accumulated / max(totalWeight, 0.000001);
}- Source texturesRGB
- Directional Gaussian gatherOne fullscreen render pass
- Build the aspect-correct field basis
- Calculate the local line radius
- Gather Gaussian-weighted samples in linear light
- Mix the effect
- Encode to sRGB
- Display output
Why these steps are here
- Correct the field metric. Multiplying horizontal UV distance by the source aspect ratio keeps radial directions geometrically circular rather than screen-stretched.
- Build a local basis. The blur direction rotates around the optical centre instead of remaining fixed across the frame.
- Grow from the centre. A field power leaves axial detail sharp and concentrates the evidence near the edges.
- Normalize the gather. Dividing by total Gaussian weight avoids a brightness change as the kernel grows.
- Bound the pass. Forty-nine taps cap the direct gather while mip sampling suppresses sparse-kernel stepping.
A production optical renderer can replace this slice with a depth-aware two-dimensional PSF atlas.
Notes
- The procedural grid is the default because it makes the sharp centre, rotating peripheral direction, and edge growth measurable.
- Real lenses combine astigmatism with field curvature, defocus, coma, distortion, and sensor-plane tilt; this playground isolates only the oriented line-spread cue.
- The sign or orientation of the observed blur depends on the sensor plane relative to both astigmatic focal surfaces.
- The model has no scene depth, pupil coordinate, wavelength, or lens prescription, so its pixel radius is an artistic control rather than a calibrated optical measurement.
References
Nikon MicroscopyU — Astigmatism — explains sagittal and tangential focal surfaces and the resulting line-like point images.
Edmund Optics — How aberrations affect imaging lenses — manufacturer reference for spherical, astigmatic, field-curvature, and chromatic aberrations.