Training the Eye: color relativity and interaction
Learning objectives
- Learner can demonstrate that a single color is almost never perceived as it physically is, separating color agent from color effect
- Learner can predict how a ground subtracts its own hue/lightness and how simultaneous and successive contrast generate complements
- Learner can build the interaction studies with cut color paper and stripe layouts that isolate hue relationships
Capstone — one whole task that evidences the objectives
Produce an Albers-style color-interaction plate set in cut paper: make one color look like two, make two colors look like one (illusory transparency/middle-mixture), and a stripe study that suppresses shape so the interaction reads as pure color relationship — annotate each with the effect it demonstrates.
Prerequisite modules
Every palette you push to a projector behaves like Albers’s paper: the moment a hue lands next to another on screen — behind a dancer, over a strobing background — it stops being the RGB value you typed. This module trains the eye that live visualists need before any code: the ability to see that color is relational, and to predict how a context will bend a swatch before you commit it to a running patch.
The arc starts supported and ends blind. First, internalize the thesis that color is relative and the split between color agent and color effect — the pigment you choose versus the sensation the audience gets. Then run small guided trials: watch a ground subtract its own hue and lightness from whatever sits on it, feel the eye generate complements through simultaneous contrast and afterimage, and test gray’s chameleon behavior on colored grounds. The how-to atoms carry the method: “Color paper isolates hue relationships from mixing and texture variables” tells you why flat cut paper (or flat digital fills) is the right medium, and “Arranging colors exclusively in stripes suppresses shape dominance” gives the layout that forces color, not shape, to do the talking.
The capstone withdraws the scaffolding: you must engineer the illusions yourself. Making one color read as two is pure ground subtraction; making two read as one demands calibrating a believable middle mixture until opaque paper reads as transparency — each required atom is a mechanism the plates cannot succeed without, and the annotations prove you can name what the eye is doing. Supporting atoms widen the frame: the darkest-on-top stacked-veil route to perceived transparency, illumination physics, pointillist optical mixture, film and volume color, edge softness, and the Bezold effect extend the same relational logic toward lit 3D scenes and full generative compositions.
Walkthrough
Albers’ Interaction of Color proves colour is never absolute — a swatch is defined by its neighbours. You’ll build his classic plates in code, where changing one number per ground engineers the illusion. Paste each sketch into the p5 web editor and press Run (▶). Each step is a complete, standalone sketch. View it full-size — the effects only work at scale.
1 — the ground subtracts. The founding demonstration: the same grey square looks lighter on a dark ground and darker on a light ground. The eye judges a colour relative to what surrounds it, then subtracts the ground — so identical values read as different ([[color-relativity-thesis]], [[color-ground-subtraction]]).
function setup() { createCanvas(400, 400); noStroke(); }
function draw() {
background(0);
fill(30); rect(0, 0, 200, 400); // dark ground
fill(220); rect(200, 0, 200, 400); // light ground
fill(130); rect(60, 150, 80, 100); // the SAME grey...
fill(130); rect(260, 150, 80, 100); // ...looks lighter on the left
}
2 — the ground casts its complement. A neutral grey on a coloured ground takes on a tint of that ground’s opposite — simultaneous contrast. Grey on red drifts green; grey on green drifts pink. The colour effect is generated by your eye, not present in the pixels ([[simultaneous-contrast-eye-generates-complement]], [[color-agent-vs-color-effect]]).
function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100); noStroke(); }
function draw() {
fill(0, 75, 80); rect(0, 0, 200, 400); // red ground
fill(140, 70, 70); rect(200, 0, 200, 400); // green ground
fill(0, 0, 60); rect(60, 150, 80, 100); // the SAME neutral grey...
fill(0, 0, 60); rect(260, 150, 80, 100); // ...tinted toward each ground's complement
}
3 — make one colour look like two. Albers’ first exercise. Pick two grounds and one swatch tuned so the ground subtraction pushes it in opposite directions — the single fill reads as two distinct colours ([[color-agent-vs-color-effect]]).
function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100); noStroke(); }
function draw() {
fill(200, 70, 90); rect(0, 0, 200, 400); // bright cyan ground
fill(200, 20, 35); rect(200, 0, 200, 400); // dark, desaturated ground
let swatch = color(200, 45, 62); // ONE colour
fill(swatch); rect(70, 160, 60, 80);
fill(swatch); rect(270, 160, 60, 80); // reads brighter on the right, richer on the left
}
4 — make two colours look like one. The harder inverse: two different swatches on two grounds, each nudged by its ground until they converge on the same apparent colour — the middle-mixture illusion ([[middle-mixture-illusion]]).
function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100); noStroke(); }
function draw() {
fill(45, 70, 90); rect(0, 0, 200, 400); // warm ground pushes its swatch cool
fill(215, 70, 70); rect(200, 0, 200, 400); // cool ground pushes its swatch warm
fill(130, 30, 75); rect(70, 160, 60, 80); // a greenish swatch...
fill(95, 30, 75); rect(270, 160, 60, 80); // ...and a yellowish one meet in the middle
}
5 — suppress the shape (stripe study). Interleave thin stripes and the shape disappears — the eye can only read the colour relationship, and the whole field shifts key as one stripe colour changes. This is the Bezold effect: one colour re-tunes the entire pattern ([[color-stripes-shape-reduction]], [[bezold-effect]]).
function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100); noStroke(); }
function draw() {
background(0, 0, 100);
for (let y = 0; y < height; y += 8) { // 400/8 = 50 stripe pairs
fill(30, 80, 85);
rect(0, y, width, 4); // the fixed stripe
fill(map(y, 0, height, 200, 40), 70, 80);
rect(0, y + 4, width, 4); // the changing stripe re-keys the field
}
}
6 — the plate (the capstone). One canvas, three effects: one-looks-like-two up top, two-look-like-one bottom-left, and a stripe study bottom-right. Each is engineered by choosing grounds that bend the swatches — a single set you could annotate effect by effect ([[illusory-transparence-opaque-paper]]):
function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100); noStroke(); }
function draw() {
// top: one colour reads as two
fill(280, 65, 85); rect(0, 0, 200, 200);
fill(280, 22, 34); rect(200, 0, 200, 200);
let one = color(280, 42, 60);
fill(one); rect(70, 60, 60, 80);
fill(one); rect(270, 60, 60, 80);
// bottom-left: two colours read as one
fill(45, 70, 88); rect(0, 200, 100, 200);
fill(210, 70, 72); rect(100, 200, 100, 200);
fill(120, 28, 78); rect(30, 260, 40, 80);
fill(95, 28, 78); rect(130, 260, 40, 80);
// bottom-right: stripe study suppresses shape
for (let y = 200; y < 400; y += 8) {
fill(30, 80, 85); rect(200, y, 200, 4);
fill(map(y, 200, 400, 210, 40), 65, 80); rect(200, y + 4, 200, 4);
}
}
What good looks like. A successful plate makes a skeptic look twice — the one-looks-like-two swatches should be provably identical (comment the fills to the same value) yet refuse to look it. The beginner failure is grounds too similar to their swatch, so nothing shifts; push the ground’s saturation and value further from the swatch until the illusion snaps in. Read every generative palette you build afterwards this way: a colour is only as good as the neighbours you give it. (Skill map: live-visualist Domain B2 — colour as a relationship, value contrast, seeing what the eye actually does.)
Now make it yours. Sample your own two grounds and hunt for the single swatch that reads as two. Animate the stripe study’s changing hue with frameCount and watch the whole field breathe. Build an illusory transparency: a swatch that looks like a translucent veil over two grounds. Feed the grounds from a [[generating-palettes-in-hsb|single-hue palette]] and test whether relativity still bites within one hue family.
Atoms in this module
Required — these gate the capstone
Supporting — enrichment, not gating
Part of curricula
- Live Visualist — zero to performing live-coded & generative visuals — See & sketch — training the eye and the first lines of code required
- Shader Artist — real-time GPU craft to a demoscene-grade visual — The fragment shader as a per-pixel instrument recommended
- VJ — visual performance with projection, light & video — See, source & mix: your first clip set recommended
Unlocks — modules that require this one