Risograph Print Risograph 丝网印刷
Sunday Ride·40s·Lemo-Opuscarby Lemomo
Animation that looks printed, frame by frame, on a stencil duplicator: two or three translucent spot inks overprinted on warm paper, halftone dots, ink grain, and plates that never quite line up.
The demo: A Sunday-morning bike ride through the city — bakery, park, riverside — in two misregistered inks.
Animation that looks printed, frame by frame, on a stencil duplicator: two or three translucent spot inks overprinted on warm paper, halftone dots, ink grain, and plates that never quite line up. References (grammar only): Tom Haugomat's riso illustrations (colour fields and silhouettes, a small figure in a large world, extra colours made by overprinting); Jacques Tati's Jour de fête (comedy staged small in a wide frame, everyday sounds as rhythm); real riso prints (translucent inks, misregistration, pinholes, feed streaks). Copy none of their characters, compositions or palettes.
1. Essence, and what it is not
A risograph prints one colour at a time: each colour is its own stencil ("plate") with its own drum of translucent ink. That one fact makes the look:
- A tiny palette: 2–3 spot inks on warm off-white paper.
- Overprint mixing: inks multiply, so two inks make a third colour and all three approach black; a tint of one ink over a solid of another gives the brightest mixes.
- Misregistration: every plate lands a few pixels off; edges show slivers of paper or a coloured halo.
- Halftone dots for mid-tones, each plate on its own screen angle; imperfect ink: pinholes in solids, streaks along the feed direction, blotchy density.
- Flat shapes, no outlines: forms are colour fields and silhouettes.
Not flat vector art with a noise overlay (every colour comes from the plates), not CMYK pop-art halftone (no process colours, no keyline), not screen-print posters (riso ink is translucent and grainy, not opaque). Never show the RISO brand, logo or machine trade dress; ink names are colour references only.
2. Materials & rendering
Pipeline. Draw each frame into one RGB canvas where each channel is one plate's density (R = ink 1, G = ink 2, B = ink 3; 0 = none, 1 = solid). source-over gives true knockouts; globalCompositeOperation = 'lighter' adds ink only to the channels you set: a true overprint. A WebGL2 shader "prints" it:
- per plate: offset in px + tiny rotation → misregistration;
- halftone: cosine spot function on a rotated grid, period ~6–8 px at 1080p, anti-aliased threshold; densities ≥ ~0.9 print solid; screen angles ≥ 15° apart;
- grain on the dot threshold, pinholes in solids, density varying with a feed-direction streak and a slow blot noise;
- composite
paper × Π mix(1, ink_i, coverage_i), with faint paper fibre; - dots anchored to the paper (screen), not to objects: a pan slides the image under a fixed screen, as if each frame were printed anew;
- a per-plate gate and a roller sweep (moving edge, slightly heavier ink band) let a plate arrive mid-shot.
Composition rules.
- Every area uses at most two plates, at most one of them as a tint. Three halftones on top of each other = mud.
- Big flat shapes, lots of solid paper and solid ink; halftone in a few stepped bands (e.g. 20 / 40 / 60 / 100 %) for skies, shadows, distance.
- Characters get a paper-white knockout halo (4–5 px): stamp their layer in a ring with
filter: brightness(0)(zero ink = paper), then draw them. Plates misregister around it, so it picks up coloured fringes like a real trap. - One horizon, one big flat field or disc, one small figure; the figure's head against the flattest colour in the frame.
- Design for the one-plate version: every main colour contains some of the first plate, so a one-ink frame still reads as a complete silhouette. A deliberate exception stays blank paper until its plate arrives: a reveal.
3. Colour logic
- 2–3 spot inks, never more, plus paper; every other colour is an overprint or a tint. No gradients except stepped halftone.
- Pick inks whose pairs mix into useful colours; at least one must carry a silhouette alone.
- Paper is warm off-white (around
#F4EEE2), never pure white; paper white is a colour too (knockouts, highlights, subtitles). - Light neutral surfaces (skin): a light tint of the palest ink. Dots of a saturated ink on skin look like a rash.
- Save the full overprint (every plate, densest mixes) for the moment that earns it.
- Example ink sets: Blue
#0078BF+ Yellow#FFE800+ Fluorescent Pink#FF48B0; Teal#00838A+ Fluorescent Orange#FF7477; Federal Blue#3D5588+ Red#FF665E+ Sunflower#FFB511.
4. Type & subtitles
- Type is printed: titles and subtitles live on one plate, so they misregister and grain with it. A title can be printed on two plates with a visible offset: the riso double-hit.
- Fonts (OFL): heavy grotesque for titles (e.g. Bricolage Grotesque 800), geometric sans for captions (e.g. Jost 500–700). Preload every weight before
READY. - Subtitles: a paper-white knockout strip (zero ink, small radius) with text on one plate, ~40–46 px; its edges catch misregistration fringes. Hold ≥ max(1.8 s, speech + 0.6 s).
- Prints don't fade: titles arrive with a roller wipe or on a beat and leave on a cut.
5. Motion quality
- Characters act on twos (12 fps); camera moves on ones (24 fps): a stepped camera reads as judder.
- Registration is not jittered every frame. One fixed set of offsets per shot (±1–3 px). A kick (≈ 8–14 px, decaying in ~0.25 s with slight ringing) on an accent; a drift up to ~25 px through a held moment, snapping back on the downbeat.
- Grain boils partly (about a third re-rolls per print); sheet streaks and blots change only at cuts.
- Simple cycles on few drawings; secondary motion (scarf, flag, tail) as a travelling sine wave.
6. Camera grammar
A vocabulary, not a route. Opening and ending come from the topic.
| Move | Expresses | Can serve |
|---|---|---|
| Wide lateral tracking, small figure, empty sky | Travel, routine, room | a commute; a process line; a title |
| Static wide, the subject crosses the frame | Comedy of scale | a gag; an arrival; a crowd |
| Locked composition: horizon, disc, figure | Stillness, awe | a decision; a reveal; the film's one pause |
| Ground-level low angle, big foreground shapes | Energy, abundance | a burst; a harvest; a launch |
| Medium two-shot held for a look | Reaction | a joke landing; a deal; a disagreement |
| Straight top-down, long shadows | Pattern, a map | a schedule; a floor plan; a game board |
| Push into a halftone field until dots are shapes | Entering the print | a close look at data; a memory; a cell |
| Pull back to reveal the paper | It was one sheet | a series; an archive; a summing-up |
| Match cut on a flat shape | Continuity through form | a time jump; cause and effect; before/after |
Framing: lots of paper and solid ink, text on empty sky or a knockout strip. Transitions: overprint growths, roller sweeps, shape match cuts, hard cuts on beats. Never a cross-dissolve, never a soft digital wipe.
7. Sound palette
- Instruments, as options: warm, dry, handmade, slightly lo-fi: upright or electric bass, vibraphone or marimba, nylon guitar, whistled or hummed melody, Rhodes, toy piano, brushed kit, shaker and rim clave, a small drum machine through tape saturation.
- Layering like plates (an option): each new plate brings one instrument, and they can leave one by one.
- The machine is the signature foley: feed "shhk", drum "ka-chunk" at a plate arrival, motor hum, a sheet landing on a stack, a guillotine cut. Other foley dry, close and papery, following the story's materials.
- Silence: a held bar with reverb tails cut, at most ambience or one distant sound; it pairs with a registration drift, and the snap brings everything back.
- Mix: dry and close; music ducks ~8 dB under voice; −14 LUFS. Voice relaxed and conversational, short lines, verified with whisper. No grain added at mux: it is in the print.
8. Native moves
A menu: use the ones your story needs.
- Plates as narrative. The world gains a plate at each turning point. Fits content like: a product arriving as a new ink; a city history, one ink per era; colour returning during a recovery.
- Two inks, a third where they meet. Fits content like: a merger; a duet; two data sets whose overlap is the finding.
- Overprint transition. A shape of one ink grows over the frame, turning everything beneath into the mix, then shrinks into the next scene's key shape. Fits content like: a pill dissolving; a spotlight becoming a moon; a stamp becoming a map pin.
- Registration as rhythm and feeling. Kicks on accents, drift in a held moment, snap on the downbeat. Fits content like: nerves before a speech; dizziness; a memory coming into focus.
- Reflections as separated plates. Each plate wobbles on its own phase. Fits content like: a shop window; heat over a road; a coffee surface.
- Knockout reveal. A shape made only of missing ink; its plate arrives later. Fits content like: a missing piece; a secret; a logo hidden in plain sight.
- Halftone scale. Dots grow into shapes as the camera pushes in. Fits content like: population; rainfall; a crowd that turns out to be people.
- It is a sheet of paper. The print can be stacked, folded, cut or pinned; grain boils like a flipbook of prints. Fits content like: a zine; a poster series; a flyer passed hand to hand.
9. Pitfalls of the medium
- Three halftoned plates in one area = mud → two plates, one tint.
fract(p*vec2(233.34,851.73))draws vertical stripes across solids at 1080p → a well-mixed hash (fract(vec3(p.xyx)*.1031)family).- Per-frame registration jitter and sheet streaks flicker and blow up file size → fixed offsets per shot, kicks on accents, sheet noise at cuts, partial boil.
- JPEG screenshots (4:2:0) smear saturated dots → PNG frames into a lossless yuv444 intermediate, encoded once with
-tune grain; check at 100 % and 50 % for moiré. - The halo layer must copy the canvas transform, or zoomed shots draw the subject at the wrong scale.
- Additive
over()inside a transparent layer loses its meaning → overprint on the plate canvas. - A main colour without the first plate floats loose in one-ink frames → build palette recipes up from the one-ink silhouette.
evenoddfills of arches fill solid → trace the inner edge in the opposite direction.
10. Engine
In demo/: riso.js (print shader: plates, halftone, grain, registration, kicks and drift, gates, roller sweeps, reflection wobble), draw.js (ink(b,y,p) densities, over() overprint, layer() paper halo, 2-bone IK, limbs), sheet.js (model sheet with a "plates = story" row via S.mask), tools/video_png.mjs (PNG frames → lossless intermediate), tools/mux.sh. Minimal new frame: two plates (R = teal, G = orange); a solid teal hill, an orange disc drawn with lighter so it darkens where it crosses the hill, a 40 % teal sky band, a figure knocked out with layer().
11. Variation space
You decide the inks and what each plate means, the structure, characters (or none), opening, ending, camera path and pacing. All far from our demo:
- Structures: two inks in dialogue (two subjects alternate shots and only overlap at the end, making the third colour); subtraction (start at full overprint, lose a plate at each loss, end in one ink); a zine (each shot a page turned, each page a different two-plate pairing).
- Openings: a knockout (a blank shape in a full-colour field, filled by its plate seconds later); dots first (extreme close-up of halftone that pulls back into an image); ghosts converge (three colour ghosts drift together and snap into a readable frame on the first beat).
- Endings: one ink left (plates lift away until the last line stands in one colour); the print on a wall (the last frame becomes a poster pasted up inside the world it showed); a folded sheet (the print folds into something the story needs: a boat, an envelope, a ticket).
How our demo was made (story, shots, score, end card, build): DEMO.md. Read it after your treatment exists.
Director's notes for the demo film
One example among many. Don't reuse its story, arc, shots, props or timings.
Demo: Sunday Ride (40 s) · risograph.mp4 · source in demo/
Story & structure
A lanky man in round glasses cycles across town on a Sunday morning to eat breakfast by the river. The city starts printed in the Blue plate only; each place he passes adds a plate: the bakery brings Yellow (a baguette handed over without him slowing down), the park brings Pink (a burst of pigeons, one of which hitches a ride on the baguette), and by the river all three plates overprint. He shares the bread with the pigeon; the camera pulls back and the whole film was one sheet sliding out of the printer onto a stack of earlier prints. Theme line: "Same ride every Sunday. Never quite the same print."
Arc (40 s = 20 bars of 2 s): quiet one-ink opening, hook inside 3 s (the ink being laid down) → each location adds a plate and an instrument → a small turn (the pigeon passenger) → full-overprint climax with a held silent bar → warm resolution (sharing) → scale reveal of the paper. One character, one goal, one turn.
Plate recipe for the story: first plate = the "before" state (the sleepy city), each added plate = a turning point, full overprint = the climax. Native moves spent: plates as narrative (Blue → Yellow → Pink), overprint transition (a pink disc swallows the park and becomes the river sun), registration as rhythm (kicks on the title, plate arrivals and the pigeon burst; a drift in the silent bar, snap on the downbeat), reflections as separated plates (the river), every frame a print (grain boil), it is a sheet of paper (the final pull-back).
Shots
| # | Time | Plates | Shot | Camera / note |
|---|---|---|---|---|
| 1 | 0–2 | B | Bell ECU | Blue plate rolled on left→right over handlebar and bell; thumb flicks the bell on the first beat (1.0) |
| 2 | 2–8 | B | Sleepy blue street | Wide lateral tracking: the figure small, the sky big and empty for the title (2.0–5.4); narration from 5.6 |
| 3 | 8–16 | B+Y | Bakery | Cut to medium tracking as Yellow sweeps across; the baker's hand offers the baguette at 11.3, caught without slowing at 12.0 (Tati's no-slowdown hand-off), staged at the rider's reach height, ahead of him, above the basket so nothing covers it |
| 4 | 16–19 | all | Park | Static wide as Pink arrives: let him cross the frame (Tati) |
| 5 | 19–21.5 | all | Pigeons | Ground-level low angle, pigeons big in the foreground; bell at 19.5, the flock bursts at 20.0 with a registration kick |
| 6 | 21.5–24 | all | Passenger | Medium close on rider + pigeon on the baguette for a two-beat look |
| 7 | 24–26 | all | Overprint transition | A pink disc grows from the basket, turns every blue beneath it violet, shrinks into the huge low river sun |
| 8 | 26–29 | all | River | Haugomat composition, locked off; he brakes and stops (the only moment he stops); silent bar, plates drift, snap back at 28.0 |
| 9 | 29–32 | all | Sharing | Medium side shot, the sun behind him; bread crack at 29.5, half to the pigeon at 30.5 |
| 10 | 32–36 | all | Top-down → pull back | Straight top-down with long shadows, then pull back to the paper coming out of the printer onto a stack of earlier prints (blue street, bakery, park visible underneath) |
| 11 | 36–40 | all | End card | Last bell at 38.0 |
Score structure
Original light bossa nova, D major, 120 BPM (1 bar = 2 s, so cuts land on even seconds), demo/music/score.py (numpy) + demo/music/bell.py. The music is layered like the plates: one ink = nylon guitar alone; + Yellow = shaker, rim clave, soft brushes (and the bicycle bell as percussion); + Pink = upright bass and a whistled melody; full overprint = + vibraphone. Bar 1 has no music (paper feed, drum, bell). A fully silent bar (reverb tails cut) under the climax drift (26–28) holds only water, birds and a distant church bell (it is Sunday) at 26.3; the full band returns on the snap at 28.0. During the pull-back the instruments leave one by one (vibraphone → whistle → bass → percussion), one per step of the pull-back; guitar and a held Dmaj9 over the end card.
Foley: the riso machine at every plate arrival (paper feed "shhk" + drum "ka-chunk"; motor and paper rub at the end; a soft paper landing at 39.5). Bicycle bell (two inharmonic partials ~2.1 / 3.4 kHz, 5 fast strikes per ring), freewheel ticks, brake squeal. Bread crust crunch (dense tiny band-passed clicks). Pigeon wings (short band-passed noise bursts), coo (gliding 300–400 Hz tone). Water lapping.
Voice: relaxed male narrator, Kokoro am_adam, speed 0.95, 5 short lines at 5.6, 9.0, 21.7, 28.3, 32.8, each verified with whisper. Music ducks −8 dB under voice; −14 LUFS; mux grain 0.
Palette & props
- Inks: Riso Blue
#0078BF(screen 15°), Yellow#FFE800(0°), Fluorescent Pink#FF48B0(75°) on paper#F6F1E6. Mixes: Blue + Yellow = green, Blue + Pink = violet/indigo, Yellow + Pink = orange-red, all three = near-black; 60 % Blue dots over solid Pink = purple. - Shader numbers: rotation ±0.0005 rad; halftone period 7 px at 1080p, threshold smoothstep ±0.07; solid at ≥ 0.9; grain ±0.08 on the threshold; pinholes where noise > 0.93 (×0.75); ink density
k = 0.80 + 0.14·streak + 0.08·blot(streak = noise stretched ×10 along the feed); paper fibre ±1.5 %; grain boil 35 %. - Sky bands 20 / 38 / 62 / 100 %. Paper halo 4–5 px, 12 stamps in a ring.
- The rider (plate densities): skin Yellow 26 % (cream; paper in the one-ink scene); sweater Blue 40 + Pink 100 (light blue dots → berry purple); trousers Blue 75 + Yellow 100 (→ olive green); hair Blue 100 + Pink 22; shoes Blue 100. The chunky scarf is Yellow + Pink only, so it is blank paper until the Yellow plate arrives and is the first thing to light up. His head sits against the sun disc at the river.
- Pedalling: crank angle from wheel travel (
crank = distance / wheelRadius / 2.2), legs by 2-bone IK to the pedals, scarf as a travelling sine wave. - Pigeons: about 1.2× his head size, round chest, tiny steps with a head bob, head tilts for "thinking", a 4-frame flap cycle (up / half / down / tuck) on twos; flocks mix sizes 1.2–2.4× and stagger take-off by up to 0.35 s.
End card
Subtitles: paper-white knockout strip, 6 px radius, centred 1000 px down, Blue text, Jost 500 42 px, 0.5 px tracking. Title card: "SUNDAY RIDE", Bricolage 800 190 px on the Blue plate in the sky, revealed by a left→right wipe on the first chord, removed on a beat.
End card: blank paper, the title double-hit in Pink + Blue (10 px offset), "RISOGRAPH PRINT", the credit line, registration crosshairs in the corners, and a tiny rider crossing the baseline while the bell rings. The "LemoLab × Claude Opus 5.5" sign-off belongs to this library's demo only; a user's film carries no LemoLab credit and no copy of this card.
Build notes
styles/risograph/demo/
riso.js WebGL2 print shader (plates, halftone, grain, registration, sweeps, water reflection)
draw.js plate-canvas helpers: ink(b,y,p), over() overprint, layer() paper-halo, IK, limbs
rider.js rider, bike, pigeon, baguette (all colours as plate densities)
scenes.js river, street + bakery scenes2.js park, top-down quay, printer, bell ECU
film.js timeline (120 BPM), shots, registration kicks/drift, plate gates, subtitles, sound events
sheet.js model sheet (?sheet=1) lines.json narration
music/score.py original bossa nova (numpy) music/bell.py bicycle bell
mix.py foley + ambience + ducked voice + score → mix.wav
tools/ video_png.mjs (PNG frames, lossless intermediate), mux.sh (crf16 -tune grain), subs.py
- Design the plates first: what the one-ink frame looks like and what each plate adds. The model sheet (
?sheet=1&v=2,demo/stills/modelsheet_v2.jpg) has a "plates = story" row: the same character with 1, 2, 3 plates viaS.mask. sh styles/risograph/demo/build.shrebuilds everything: TTS → whisper → score → events → mix → SRT → render (960 frames, ~2–4 min with 3 workers) → mux → style frame, poster, model sheet.- Review:
node core/render/still.mjs styles/risograph/demo --range 0:40:1.5+core/render/sheet.py; key actions at 0.2 s steps; the encoded film at 100 % and 50 % for moiré.
Encoding: PNG frames → lossless intermediate (qp 0, yuv444) → one encode at crf 16 -tune grain (~280 MB for 40 s); crf 20 without -tune grain is ~120 MB and still clean at 1080p and 50 %. Per-frame jitter + per-frame streaks had pushed x264 to 900 MB.
Pitfalls tied to this demo's props:
- The hand-off: the baker's arm is in the background plane and disappeared behind the rider → the exchange staged ahead of and above him.
- Bridge arches filled solid with
evenodd→ underside traced witharc(..., true). - The first design (lanky, round glasses, horizontal stripes) read as a famous picture-book character → solid knitwear and a different signature (the chunky scarf).
- Sweater and trousers without Blue showed a floating head in the one-ink opening.
- Pink dots on skin looked like measles → skin is Yellow only.



