THE PIXEL LAB

Keith & Claude teach a screen to paint with random dots — July 2026

Every picture below is a live program. Press RUN and it computes in your browser.

This page is drawn from a real working conversation between Keith Stein and Claude. The idea was simple: control every pixel of a 707 × 300 screen with one BASIC-style command — PSET x, y, r, g, b — pick points at random, colour each by a rule, and see what worlds emerge. The dialogue is abridged; the programs are the originals.

1 · A circle from dice

KEITH: x = RND*200-100 : y = RND*200-100 : R = SQR(x^2+y^2) — if R < 80 then PSET red, else PSET blue. Loop till keypress. I'm hoping for a red circle of radius 80 on a blue square, centred on 0,0.
CLAUDE: Your program's sound — and note your own colour formulas do more than you asked: the red brightens outward (R×3), the blue fades outward (255−R). Watch it stipple in.
0 points

Monte Carlo painting: no line of code ever “draws a circle” — the circle is a statistical fact about 200,000 independent dice rolls.

2 · Time enters: rippling rings

KEITH: If I want to change colour with time, can I use Ti for seconds from start? Then let's try g = 100*SIN(R − 4*Ti) + 110.
CLAUDE: Constant colour follows R = 4·Ti + const — green crests marching outward at 4 pixels per second. And a subtlety of the random-dot method: a pixel only changes when the dice revisit it, so instead of rings gliding smoothly you get a churning, shimmering wavefront — like sunlight on rippled water.
Ti = 0.0 s

Red disc, radius 80; green gun rippling with time; blue fading with radius. Three guns, three different functions, one screen.

3 · The DJ deck: your pointer, your clicks, your line 160

KEITH: Can one of the sources follow my mouse? And when I click, I want a large step change.
CLAUDE: Two ripple sources, waves added: A = SIN(R1·K − S·Ti) + SIN(R2·K − S·Ti). Your pointer is source 1. A click is a drum hit: wavelength K, speed S, palette and the second source all jump to new random values — but the screen doesn't jump, the new picture soaks in through the old at the repaint rate.
KEITH: First thing I tried was multiplying the sines instead of adding. The patterns remind me of magnetic fields — what does multiplying represent physically?
CLAUDE: Sum is interference; product is modulation. sin A·sin B = ½[cos(A−B) − cos(A+B)]: the first term freezes into stationary hyperbolae (the fringe skeleton), the second travels along ellipses sharing the same two foci — and confocal ellipses and hyperbolae always cross at right angles. Your eye recognised the orthogonal grid of a field diagram before the algebra did. It's also how every radio mixer has worked since the 1920s.
160 A =
pointer = source 1 · CLICK canvas = drum hit · K=0.35 S=6.0

Try: SIN(R1*K - S*Ti) * SIN(R2*K - S*Ti) (Keith's discovery) · SIN((R1-R2)*0.2) · SIN(SQR(ABS(x*y))*0.3 - 2*Ti). Mistype and the last good line keeps running.

4 · The Longest Day

KEITH: Next a horizon: IF y > 10 THEN sky blue ELSE green. Then Claude offered a sun, depth-shaded grass, a sky gradient, a sunset… I said put them all in, eh!
CLAUDE: A complete day in Monte Carlo dots. Everything is still just IF-tests on each random pixel: sun first (clipped by the horizon — occlusion for the price of moving an IF), then sky with a sunset term that peaks when the sun's altitude nears zero, then ground brightest at your feet, and 120 fixed stars painted only when daylight fades.
60s

Watch a sunset: for a few seconds the orange sky, the reddened sun and the first stars all coexist in the churning dots.

5 · Into 3D: ripples on water, in perspective

KEITH: Instead of grass I want flat WATER stretching to the horizon — and those 2D ripples on it, seen in 3D. I'm thinking about transferring our 2D skills to 3D. And my pointer drops the pebble.
CLAUDE: The classic graphics leap. Every screen pixel below the horizon maps to a point on the flat water by perspective inversion: depth Z = 3000/(horizon − y). The wave physics stays exactly 2D — same sin(kR − ωt) — only the viewpoint changed. Circular ripples become flattened ellipses, tighter toward the horizon, just as a standing eye sees a pond. Skate your pointer near the horizon and feel the nonlinearity: tiny screen moves, huge world distances.
you: X=−60 Z=120

Screen → world → physics → screen. The same in/compute/out architecture as a planetary ephemeris.

6 · Solid geometry: the cube convoy

KEITH: A cube of side 10 at the origin, viewed from wherever I say. Then colour its visible faces with light at a known position, while it rotates. Then ten of them, spinning on one steady axis, moving away…
CLAUDE: Everything runs on the four Judy Number operations: subtraction and modulus aim the camera, a cross product builds its screen axes, one dot product culls faces turned away, another is Lambert's law — brightness = N·L. With ten cubes the painter's algorithm sorts far-to-near so near paint lands on top, and each cube's dot ration scales as 1/Z² to match its screen area. Sunlight here is directional — uniform everywhere — so the convoy stays legible right down to the last few pixels.
cubes: 0/10

Six coloured faces read the rotation for you. A new cube launches every 2.5 s; each recycles from the deep at Z = 1800.

7 · Fractals: the deepest picture from the shortest program

KEITH: I want a fractal program written in a few lines of BASIC, with the crucial line editable. And zoom on the mouse wheel — and the changes gradual, the clicked point gliding slowly to the centre.
CLAUDE: Line 60 is the whole universe — z → z² + c written in real and imaginary parts: XN = x*x − y*y + CX : YN = 2*x*y + CY. Everything else is bookkeeping. Each pixel asks: starting from zero and applying that line over and over, do I escape to infinity or stay bounded? The black interior never escapes; the coloured bands record how fast each point fled — contour lines of escape time, crowding infinitely toward the boundary.
KEITH: Wondering if writing the whole screen from Xmin to Xmax in one double loop might beat our random dots, which are bound to take longer…
CLAUDE: Dead right — random darts pay the coupon-collector's tax, about 15 visits per pixel to cover them all, and fractal pixels are expensive. The systematic sweep visits each exactly once. And with the formula hard-wired (no editable line), the browser's compiler fuses the loop into machine code — the whole 212,000-pixel screen repaints tens of times a second. Scan for stills and speed; dice for shimmer. The Lab keeps both.

First the thoroughbred — fixed formula, full screen every frame. Wheel to zoom in fine steps, click to glide there, rotate and spin at will. Keith's green gun, G = 120 + 120*COS(n*π), zebra-stripes every contour of the escape count:

90° zoom 1× · ms

Zoom to ~10¹³× and the picture goes blocky, then trembles: you have reached the floor of the machine's 16-digit arithmetic — the number line, as the computer knows it, is not a continuum.

And the tinkerer's version — slower, because every iteration passes through your editable lines, but lines 60 and 100 are yours. Ti (seconds since RUN) works in all of them:

60 XN = : YN =
100 R = : G = : B =
Ti = 0.0 s · zoom 1× · wheel zooms, click glides

The default line breathes — COS(Ti/50) sweeps the whole family of related fractals, returning to the true Mandelbrot every ~5 minutes. Try the Burning Ship: YN = 2*ABS(x*y) + CY — one ABS, and the depths fill with straight-line rigging. Cubic: XN = x*x*x - 3*x*y*y + CX, YN = 3*x*x*y - y*y*y + CY. Rotate 90°: XN = x*x - y*y - CY, YN = 2*x*y + CX.

What the Lab taught us, in one paragraph. Two ways to spend the dice: pick a random screen pixel and ask “what's here?” (scenes 1–5), or pick a random point on an object and project it to the screen (scene 6) — ray-tracing's outlook versus the graphics card's. Perspective is two lines: Z from height, X from Z. Occlusion is an IF. Lighting is a dot product. And the whole 3D engine — camera, culling, shading — is subtraction, modulus, dot and cross on Judy Numbers J = x + iy + jz. And one iterated line — z² + c — holds infinite depth, until the machine's own sixteen digits run out beneath you.