Reveals · effect

HalftoneReveal

A picture arriving dot by dot, the way a halftone comes up on press.

press replay to run it again

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

paper #fbfaf4

css colour

Shown wherever a dot has not grown yet, which at the start is the whole frame. Match it to the page behind or the reveal begins as a visible panel.

screen 14

4 to 48

Cell size in CSS pixels. Bigger cells are a coarser screen and a more obviously printed arrival. Laid out in pixels rather than in UV so the dots stay round and keep their size when the element changes shape.

angle 45

0 to 90

Screen angle in degrees. 45 is the one a printer reaches for, because a screen on the square reads as a grid and fights whatever is underneath it.

sweep 24

0 to 360

Direction the reveal travels, in degrees. 0 runs left to right. Only visible when scatter is below 1.

scatter 0.55

0 to 1

0 is a clean directional sweep, 1 is a random dissolve with no direction at all. Between the two the sweep keeps its direction but its leading edge is ragged, which is the part worth having.

feather 0.55

0.05 to 1

How much of the reveal has cells part way through at any one moment. Low is a hard edge travelling across; high has the whole frame coming up together.

grain 0.4

0 to 1

Paper tooth over the whole thing.

duration 1800

200 to 8000

Milliseconds from blank paper to the finished picture.

What it needs

Dependencies
None at all
Browser
WEBGL2
Frame budget
~0.6 ms · 1 context
Pinned to
v0.8.0
  • The picture is the host element's own <img> child. It is hidden from sight and left in the document, so the alt text is whatever you wrote and a page with no JavaScript still shows it
  • renderAtTime is pure in t, so replaying is a matter of resetting the clock rather than restarting anything
  • One WebGL2 context, one full-screen triangle, no buffers and no attributes
  • One texture read and one hash per pixel. There is no loop and no second pass
  • The image uploads once, on load. Nothing is uploaded per frame
  • The screen is laid out in CSS pixels, so the cost is per pixel and does not change with the cell size