Encoding Color Numerically: RGB, color spaces, and gamma
Learning objectives
- Learner can explain why RGB numbers are meaningless without a color space, and normalize/encode them correctly
- Learner can trace trichromacy → CIE matching functions → XYZ hub → chromaticity diagram, and read a gamut and white point
- Learner can perform color math in linear light, convert between spaces by matrix, and reason about gamut/HDR edge cases
Capstone — one whole task that evidences the objectives
Build a small color-space toolkit in code: normalize RGB, linearize using the sRGB TRC, convert linear RGB↔XYZ via a matrix derived from primary matching, plot the working gamut on the xy chromaticity diagram with its white point, and demonstrate one out-of-gamut/extended-range case — all annotated with why each step must happen in linear light.
Prerequisite modules
Every live-coded visual ends as three numbers per pixel, and on a real rig those numbers get reinterpreted constantly: a vec3 in your shader, an sRGB PNG texture, a projector with its own primaries, an HDR-capable LED wall. When a gradient goes muddy mid-set or a palette shifts between your laptop and the venue screen, the cause is almost always color math done on encoded values or numbers moved between spaces without conversion. This module builds the whole task of a working color-space toolkit — the code you will lean on every time you blend, fade, or port visuals across displays.
The arc starts supported and concrete: first internalize that “RGB numeric values have no meaning without a color space” and drill normalizing 0–255 palettes into the 0.0–1.0 floats shaders expect. Then follow the science upward — trichromacy explains why three numbers suffice, the CIE color matching functions show how that was measured, and CIE XYZ emerges as the device-independent hub. With “matching pure primaries individually” as your JIT procedure and Grassmann’s laws as its license, you derive a 3×3 conversion matrix yourself rather than pasting one. The sRGB piecewise TRC and the principle that color arithmetic must happen in linear light become the habits you re-apply at every step, until the unsupported capstone — toolkit, gamut plot with white point, and one out-of-gamut or extended-range demonstration — needs no scaffolding.
Required atoms are exactly what the capstone cannot ship without: encoding, the XYZ pipeline, matrix derivation, and the edge-case concepts (negative primaries, extended range) your demonstration must exercise. Supporting atoms enrich judgment — why magenta is a brain construction, why the xy diagram lies about distance, why perceptual encoding exists at all — deepening the annotations without gating the build.
Runnable examples
Generated from the context/ instrument corpus by concept (redistributable idioms only). Do not edit — regenerate with gen-module-examples.mjs.
palette-cycle
osc(30, 0.1, 1).colorama(0.1).out()
hydra-0015 · CC0-1.0
hsvrgb [fract (ft/6.28 + 0.1*time), 1, 1] >> rgb
punctual-0024 · CC0-1.0
gamma-correction
col = pow(col, vec3(1.0/2.2));
glsl-0021 · public-domain
pow ([lo,mid,hi]) 0.4545 >> rgb
punctual-0034 · CC0-1.0
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 — Generative canvas — colour, motion, and Hydra live-coding required
- Shader Artist — real-time GPU craft to a demoscene-grade visual — The fragment shader as a per-pixel instrument recommended