Crayon World 3D — our demo

One example among many. Don't reuse its story, arc, shots, props or timings.

Demo: The Butterfly (《蝴蝶》, 64.5 s) · crayon-world.mp4 · source in demo/

Style and demo by 2nd1st, contributed to Lemo-Opuscar in pull request #17.

Story & structure

An old woman has died. The film is her last visit, in first person: she wakes on a wild flower on the hillside above her village, flies down over the wheat and the roofs, over the bamboo fence into the garden she planted, and lands on one flower in the row. Her husband is watering the row with a long-handled ladle. At her flower he stops, looks down at it for a moment and doesn't pour; he waters the next ones, then looks back at it. Cut to his eyes: a yellow butterfly sits on that flower. It takes off toward the village and the hill, his gaze follows it up, and the page prints what he says: 等我哦。 / Wait for me.

What she is stays unseen for 44 s; nothing is explained. The clues are only flown past: fresh chrysanthemums in front of a stone on the hillside, her flowered straw hat on a nail by the door, a photo of the two of them on the windowsill.

Native moves spent: the camera is someone (0–43.8 s), passing, not pointing (the stone, the hat, the photo), wind (the flower she rides, the slope, the washing), cut to the other's eyes (43.8 s), blank paper for words (51–64.5 s).

Shots

# Time Shot Camera Native move / note
1 0–6.9 s wild flowers on the slope, close; she rides the head of one flower in the wind swaying with the flower; gaze from the flowers up to the slope below (0.9–3.6 s), then round to where she will fly (3.6–6.9 s) Wind; the sway settles by take-off
2 6.9–12 s take-off; the stone with chrysanthemums slides past on the left (8.5–10 s); the village swings in spline from rest; gaze direction lags (τ 0.3 s) Passing, not pointing
3 12–20 s down the hill path, skimming the wheat low skim, a butterfly's bob
4 20–30.6 s over the roofs; the bench under the big tree (slower); the washing line seen from six or seven metres
5 30.6–34.2 s over the bamboo fence into the garden; him watering the row; the house, hat and photo in passing; she lands on the 8th flower spline comes to rest on the flower head
6 34.2–43.8 s on the flower: he waters flowers 4 and 5, reaches hers (38.4 s), looks down without pouring, waters 8 and 9, looks back at it (42.5 s) sways with the flower; gaze follows him with a lag one breath of silence at 38.9 s
7 43.8–51 s cut to his eyes: the butterfly on that flower, wings slowly opening and closing; it takes off at 46.2 s and flies toward the village and the hill his eye height, fov 27°, gaze follows it (τ 0.32 s) and rises Cut to the other's eyes
8 51–64.5 s only a ragged strip of sky stays coloured; the rest thins to blank paper; 等我哦。 written in at 53.1 s, Wait for me. at 54.5 s; the butterfly becomes a doodle and is gone held on the sky above the roofs Blank paper for words

Score structure

D major, 3/4, 78 BPM (one bar = 2.308 s). Take-off (bar 3), the cut (19), the butterfly's take-off (20) and the words (23) land on bar lines.

Palette & props

End card

No separate card: the film ends on the printed words, held over the music box running down. On the last bar line (bar 26, 60.0 s, with the final strummed chord) the sign-off 2nd1st × LemoLab × Claude Opus 5.5 is written in on the same blank paper, letter by letter over 1.4 s in the film's own crayon type (Patrick Hand, 32 px, indigo line colour), right-aligned on the paper between the roof and the tree at the right (CREDIT, CR_AT in film.js); it holds to the end, 4.5 s. 2nd1st made this style and its demo. 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

sh styles/crayon-world/demo/build.sh

Fonts (if missing) → sample libraries (if missing) → tools/score.py → picture at 24 fps with core/render/video.mjs (≈ 1 min on an M-series Mac, 4 workers; WORKERS=2 for fewer) → mux.sh (−14 LUFS, no grain) → delivery encode → readcheck.mjs → poster at 32.5 s (over the fence into the garden) and four stills.

On a fresh clone: the fonts need the network (Google Fonts); the sample packs come from sh tools/fetch.sh instruments freepats, vcsl and vsco2ce (build.sh fetches any that are missing); three.js and playwright-core from the library's npm install, numpy/scipy/soundfile from its .venv.

File size: every drawing is new wax and paper texture, so at mux.sh's crf 19 the film is about 500 MB. build.sh therefore masters without added grain (the second frame of each drawing is then an exact repeat and costs almost nothing) and re-encodes the master with x264 -preset slow -crf 30, audio copied, to about 150 MB. Strokes, outlines and type keep their look; only the finest paper tooth softens a little. CRF=<n> changes it.

Waking on the slope Over the village On her flower, watching him His words

File What it holds
demo/engine/npr.js regions, the analysis render and ring tracing (STYLE.md §10)
demo/engine/crayon.js crayon line, scribble fill, dabs, type
demo/engine/gl.js the WebGL2 compositor: paper, wax adhesion, knock-out, emboss, vignette
demo/film.js the world, the camera route and gaze, his watering, the butterfly, the words, frame(t) and texts(t)
demo/main.js the page contract (render(t), DUR, TEXTS(t)); ?to=<s> renders only the start
demo/tools/score.py the score and foley, written to demo/out/mix.wav
demo/tools/fonts.py subsets Long Cang and Patrick Hand to the two printed lines and the sign-off (reads LINE, LINE_EN and CREDIT in film.js; needs the network)

Pitfalls tied to this demo: