Urban Sketch · Pen & Wash 钢笔淡彩

Where the Wind Went·32s·Lemo-Opuscarby Lemomo

A sketchbook page drawn on location: fine sepia fineliner lines that wobble, overshoot and never quite close, with loose transparent watercolour dropped on top. The colour sits slightly off the lines, spills over them, and dissolves into cream cold-press paper at the page edge.

The demo: A park that is only a pen sketch; wherever the wind carries her straw hat, colour follows.

City & travelArchitectureLifestyle brands
Style prompt · STYLE.md

A sketchbook page drawn on location: fine sepia fineliner lines that wobble, overshoot and never quite close, with loose transparent watercolour dropped on top. The colour sits slightly off the lines, spills over them, and dissolves into cream cold-press paper at the page edge. References (grammar only):

  • Urban-sketching sketchbook pages: line first, then wash; colour off-register; handwritten date and place in the corner; the page edge breaking up into dabs.
  • Paperman (2012): a monochrome world with one coloured object.
  • The Red Balloon (1956): an object as the protagonist, the camera following it across a city.
  • Jazz waltz (the Vince Guaraldi school): 3/4 swing, walking bass, brushes, a woodwind lead.

Nothing is copied from these: no characters, melodies, layouts or type.

1. Essence, and what it is not

Reportage drawing, made on location in a few minutes. Two layers that stay visibly separate:

  1. Ink. One thin, near-constant line (a 0.3–0.5 mm fineliner) in dark sepia. It wobbles slightly, overshoots corners by a few pixels, breaks mid-stroke, and suggests rather than describes: a few window marks instead of a grid, scalloped fragments instead of a whole tree outline.
  2. Wash. Transparent watercolour glazed on top, misregistered by 1–3 px from the line, sometimes spilling past it, leaving paper white for highlights and figures (reserves). Dried edges are darker (pigment pools at the rim), and pigment granulates into the paper tooth.

The page is part of the image: warm cream cold-press paper with large-scale mottling and fine tooth. Nothing is painted edge to edge; the painting frays into leaf-sized dabs and white holes, leaving margins for handwriting.

Not Watercolor Brush (no line-free wet-in-wet painting, no painterly edges without ink), not Whiteboard (no marker, no explainer diagrams), not Chinese Ink Wash (no brush calligraphy, no monochrome ink tones). Line and wash, both, always.

2. Materials & rendering

  • Paper: two octaves of fbm mottling (a few %), a tooth tile multiplied over everything, figures included.
  • Ink: ~96 % coverage; world line width thinner far, thicker near (e.g. 1.3–3.4 px); wobble ~1 px; overshoot 3–8 px; a third to half of long strokes get one small gap. Strokes are baked with their draw time per pixel, so the shader plays back stroke order.
  • Wash: 2–3 rough-edged layers, multiply, alpha ~0.4–0.65, offset from the line by about one line width, a dried edge at 30–40 %; granulation = pigment × (0.82 + 0.36 · fbm).
  • Colour arrival field: every pixel has a time at which colour reaches it. The wash is revealed through it with a ragged wet front (darkened band just behind the front) and noisy edges. Figures bloom from a point with a noisy circular clip.
  • Foliage: pale base wash, then light and shadow masses, then small leaf dabs coloured by light direction, holes at the rim, scalloped ink only on the outline.
  • Sky: a few big soft washes at low alpha, fading upward; clouds are reserves with a tinted belly.
  • Buildings: local colour; shadow side mixed ~45 % with a cool violet-grey; distant blocks mixed ~50 % with a haze colour.
  • Figures: a 3D skeleton in orthographic projection; torso from cross-sections; limbs as organic tapered tubes; hair and head as one mass; face left blank (one nose tick in profile); shadow side mixed with violet.
  • Page edge: a noisy boundary, a white-dab band inside, a coloured-dab spray outside.
  • Deterministic: same seed, same marks.

3. Colour logic

  • Ink is one colour (dark sepia or warm black); it never changes.
  • Wash is local colour, lightly: few pigments, mixed on the page; shadows are the local colour mixed toward one shared cool violet; distance mixes toward one haze.
  • Paper white is the brightest value; it is reserved, never painted.
  • Colour can be withheld: a page may be ink-only with colour as an event (one tinted object, colour arriving with a cause).
  • Example palettes: park in summer (lawn #c3c96f, leaves #7fa04a, sky #9fbcd6, limestone #d8c6a0); harbour morning (sea #7fa6b8, hulls #c9573f, rope #c8a86b, sky #bcd0dc); winter market (roofs #8b93a6, lights #e2b04a, awnings #b8483e, snow = paper).

4. Type & subtitles

  • All text is handwriting on the page, written on left to right with pen sound, and moves with the camera: a corner note (e.g. Reenie Beanie: day, time, weather, place), titles and colophon in a casual hand (e.g. Caveat 500–600), left-aligned in the blank margin.
  • Subtitles, if there is a voice: handwritten lines in the page margin or a caption strip written into the lower margin, never a generic overlay box. Hold ≥ max(1.8 s, speech + 0.6 s).
  • The style works well without any voice.

5. Motion quality

  • Figures boil at 12 fps (line wobble and wash seeds change every 1/12 s). The static page does not boil (it is a real page); the camera moves every frame, smoothly.
  • Performance: anticipation, action, follow-through; footsteps on the beat.
  • Invisible forces are drawn: wind as ink curls that draw on and erase from the tail, trailing dabs; sound as ink lines; heat as wavy strokes.
  • Colour never snaps: it blooms from a point or arrives through the field.
  • Stroke-order draw-on for anything that "appears".

6. Camera grammar

A 2D camera over a large page (e.g. 5120 × 2880). Designed moves use cubic easing; follow shots use a critically damped spring on a lead-ahead target, so the camera lags like a hand-held follow. A vocabulary, not a route. Opening and ending come from the topic.

Move What it expresses Can serve
Push-in attention; a detail observed a face; a sign; a small event
Lateral follow on a spring travel, pursuit an object carried; a walker; a vehicle
Crane up a new level, a view opening a skyline; a tree; a balcony
Whip-tilt with slight roll sudden change of direction a fall; a gust; a surprise
Punch-in with a short shake impact a catch; a collision; a door slam
Pull back to the whole page scale; the sketch as an object a summary; a place in full
Tilt into the margin from picture to words notes; a date; a title
Slow pan across a line-only area the world before colour a quiet start; memory
Hold while the pen draws the act of noticing a subject being drawn
Page turn to a new spread another time or place a travel diary; a sequence of days

Framing: subjects ≥ ⅓ of frame height at story beats; a small key object gets a faint paper halo (reserve) so it reads over busy foliage. Transitions: camera travel on the page, page turns, or colour arriving; no dissolves.

7. Sound palette

  • Ambience from the place: paper room tone first, then the location once it has colour (birds, traffic, harbour gulls, market chatter). J-cut a place's sound a bar before we see it.
  • Pen on cold-press paper: band-passed noise (~1.6–7.5 kHz) with a fibre texture and grain clicks, one burst per real stroke; thousands overlap into a hiss during a fast sketch; brighter short strokes read like a hi-hat.
  • Water and brush: a wet brush "shhh" for blooms, a jar rinse, a drip.
  • Foley follows objects at sketch scale: fabric or paper flapping for things in the wind (rate and level from speed, pan from screen x), steps on the beat, bells, splashes.
  • Music families: a jazz waltz (walking bass in three, brushes, piano, clarinet or flute); a café accordion trio; solo nylon guitar; a string quartet pizzicato; a brass band for crowds. One colour instrument per area of the page works well.
  • Silence as a tool: a bar of true silence (ambience included) at the height of suspense; the first sound after it is the next gesture.
  • Mix: music ducks under key hits; foley high-passed ~90 Hz; −14 LUFS, moderate LRA.

8. Native moves

A menu: use the ones your story needs.

  • Line before colour. The pen draws a subject in real stroke order, then the wash drops in; the drawing is the spectacle. Fits content like: a cathedral façade; a chef plating a dish; a street musician.
  • Colour as arrival. Wash spreads from a source with a wet front, so an event paints the page; figures stay frozen line drawings until colour touches them. Fits content like: a sunrise over a harbour; a parade moving down a street; the lights of a market switching on.
  • The one coloured thing. A colourless sketch with a single tinted object that becomes the protagonist. Fits content like: a red umbrella in the rain; a yellow taxi; a child's kite.
  • The page as frame. Pull back until the whole page shows, edges dissolving, handwritten notes in the margin. Fits content like: a travel diary entry; a neighbourhood portrait; a day in a place.
  • Carrot people. Distant crowds as one wash blob, two leg lines and a head dot. Fits content like: a station at rush hour; a stadium; a beach.

9. Pitfalls of the medium

  • Straight edges in the colour field from clipping by a bounding box → clip by the actual noisy distance.
  • Rectangular masks around complex silhouettes leave notches → mask with the real stepped silhouette.
  • Characters losing colour when they move into unpainted areas → sample arrival once (or tie it to the event), never at the current position.
  • Static ink can't be occluded by later washes → erase far ink inside nearer shapes before drawing; use carrot people for far crowds.
  • IK feet pinned while blending poses splay the legs → blend foot targets toward under-hip.
  • Front-facing heads go bald → draw the hair mass, then knock the face out of it.
  • Big canvases in headless Chrome: pack ink and time into RGBA byte textures yourself and upload the arrival field as a filterable float texture (R16F).
  • Painting edge to edge kills the sketchbook feel → leave margins and fray the edge.

10. Engine

demo/engine.js (deterministic): penStroke + drawPen (fineliner with wobble, overshoot, gaps, draw-on), rasterPen (bakes stroke order into an ink + time layer), wash, reserve, dab / foliage, arrivalField (colour arrival per cell from sources), compositor (WebGL page: paper × wash revealed by arrival × ink revealed by stroke time), figure + drawPrims (sketched people), sketchShape (any shape in this style in one call), handwrite. demo/poses.js holds a pose library. API table and a minimal example that draws something new: DEMO.md.

11. Variation space

You decide the place, the subjects, what colour does (always there, withheld, arriving), the voice (or none), the music family, the camera path, the opening, the ending and the length.

All far from our demo:

  • Structures: a travel diary of five pages, one per day, each page turned by the wind or a hand; a single street corner drawn at four times of day, the wash changing while the ink stays; a recipe where each ingredient is drawn from life at the market and the final dish is painted last.
  • Openings: the blank page with only the handwritten date, then the first line of the horizon; a close-up of a coffee cup on the page's edge, pulling back to find the city drawn behind it; rain dots landing on the paper and blooming into the first washes.
  • Endings: the sketchbook closes on the page; the last figure walks off the page into the blank margin; the colour drains back to ink as the evening comes, leaving one lit window.

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: Where the Wind Went (32.4 s, 1920×1080, 24 fps, no voice-over) · urban-sketch.mp4 · source in demo/

The original header: a sketchbook page from the park bench: fine sepia fineliner lines that wobble, overshoot and never quite close, with loose transparent watercolour dropped on top. The colour sits slightly off the lines, spills over them, and dissolves into cream cold-press paper at the page edge.

Story & structure

A park exists only as an ink sketch, and the only colour on the page is a straw hat. A gust steals the hat, and the page gets painted wherever the wind carries it.

The original "what the style is" notes with the demo's exact colours: paper #f5eede, ink #2b2520.

Reportage drawing, made on location in a few minutes. Two layers that stay visibly separate:

  1. Ink. One thin, near-constant line (a 0.3–0.5 mm fineliner), dark sepia #2b2520. It wobbles slightly, overshoots corners by a few pixels, breaks mid-stroke, and suggests rather than describes: a few window marks instead of a grid, scalloped fragments instead of a whole tree outline.
  2. Wash. Transparent watercolour glazed on top. It is misregistered by 1–3 px from the line, sometimes spills past it, and leaves paper white for highlights and for figures (reserves). Dried edges are darker (pigment pools at the rim), and pigment granulates into the paper tooth.

The page itself is part of the image. The warm cream #f5eede cold-press paper has large-scale mottling and a fine tooth. Nothing is painted edge to edge: the painting frays into leaf-sized dabs and white holes, leaving a blank margin for handwriting.

Stories the style was pitched for, and the native moves the demo used (line before colour for the sketch spread and skyline; colour as arrival driven by the gust; the one coloured thing = the straw hat; the page as frame for the ending):

Good for: travel diaries, city portraits, a day in a place, "the moment I noticed…", slice-of-life, gentle comedy with small figures, anything that benefits from feeling observed and handmade.

Native moves (only this medium does them):

  • Line before colour. Show the pen drawing a subject stroke by stroke (in real stroke order), then drop the wash in. The drawing process is the spectacle.
  • Colour as arrival. Every pixel has a colour arrival time. Wash spreads outward from a source with a ragged wet front and a dark tide line, so you can paint with an event (wind, a runner, music, a sunrise). Figures stay frozen line drawings until colour touches them, then start moving.
  • The one coloured thing. Open on a colourless sketch with a single tinted object; it becomes the protagonist.
  • The page as frame. Pull back until the whole page is visible, edges dissolving, with handwritten title and notes in the margin. This works as an end card and a scale reveal in one.

Shots

A 2D camera over a 5120×2880 page (the final pull-back shows it 1:1 at 0.375×).

  • Designed moves use cubic easing. Follow shots use a critically damped spring on a lead-ahead target, so the camera lags like a hand-held follow (stiffness 28, or 70 for the fall).
  • The demo uses push, pull, lateral follow, crane-up, whip-tilt with a slight roll, a punch-in with a 0.35 s shake on impact, a long pull-back, and a tilt down into the margin.
  • Keep subjects at least one third of frame height at story beats; the hat gets a faint paper halo (reserve) so it reads over busy foliage.

Motion as used in the demo

  • Figures boil at 12 fps: line wobble and wash seeds change every 1/12 s. The static page does not boil (it is a real page); the camera moves every frame, smoothly.
  • Figures keep anticipation, action and follow-through: a crouch before standing, a lunge and stumble on a miss, a prone slide after a dive. Footsteps land on the beat (run cycle = 2 beats).
  • The wind is drawn: ink "~@" curls spawn behind the hat on every beat, draw on in 0.4 s, then erase from the tail; leaf dabs trail the hat.
  • Colour never snaps. It blooms from a point with a noisy circular clip (figures) or through the arrival field (the world).

Score structure

Three layers; no voice-over.

  • Ambience: paper room tone → park birds (after colour arrives) → a low city hum that comes in a bar before the skyline (J-cut). Everything drops out for the silent bar.
  • Foley: pen on cold-press paper (band-passed noise, 1.6–7.5 kHz, with a fibre amplitude texture and grain clicks, one burst per real stroke; thousands overlap into a hiss during the sketch spread; skyline strokes are brighter and read as a hi-hat); a wet brush "shhh" for every big bloom; wind J-cut from the right channel; the straw hat as paper flapping whose rate and level follow its speed and whose pan follows its screen x; steps on the beat; bike bell; dive, slide, catch slap and water plop.
  • Music: 150 BPM jazz waltz in F: Sneakybass walking in three, synthesized brushes plus pedal hi-hat, upright piano on beats 2–3, a clarinet lead, muted trumpet for the city, pizzicato ostinato, vibraphone and marimba stabs where trees burst, and a floating D♭maj7♯11 at the apex, followed by one bar of true silence. The first sound after it is a chromatic clarinet fall with timpani; the catch lands on a tutti downbeat.
  • Mix: music ducks under the catch; foley high-passed at 90 Hz; −14 LUFS, LRA 7.

Palette & props

Element Value
Paper #f5eede; mottling fbm at 0.0011 and 0.0062 cycles/px, ±4.5 %; tooth tile multiplied on top of everything, figures included
Ink #2b2520 at 96 % coverage; world line width 1.3–3.4 px (thinner far, thicker near); wobble 0.9–1.3 px; overshoot 3–8 px; 30–60 % of long strokes get one 3–9 px gap
Wash 2–3 rough-edged layers (edge noise 4–12 px), multiply blend; alpha 0.4–0.65; offset from line by 0.7–1× line width; dried edge stroke at 30–40 %
Granulation pigment × (0.82 + 0.36 · fbm(p · 0.21))
Wet front reveal smoothstep over 0.16 s of arrival time; front band darkened +70 % (Gaussian at +0.07 s, σ 0.08 s); edge noise ±240 px coarse + ±40 px fine
Foliage pale base wash (sun #d6d56f), then light and shadow masses, then 5–20 px leaf dabs coloured by light direction: #d6d56f → #aabf57 → #7fa04a → #56793c → #3f5d36; holes at the rim; scalloped ink fragments only on the outline
Sky a few big soft ellipses of #9fbcd6 / #86a6c8 at 10–20 % alpha, fading upward; clouds are reserves with a #b7b3c9 belly
Buildings limestone #d8c6a0, ochre #cfaa72, glass #98b1c8, brick #c49a7a; shadow side = colour mixed 45 % with #5a5f82; distant blocks mixed 50 % with haze #b9c0cc
Lawn and path #c3c96f / #dcd98b light bands, #7f9c52 shade dabs; path #d8ccb1; grass = 2–4 ink flicks per tuft, denser near the camera
Figures 3D skeleton, orthographic projection; torso silhouette from cross-sections; limbs as organic tapered tubes; hair and head as one mass; face left blank (one nose tick in profile); shadow side = colour mixed 40 % with violet #464873
Page edge noisy boundary (fbm 0.004, ±80 px); a white-dab band 70 px wide inside, a coloured-dab spray 70 px wide outside

Titles and end card

No subtitles are needed. All text is handwriting on the page, written on with a left-to-right reveal and pen sound:

  • corner note in Reenie Beanie (Sun. 3:40 pm — windy);
  • title and colophon in Caveat (500–600 weight), left-aligned in the blank page margin.

The text stays in the world and moves with the camera, never as an overlay.

End card (demo/film.js, notes()): the title "Where the wind went." written in Caveat 500 at 190 px in the lower-left margin (28.2–29.5 s), then the colophon in the same column: "Urban Sketch · Pen & Wash — a Lemo-Opuscar style" (30.1–30.8 s), "LemoLab × Claude Opus 5.5" in Caveat 600 (30.6–31.2 s), and the music, sample and font credits (31.0–31.8 s). 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 (take those handwrite() lines out when reusing the code).

Build notes

styles/urban-sketch/demo/
  engine.js   pen, wash, foliage, arrival field, GL compositor, figure rig, hat, bike, handwriting, sketchShape
  world.js    the static page: sky, skyline (ink in stroke order), trees, lawn, path, lamp, pond, bridge, crowd, edge dissolve
  poses.js    character looks + pose library (sit, run, walk, cycle, dive, prone, wave)
  film.js     timeline: hat path, camera, performances, colour sources, sound cues
  audio/      score.py (music) · foley.py (all procedural sound) · mix.py
  build.sh    one command, from nothing to urban-sketch.mp4

Render: node core/render/video.mjs styles/urban-sketch/demo --fps 24 --workers 4 renders 778 frames in about 40 s on an M-series Mac; world build takes about 4 s per worker.

Pitfalls we hit

  • Straight edges in the colour field. The source bounding box ignored its vertical stretch (sy), and the slow "creep" beyond the reach radius was cut by a square box. Clip by the actual (noisy) distance, not the bbox.
  • Rectangle masks around set-back towers left white notches in the sky. Mask with the real stepped silhouette (tiers, spire, pyramid, water tank).
  • Characters losing colour when they run into unpainted areas. Sample arrival once at the character's start point (or tie it to the event that coloured them), never at the current position.
  • Static ink cannot be occluded by later washes. Far crowds therefore use carrot-people (one wash blob, two leg lines, a head dot) instead of full rigs; building ink is erased inside nearer buildings and tree crowns before drawing.
  • IK feet left pinned while blending sit → stand splays the legs. Blend the foot targets toward under-hip positions.
  • Front-facing heads went bald. Always draw the hair mass, then knock the face out of its lower part.
  • Headless Chrome and big canvases: 5120² canvases for ink, time, colour and the page are fine, but pack ink and time into RGBA byte textures yourself (getImageData), and upload the arrival field as R16F (filterable).

Engine reference

All functions are in demo/engine.js and are deterministic (same seed, same marks).

Function What it does
penStroke(pts, {w, wob, over, gap, seed, smooth}) prepares a fineliner stroke along any polyline (wobble, overshoot, taper, gaps)
drawPen(ctx, stroke, p=1, col=INK, alpha=1, from=0) draws it up to fraction p (draw-on); from erases from the tail
rasterPen(inkCtx, timeCtx, stroke, t0, dur, win) bakes a stroke into a static ink layer plus its per-pixel arrival time (stroke order playback in the shader)
wash(ctx, poly, [r,g,b], {a, j, layers, edge, dx, dy, seed}) a watercolour wash on any polygon (rough edges, glazing, dark tide line, offset)
reserve(ctx, poly, a) lifts colour back to paper (reserves, foreground occlusion)
dab(ctx, x, y, r, angle, col, a, seed) / foliage(ctx, crown[], opts) leaf dabs / a whole tree crown
arrivalField(W, H, gw, gh, sources, {amp, creep}) colour arrival time per cell; sources = [{x, y, t, v, R, sy, mask, hard}]
compositor(canvas, layers) → draw(cam, t) WebGL page: paper × wash (revealed by arrival, wet front) × ink (revealed by stroke time)
figure(look, pose, place, {seed, boil}) → prims a sketched person (knock / wash / ink primitives); prims.head, prims.hand for attachments
hat(c, r, [rx, ry, rz]), bike(place, phase, col) props with true 3D orientation
drawPrims(ctx, prims, {color, ink, clip}) draws primitives; color 0..1 = how far the wash has arrived; ink = draw-on progress (number or per-primitive function)
sketchShape(ctx, poly, col, {ink, wash, offset, color, p}) any shape in this style in one call
handwrite(ctx, text, x, y, size, p, {font}) handwriting written on left to right

The "only colour" hook. Leave everything at color: 0 (pure ink) and pass color: 1 only for the element that keeps its colour, as the straw hat does in the demo. Or give that element an arrival source at t = 0 and everything else later.

Minimal example: a warm orange #D97757 four-point sparkle with a short cursor tail.

import { sketchShape, sparkle, penStroke, drawPen, hex } from './engine.js';
const star = sparkle(960, 540, 120, .24);                       // 4-point star polygon
sketchShape(ctx, star, hex('#D97757'), { ink: 3, wash: .7, offset: 3, seed: 7 });
drawPen(ctx, penStroke([[1040, 610], [1180, 640], [1300, 646]], { w: 3, wob: 1.2, over: 6, seed: 8 }), 1);   // the tail