Lateral chromatic aberration

How wavelength-dependent magnification separates colour channels toward the image edge — and how three inverse texture lookups reproduce it.

Visible effect

Colour separation grows with image height

Inspect a high-contrast edge near a corner, then compare it with the same edge near the optical centre.

At the centre the colour channels coincide. Toward the edge, red and blue move to opposite sides of the green reference, producing radial red–cyan or blue–yellow fringes.

Physics

Different wavelengths, different magnifications

Wavelength-dependent magnification in a lens Red, green, and blue rays from one off-axis object point pass through a lens and arrive at different image heights on the same sensor plane.off-axis object pointcompound lensimage plane
Dispersion makes the lens system’s transverse magnification slightly wavelength-dependent. One off-axis detail therefore reaches different image heights in red, green, and blue; the separation vanishes on the optical axis.

Optical glass has a refractive index that varies with wavelength. A real compound lens balances that dispersion, but its remaining transverse magnification can still differ slightly across the spectrum. Off-axis details then land at different image heights for red, green, and blue.

Mathematics

One radial mapping per colour channel

The shader approximates wavelength-dependent magnification with a separate radial polynomial for each RGB channel. Green is the reference mapping in the playground:

The polynomial is a compact image-space approximation, not a spectral ray trace. Its forward form predicts where an ideal channel sample lands. Raster rendering needs the inverse: for each destination pixel, find the source coordinate for red, green, and blue.

Shader

GLSL RGB inverse mapping

The playground compiles the coordinate function below twice per processed pixel—once for red and once for blue. Green uses the unmodified reference coordinate.

chromaticSourceCoordinateGLSL
// WHAT: Find a wavelength-dependent source coordinate for one colour channel.
// HOW: Iteratively invert the radial distortion polynomial in aspect-correct
// space; the caller repeats this with different coefficients for R, G, and B.
// WHY: Channels magnified by different amounts separate toward the frame edge,
// while inverse mapping keeps the output fully sampled.
vec2 chromaticSourceCoordinate(
  vec2 destinationUv01,
  vec2 centerUv01,
  vec2 radialCoefficients,
  float aspect
) {
  // Work in isotropic image coordinates so radius is not stretched by aspect.
  vec2 destination = destinationUv01 - centerUv01;
  destination.x *= aspect;
  vec2 source = destination;

  for (int iteration = 0; iteration < 9; iteration += 1) {
    // Fixed-point inversion solves source * radialScale(source) = destination.
    float r2 = dot(source, source);
    float r4 = r2 * r2;
    float radialScale = max(
      1.0 + radialCoefficients.x * r2 + radialCoefficients.y * r4,
      0.000001
    );
    source = destination / radialScale;
  }

  // Return to normalized texture coordinates for the actual channel sample.
  source.x /= aspect;
  return centerUv01 + source;
}
Processing pipelineBoxes mark actual render-pass boundaries.
  1. Source texture
  2. Per-channel coordinate remapOne fullscreen render pass
    • Channel mappings · parallel
      Invert and sample redInvert and sample greenInvert and sample blue
    • Recombine RGB
  3. Display output

Why these steps are here

  1. Build an isotropic radius. Scaling x by the target aspect ratio prevents a circular optical field from becoming an ellipse in UV space.
  2. Invert the forward polynomial. Nine bounded fixed-point iterations recover the channel’s source radius without forward-scattering pixels or leaving raster holes.
  3. Read channels separately. The fragment shader performs red, green, and blue texture reads at their own coordinates, then recombines the scalar samples.
  4. Mix the result. Amount blends the separated RGB result with the unmodified sample; it does not change the optical polynomial.

Three texture reads are used per processed pixel, or four while the amount blend also retains the original sample. No history buffer is required.

Notes

  • The RGB channels are broad display primaries, not individual wavelengths, so this is a perceptual approximation.
  • A symmetrical lateral aberration vanishes at the optical centre and grows with field height; a displaced centre makes the fringe field asymmetric within the frame.
  • Channel order can reverse with lens design, focal length, and image region. The sign controls expose both orientations.
  • Strong coefficients can make the radial mapping non-monotonic. The playground deliberately limits their range.

References

Edmund Optics — How aberrations affect imaging lenses — manufacturer reference for spherical, astigmatic, field-curvature, and chromatic aberrations.

Nikon MicroscopyU — Introduction to microscope objectives — manufacturer educational reference on coma, astigmatism, field curvature, chromatic correction, and flare.