Dithering shader
I turn a continuously lit 3D helmet into ink and paper with a repeating 4 × 4 threshold screen.
The light stays continuous; the marks do not
A dot pattern has to preserve enough of the lighting for engraved edges and recessed channels to remain legible as an object turns. The shader samples a pixel block, computes Rec. 709 luminance and compares it with a Bayer threshold to choose ink or paper.
The 4 × 4 threshold screen.
A repeating 4 × 4 threshold matrix turns a continuous tone into ink marks. Change the mark size and shape to see how the same field gains a different rhythm.
Movement shares one rendering schedule
React Three Fiber and Three.js render the helmet, with a full-screen GLSL pass through the postprocessing library. A demand-driven scheduler coordinates ambient float, introduction and orbit motion.
Direct controls support mouse, touch and keyboard. Reduced motion stops automatic movement, and a static poster covers loading, WebGL failure and context loss.
The study runs in a browser
The shader study on this site lets a visitor examine the image directly. Arrow keys rotate the helmet. Home resets the starting pose. The standalone repository runs through Vite with npm ci and npm run dev, and includes the model, Draco decoder and poster.
The fallback is part of the experience
Method & limits: the helmet is a credited Royal Armoury scan, and the threshold pattern builds on Klems’s shader. The related site study and standalone app have different presentations.
I’d keep the controls and fallback as carefully designed as the shader. The image should still make sense when animation or WebGL is unavailable.