Color Exploration

Interactive instruments for understanding digital color.

Hub 1 Value 2 Magenta 3 Saturation 4 Ramps 5 Spaces 6 Collapse

Each module states one fact about digital color and gives you an instrument to test it. The controls are the main content — the text explains what you're seeing, but the understanding comes from manipulating the thing yourself. The modules run in a loose sequence: first how perception works, then the systems that put numbers on it.

01 · Perception

Value vs. Luminance

HSV's value channel doesn't measure how bright a color looks. At V = 100, actual luminance varies by roughly 13× across hues.

Open →
02 · Perception

Magenta and Non-Spectral Colors

No single wavelength produces magenta. It exists only as a mixture — red and blue light together, with little green.

Open →
03 · Systems

Saturation Across Models

Turning up saturation darkens a color in HSV, shifts with hue in HSL and sRGB, and leaves lightness alone in OKLCH. Same slider, different operations.

Open →
04 · Systems

The Perceptual Ramp Builder

Equal numeric steps between two colors are not perceptually equal. Compare interpolation in five spaces and export the ramp that works.

Open →
05 · Systems

Why Color Spaces Exist

Blend blue to yellow in sRGB and the middle of the gradient turns gray. Every color space since was invented to fix a failure like this one.

Open →
06 · Dynamic range

Color Collapse in Tone Mapping

Brighten a saturated color and its hue shifts as channels clip. The tone map decides whether that shift is a filmic feature or a broken brand color.

Open →

Module 1 · Perception

HSV's value and HSL's lightness are not measures of brightness. Perceived brightness is luminance — a weighted sum of the primaries in which green counts for far more than red, and red for far more than blue — so two colors with identical value can differ several-fold in luminance.

How it works

The eye does not weight red, green, and blue equally. Its sensitivity peaks in the middle of the spectrum, near green, and falls off steeply toward blue — the same amount of light produces far less brightness sensation at 450 nm than at 555 nm. Relative luminance is the number that captures this: a weighted sum of the linearized RGB channels, with weights matched to the eye. Under Rec. 709, Y = 0.2126·R + 0.7152·G + 0.0722·B. Green carries nearly three-quarters of the total; blue carries about 7%.

HSV's value channel involves no weighting at all — V is simply the largest of the three channel values. Full-value yellow lights the red and green subpixels, which together carry about 93% of white's luminance. Full-value blue lights only the blue subpixel: about 7%. Both report V = 100. The instrument below sweeps the full hue circle so you can watch actual luminance swing while V insists nothing is changing.

The weights also explain the shape of the curve. Cyan, magenta, and yellow each light two subpixels at once, and luminance simply adds: yellow is red plus green (21% + 72% ≈ 93%), cyan is green plus blue (≈ 79%), magenta is red plus blue (≈ 28%). Those three sums are the curve's peaks, and they mean every two-subpixel secondary is brighter than either primary inside it. In the instrument, each subpixel combination sits directly beneath its position on the curve — secondaries under the peaks, lone primaries under the valleys.

In practice

A color picker's brightness number tells you almost nothing about how bright the color will look. Decisions that actually depend on brightness — text legibility, visual hierarchy, how much light a 3D material appears to reflect — need luminance or L*, both of which the readout above reports. The clearest everyday case is saturated blue text on a dark background: the picker reports the same value it would for any hue, but at 7% luminance the text barely contrasts with black. Module 4 takes this idea further and builds usable color ramps out of the measured number.

Module 2 · Perception

Magenta is a non-spectral color: no single wavelength produces it. It appears only when the eye receives long and short wavelengths at once, filling the gap the spectrum leaves between red and violet.

How it works

The visible spectrum runs from about 380 nm (violet) to 700 nm (red), and it is a line — no wavelength bends red back around toward violet. The chart below, the CIE 1931 chromaticity diagram, maps every chromaticity the eye can distinguish. Pure single wavelengths form the curved rim, called the spectral locus. Mixing two lights always produces a color on the straight line between their positions, which is why every visible color falls somewhere inside the horseshoe.

The straight edge along the bottom is the exception to the rim: the line of purples. It connects the violet end of the spectrum directly to the red end, and no point on it corresponds to any wavelength. The colors there — magenta among them — can only be produced by mixing light from the spectrum's two far ends. When the eye's long-wavelength and short-wavelength cones respond strongly while the middle stays quiet, the visual system produces magenta. The color is real; it simply has no position in the rainbow.

In practice

Every color wheel is a manufactured object. The spectrum nature provides is a line, with violet at one end and red at the other; to turn that line into a circle, the purples have to be spliced in as a bridge between the ends. That bridge is made entirely of colors that exist only as mixtures. The seamless hue circle in every color picker includes this splice without marking it — the wheel reads as a fact of nature, but it is an act of design.

Once you see the wheel as designed, its layout becomes a live question: how much of the circle should green occupy? Where exactly does the color opposite blue sit? Different answers produce different wheels, and every rule that measures angles on one — every "complementary" or "triadic" scheme — inherits those answers. It is why the same harmony rule can hand you different colors depending on which wheel it quietly assumes, and why classic advice written for a painter's pigment wheel often misfires on a screen.

Module 3 · Systems

"Increase saturation" is a different operation in every color model, and most of them change the color's lightness as a side effect.

How it works

Every model agrees that saturation is distance from gray. They disagree about which gray, and about what else is allowed to change on the way there. HSV holds the maximum channel fixed and pulls the other two down — an operation that can only remove light, so saturating in HSV always darkens, and a fully desaturated color at V = 100 is white. HSL instead pins the midpoint of the highest and lowest channels. Whether luminance rises or falls then depends on which channels are doing the moving, and that depends on hue: saturating a yellow at 50% lightness brightens it dramatically, while saturating a blue darkens it.

The saturation slider in most raster editors is a third operation: scale all three channels away from their average. Where that leads follows from Module 1's channel weights — hues whose light lives mostly in the red and green channels gain luminance as they spread away from gray, and blues lose it.

CIELab and OKLCH are the only models here that treat lightness as a protected axis. Chroma is defined perpendicular to it, so C can change while L holds still — visible in the graph below as two nearly flat lines. One footnote applies even there: at equal measured luminance, a strongly saturated color still looks slightly brighter than gray, an effect known as Helmholtz–Kohlrausch. Constant lightness in the numbers is very close to constant lightness in experience, but not identical.

In practice

This bites hardest wherever saturation gets adjusted after contrast has been approved. Pickers in design tools are almost universally HSV or HSL, so a late "make it a bit more saturated" on a brand color silently moves its lightness — and with it, every contrast ratio that color participates in. Either re-check contrast after chroma edits, or make them in OKLCH, where lightness actually stays put. The same logic extends to 3D: saturating an albedo map changes its luminance, which changes how much light the material appears to reflect — a material change, not just a color one.

Module 4 · Systems

Equal numeric steps between two colors are not perceptually equal. Perceptually uniform spaces produce visually even steps by design.

How it works

All five ramps below do the same thing: divide the interval between your endpoints into equal steps. What differs is the ruler. sRGB and HSL measure the interval with channel arithmetic; CIELab, OKLab, and OKLCH measure it in coordinates that were fitted to human judgments of color difference.

The graph shows what each ruler ignores. The dashed line is the quantity the selected space kept perfectly even — its own lightness metric. The solid line is measured lightness, L*, for the same steps. In HSL the dashed line is ruler-straight while L* swings around it, and those swings are the muddy middles you can see in the swatches. Select the OKLCH row and the two lines nearly coincide: the quantity the space keeps even is, finally, the one your eye cares about.

The geometry view explains the differences in shape terms. sRGB, CIELab, and OKLab are rectangular spaces, so a blend is a straight line through the interior — and between near-complementary endpoints, the interior is neutral gray. HSL and OKLCH are cylinders: hue is an angle, so a blend travels around the central gray axis instead of through it. That is also why a cylindrical blend between near-opposite hues has to choose a direction — the two arcs around the axis are nearly the same length, and the hue-path control makes that choice explicit.

In practice

This is the mechanism behind a familiar design-system failure. A ramp gets generated by stepping HSL lightness evenly; months later someone notices that text passes contrast on step 600 but fails on 500; the middle steps get hand-tuned, and the ramp drifts away from being a system at all. Generating the ramp in OKLCH avoids the failure at the source, because steps that are numerically even in OKLCH are even to the eye. The contrast overlay marks each step against white and black, and the export writes hex, CSS custom properties, or JSON design tokens — ready for a token file as-is.

Module 5 · Systems

No single color space is correct for everything. Each was created to solve a problem the earlier ones could not — defining a color independently of any device, making numeric distance match perceived distance, or keeping a gradient from passing through gray.

How it works

Blue and yellow sit at opposite corners of the RGB cube, so averaging their channel values lands the midpoint near the cube's center — and the center of the RGB cube is gray. Nothing malfunctioned. "Average the numbers" corresponds to "blend the appearance" only if the space was built with appearance in mind, and RGB was built to drive hardware. Failures of exactly this shape are what produced each new space: every timeline entry below pairs a space with the problem it was created to solve, and selecting one loads endpoints that reproduce the problem in the strips.

In practice

Choosing a space becomes straightforward once you ask what needs to be even: the numbers or the appearance. Gradients, ramps, and anything else judged by eye should be interpolated in OKLCH. A quick hue rotation on an existing color doesn't need perceptual accuracy, so HSV's cheap arithmetic is fine there. And when a grading or compositing tool offers a "perceptual" blend mode, this is what it means — Lab-family behavior, the kind that matches what your eye expects. "It depends" is the right answer, but what it depends on has a name.

Module 6 · Dynamic range

Brighten a saturated color and its hue shifts as its channels clip. The tone map you choose decides whether that shift reads as filmic or as a broken brand color.

How it works

A rendered or photographed scene holds light values far above what a display can show, so a tone map has to fit that unbounded range into the 0–1 the screen can emit. The simplest way is to clip: cap each channel at 1. But a saturated color is a specific ratio between its channels, and when the brightest channel hits the ceiling while the others keep climbing, that ratio changes — which means the hue changes. Push a saturated orange up and its red pins at 1 while green keeps rising, so it slides toward yellow.

Because pure primaries and secondaries have channels that clip together or not at all, they hold their hue, while every hue between them migrates toward the nearest one. Do this across the whole wheel and the hues bunch into six attractors — red, yellow, green, cyan, blue, magenta — the "notorious six" collapse familiar from bright renders and blown-out highlights. Per-channel curves like Reinhard and the common ACES fit soften the clip but skew the same way, because they still operate channel by channel.

AgX takes a different route: it desaturates the highlight as it brightens, pulling chroma out on the way to white so no single channel has to clip against the others. Hue is preserved, at the cost of vivid highlights washing to white sooner. That trade is the whole debate — the plot below lets you watch each mapper's hue drift, and the wheel shows where every hue lands.

In practice

For film and stylized renders, the hue skew is often desirable — warm highlights rolling toward yellow-white is part of what "cinematic" looks like, and filmic mappers lean into it. For product and brand work it is a defect: a brand red that turns orange in a specular highlight is wrong, no matter how bright the scene. That is the case for a hue-preserving mapper like AgX, or for compositing the brand color back in after the tone map.

This is why Blender moved its default view transform from Filmic to AgX, and why ACES 2.0 was built partly to tame the same six-hue skew. It also explains a subtle 3D pitfall: an emissive or albedo color that looks correct at rest can shift hue the moment it catches a bright light, because the tone map is doing this to it — the material didn't change, the exposure did.

Color Exploration — an instrument set for digital color.