Anamorph

cylinder mirror · from the viewpoint it was made for

Anamorph

What it is

Anamorph is an interactive catoptric anamorphosis, the mirror anamorphosis of the seventeenth-century parlour trick: a chrome cylinder standing on a sheet of paper, with a smear of ink on the paper that makes no sense until you look at its reflection, where it reads as a crisp picture. The first frame is the word HELLO and a red balloon, already baked onto the paper and already correct in the mirror, and it is the same picture on every visit. A small straight-on panel at the top right shows what the mirror shows, and that panel is where you draw: each stroke you sketch there lands on the paper as the exact inverse of the reflection, stretching and curling as it goes, while the cylinder keeps it straight.

Everything is drawn by one raw WebGL fragment shader on a single full-screen triangle, with no 3D library. Per pixel it intersects the eye ray with the mirror in closed form, either a cylinder one unit in radius and 1.75 high or a cone with a 25 degree half-angle, reflects, intersects the reflected ray with the paper plane and samples the paper, a 1024 by 1024 canvas uploaded as a mipmapped texture and patched region by region as you draw; rays that miss see a procedural room, the chrome gets a Schlick Fresnel term and one specular highlight, and the sheet a contact shadow beneath the mirror. Because the reflection is exact rather than a cube map, the picture stays right at every orbit angle for free. The inverse map, from a panel pixel through the home eye to the mirror and down onto the paper, lives in a plain TypeScript module with unit tests: a round trip through the forward reflection returns the panel pixel, a horizontal line in the panel becomes an arc on the paper, the cone map differs from the cylinder map, and every baked word lands inside the sheet. The baked picture is rendered 400 texels wide and stamped through that map, each inked texel drawn as the quadrilateral its corners map to; a brush stamp is the mapped rim of a ten-sided disc 1.4 percent of the panel's width in radius, laid down every half brush so a fast drag never leaves gaps. Without WebGL the same map is sampled in JavaScript at half resolution.

Drag on the mirror or the floor to orbit, or on anything but the panel in Orbit mode, and the mirror image bends and breaks, because the smear is only right from the viewpoint it was made for; the readout says how many degrees off-axis you are, and Reveal eases the camera home with a 0.32 second time constant, or cuts straight there under reduced motion. Scrolling zooms between 0.55 and 2.2 times the home distance, and the pitch is clamped between 6 and 90 degrees. In Draw mode a drag on the paper draws directly, and the cylinder shows what it makes of your line. Cone swaps in a cone seen from straight above, which turns the picture inside out: the panel's edge lands near the base and its centre far out, and a stamp on the apex is refused rather than smeared into a ring. Four ink chips take the page's text colour, its accent, and the red and green of the travel globe; Undo removes the last stroke, Clear blanks the sheet, and Reseed deals the next of six baked pictures in order: HELLO with a balloon, MONTE with a sun, LOOK with a boat, WHOA with a star, HIYA with a heart, PLAY with a sprout. The light and sunset themes are ink on a cream sheet with a bright chrome; the dark theme is chalk on slate with a steel cylinder reflecting a dim room.

How to use it

  • Sketch in the panel at the top right; the stroke lands on the paper already warped.
  • Switch to Draw and drag on the paper to see what the mirror makes of your line.
  • Drag on the mirror or the floor to orbit and break the picture; Reveal eases it home.
  • Try Cone: seen from above, the picture turns inside out around the apex.
  • Reseed deals the next baked word; Clear gives you a blank sheet.
WebGLGLSLOpticsRay TracingDrawingInteractive

More experiments

See every experiment