Visualizations
331 / 500

331 · Simulation

Pigment Mixing

Blue and yellow paint make green here: spectral Kubelka-Munk mixing beside naive RGB.

Five real pigments (titanium white, cadmium yellow, quinacridone magenta, phthalo blue and ivory black) each carry absorption and scattering spectra sampled at 16 wavelengths from 400 to 700 nm. Every cell of the palette sums those spectra by concentration, Kubelka-Munk theory turns them into the reflectance of a paint layer over white paper (with a Saunderson correction for the glossy surface), and the spectrum is integrated against the CIE 1931 color matching functions under D65 daylight to get its color. The right panel holds the exact same paint but averages the pigments' RGB colors, so blue and yellow come out gray, magenta and yellow brown, and black and yellow merely dark yellow instead of olive. The brush trades paint with every cell it crosses, so colors smear and streak, and wet paint softly bleeds into its neighbors.

Try it. Drag out of any paint well to load the brush, then paint on either panel; both show the same strokes. The probe plots the reflectance spectrum under the brush with both swatches. Keys 1 to 5 (or W, Y, M, B, K) load a pigment, R rinses the brush so it only smears, [ and ] change its size, and the Demo chip replays the autopilot.

  • Kubelka-Munk spectral mixing
  • CIE 1931 color matching
  • Saunderson surface correction
  • Bidirectional brush paint transfer
  • Dirty-cell incremental rendering

View the source · one module, plus a small shared runtime for sizing, the animation loop and input

Build your own

Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.

Build a paint-mixing palette that mixes colors the way real pigments do, with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.

Start simple:
- Sample light at 16 wavelengths from 400 to 700 nm. Give each of four pigments an absorption curve K and a scattering curve S over those wavelengths, built from Gaussians and smooth steps: phthalo blue absorbs strongly above about 580 nm, cadmium yellow absorbs below about 490 nm, quinacridone magenta absorbs around 540 nm, titanium white barely absorbs and scatters strongly.
- Write a function that takes pigment amounts, sums K and S weighted by amount, and uses the Kubelka-Munk equations to get the reflectance of that paint layer over white paper at each wavelength.
- Convert a reflectance spectrum to a color: multiply by a daylight spectrum and the CIE 1931 color matching functions (an analytic Gaussian fit is fine), sum to XYZ, convert to linear sRGB, and apply the sRGB gamma curve.
- Make a grid of cells, each holding the four pigment amounts, and draw it with ImageData scaled up. Put a blob of each pure pigment along the top as a paint well.
- The brush carries a mixture. At every cell it passes, it gives some of its load to the cell and picks up some of the cell's paint, so colors smear and mix as you drag. Starting a drag inside a well loads the brush with that pigment.

Once that works, make it beautiful:
- Show a second panel with the very same grid, colored by a naive average of each pigment's RGB color, so you can see blue and yellow make green on one side and gray on the other.
- Only recompute the spectral color of cells that changed, so it stays fast.
- Add a small chart of the reflectance spectrum under the cursor, filled with the colors of the spectrum.

Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as adding ivory black to show that black and yellow make olive, a glossy surface correction for deeper darks, or lighting the paint by its thickness.
PreviousKakeya NeedleTurn a needle all the way around in a disk, a deltoid, then sprouting Perron trees. NextInterior MappingA night skyline of thousands of furnished, lit rooms, and not one of them has geometry.

Related visualizations

  • WatercolorGenerative art Pigment rides a shallow-water layer, pools at the edges and granulates on paper.
  • Chromaticity LabMath Draw any light's spectrum and watch it land on the CIE 1931 horseshoe.
  • Palette CyclingRetro A waterfall, harbor rain and an aurora, animated without changing a single pixel.
  • Checker ShadowIllusions Squares A and B are the exact same gray. Move the light and the shadow keeps lying.
  • Color ConstancyIllusions Strawberries under cyan light: not a single red pixel, and they still look red.
  • Soap FilmFluids A draining soap film swirls with true thin-film colors until it turns black and pops.
  • Dither LabRetro Seven dithering algorithms race on a moving scene in 1-bit, handheld green, CGA and EGA.
  • Discharge TubesPhysics Glowing gas tubes whose colors are computed from their real spectral lines.
  • Sumi-e BrushGenerative art A bristle-by-bristle ink brush paints bamboo on rice paper that wicks and bleeds.

Use ← and → to move between demos. While the canvas has focus, keys go to the demo instead.

← More from Emergent Mind Labs