patch, Painted Valley and a coloured-pencil town: what an agent game platform ships, and two scenes built on it, taken apart
mdjsonmcp2026-11-13 · 40 min · agents · mcp · agentic-coding · 3d · threejs · procedural-generation · browser-games · game-dev
A 4:23 narrated explainer, drawn in code. Every number and picture in it is this article's own; the sources are below.
› transcript
A valley you can walk through, where every cloud, mountain and blade of grass is drawn in code. Claude Fable 5.2 helped build it, and it lives on a new platform called patch. Hi, I'm Mossby! The platform first, then both scenes, shader by shader. patch launched on November the ninth: a command line tool and an MCP server for coding agents, an asset library, and a host for games. Its tools are search, git, release and test. None of them makes a mesh, a texture or a sound. Your agent still writes the game. The library is real, and most of it is Kenney. Every item is public domain or Creative Commons with attribution, and carries its credit line. Publishing is one command. Your agent builds the game with whatever it already has. patch checks the files for secrets, size, and requests to other hosts. Patch Desktop plays it once on your own Windows PC and records it. Your agent watches that recording and says whether it starts and plays. Then a malware scan, and an AI model reads the code. With no warnings, no person looks at it. And it is live. Three things in the docs and terms are worth reading first. A new repo starts under the Patch licence. You can read and remix it, but not take it off patch. Both scenes chose MIT instead. The terms say that for some games, patch starts the game with its anti-cheat off for that session, so mods can load. And the installer writes a use patch section into your global Claude and Codex instructions, then restores it on every update. Painted Valley is plain three dot js on WebGL two. It downloads 12.8 megabytes, and the scenery in it is code: the only pictures are two textures for the footpaths. The only model is the walker. The grass, trees, clouds, mountains and village are all written in code. The finish is a Kuwahara filter. Here is a patch of the frame as pixels: two paints meeting at an edge, both speckled. Around each pixel, take a small window and cut it into four overlapping quadrants. Measure how much each quadrant varies. The calmest sits wholly on one side of the edge, and the pixel takes its mean. Do that everywhere. Inside a region all four quadrants agree, so the speckle goes flat. At the edge, one quadrant always stays on one side, so the edge survives. It looks like a loaded brush. In the valley, press P. Without the finish, the bushes are speckle. With it, they are a few flat patches. The walker writes a low alpha, so the filter leaves him alone. Light on the walker is a step, not a gradient. Smoothstep rises from zero to one as the surface turns toward the sun. Over a tiny width, so each part of him is two tones with a clean turn between. The small offset keeps grazing light lit. And the shade is a colour of its own, deeper and bluer, not the lit one darkened. The hour is one number. Sky, clouds, mountains and grass all read the same keyed colours, so nothing is repainted. The second scene is a harbour town in coloured pencil. Its claim is pure code, and it holds. The only file it loads is a skeleton with its clips. The strokes belong to each surface. Every vertex carries two numbers, and strokes run along their level lines, so they never swim. Only their spacing follows the screen. The shader measures how fast the field changes per pixel and picks a spacing in whole octaves. Walk in and new strokes fade in half-way between the old ones. Nothing slides. Strokes are only added or taken away. So the two scenes put their style in different places. The valley paints the screen, and inks only its walker. The town draws on the surfaces themselves, and turns light into how hard each stroke is pressed. Separate light from paint, then decide where the style lives: on the screen, or on the surface. patch is plumbing around your agent. The valley paints the screen, and the town draws on the surfaces. Both are open, so go and walk them. Thanks for watching! Every source is in the full article. I'm Mossby. Bye!
Why read this
Notabletop 60%patch's tools, licence and installer from its docs; both demos cloned, diffed against their parents and measured live; both looks ported to widgets.
- Original analysis
- Runs in a browser
- A new technique
Agents & harnessesMixed licencesPractitioner teardown
How this was scored
- Is it new?
- 2 of 3: A real new idea, method or capability
- Can I trust it?
- 2 of 3: Measures key facts from files, code or configs
- Can I run it?
- 2 of 3: Open code or weights with real limits
- Will I understand it?
- 2 of 3: Mechanism from first principles with figures
- Can I act on it?
- 2 of 3: A concrete recipe, numbers or comparison
- Will it last?
- 1 of 3: Relevant for months
- Does it affect many?
- 1 of 3: A specialist community
- Only here?
- 2 of 3: A teardown or measurement few others did
Score 63 of 100, ranked 319 of 740 rated articles. Each question is answered 0–3 by hand, and a 3 is rare. How articles are scored
Three posts landed on my list this week, all from the same small company. On 9 November Rehan Sheikh announced patch: "build and play games", with every game dev tool in one CLI and MCP server, 50,000+ open-source assets, remixing, modding and publishing. On 12 November his co-founder Blendi posted a walkable valley and wrote that he "used fable 5.2 to make this delightful ghibli inspired scene", playable and open source on patch. On 13 November he posted a harbour town drawn in coloured pencil, where "every surface shading, and the whole town, is pure code."
The scenes are good, and they are the best advertisement patch has. (A third, a watercolour wood, followed a few hours later; it gets a short section of its own.) So this page treats them as worked examples of the platform rather than as standalone demos. I read patch's documentation, terms, public API and the pch npm package (without installing or running it). I cloned both scenes from patch's own git host, which needs no account for an open repo, and read them. I loaded both in headless Chromium on an M1 Max and counted what they download and draw. Two widgets below port the shading code onto a small scene of my own, so you can switch each layer on and off.
Short answers first. patch is a hosted platform with a thin MIT command-line client: the tools are search, git, release and test plumbing around a curated library of mostly Kenney assets, not generators. Painted Valley's scenery is code (the only pictures it loads are 1.76 MB of footpath textures; the rest of its 12.8 MB is code, the walker, his clips and sound), and nearly half its source was copied unchanged from two earlier patch demos. The painted look is three tricks you can name: a two-tone light step, an ink line drawn from per-part alpha IDs, and a Kuwahara filter. The pencil town's claim of pure code holds, apart from 3.6 MB of skeleton and animation clips. How much of either scene Fable wrote, and from how many prompts, nothing public says.
What patch is
patch is made by New Save Labs, Inc. (the terms give a Delaware address), and Patch's own llms.txt says it "came out in November 2026". It does three jobs. It hosts browser games, which play on patch.gg in a sandboxed window. It installs and launches mods for games already on a Windows PC, through a desktop app. And it gives a coding agent the tools to make either and publish it. The launch video spends most of its 47 seconds on the third job.
"Every game dev tool in one CLI and MCP" is the phrase to check, because it suggests generators: models that make a mesh, a texture or a sound on request. The MCP server's tool list has none. It has guide and whoami; search_projects and the host-game wiki; search_assets, asset_facets, get_asset and get_asset_files for the library; project, listing and media calls; publish, validate_recipe, create_release, submit_release and release status; search_repos, get_repo, fork_repo, change requests and history scans for the git side; GitHub connection; and send_feedback. The pch CLI mirrors it (pch search, pch remix, pch assets add, pch publish, pch test start). The server is hosted at https://patch.gg/api/mcp and answers an unauthenticated call with a request for OAuth or a pch_ API key.
So the agent writes the game with whatever it already has, and patch supplies four things around that: assets to pull in, other people's code to start from, a pipeline that tests and reviews a build, and a place to put it. patch's generative work lives in separate public repos: anymove (motion capture from one AI video, Apache-2.0) and trompe (texturing a gray blockout with image models, Apache-2.0). Painted Valley's run, sprint, start and stop clips were made with anymove, which is the only place I found one of those tools inside these scenes.
The 50,000 assets
The asset endpoints of the public API need no key, so the count is checkable. Three endpoints gave three totals on 13 November: /assets/count said 54,681, /assets/facets 58,994 and /assets/status 59,148. I did not try to reconcile them; any of them clears 50,000.
What they are matters more than how many. By the facets endpoint, 30,686 of the 58,994 are 2D sprites and 21,468 are 3D models; the rest are 2,906 PBR materials, 1,812 music tracks, 1,432 HDRIs, 659 sound effects, 23 splats and 8 shaders. By source, Kenney supplies 36,003, about 61 percent of the library. Then Amazon Berkeley Objects with 7,498, Polyfork 3,070, ambientCG 2,637, Poly Haven 2,383, SimReady 2,382, KayKit 1,890, incompetech.com 1,443, Scenario 1,059 and patch itself 337. The licences are CC0-1.0 for 43,457 and CC-BY-4.0 for 15,537, nothing else, and 1,068 are flagged as AI-generated.
Every item carries its licence and a credit line, and pch assets add writes the credits into the release. You could assemble the same library from the same public sources; what patch adds is search, scale metadata (13,719 models have a measured real-world size) and web-ready conversions.
Remix is a git fork, and the default licence is not open source
Every project on patch is a git repo on git.patch.gg (docs). A new one is open once its first push has been scanned for secrets: anyone can read its history and fork it. pch remix owner/slug is that fork, recorded with where it came from. Changes go back as change requests, which patch's AI review reads as advice for the owner. Painted Valley's API record showed 5 remixes on 13 November; its parent block blendi/oil-paint showed 9.
The word "opensource" in the launch post needs one qualification. A new repo starts under the Patch licence, which is section text in the terms: anyone can play, read and remix the work on patch, but "nobody may take someone else's work under the Patch licence, or a remix of it, off Patch without its maker's OK," including to another site or to train AI models. That is source-available with a platform lock, not an OSI licence. A maker can choose MIT, Apache-2.0, a GPL or a CC licence instead, and all three scenes on this page did: code MIT, art CC0. Check the licence on each repo before you lift anything.
What is open about patch itself is narrower than the launch post suggests. The pch client is on npm as @patchgg/cli, version 1.1.0, MIT, a 2.25 MB bundled cli.js; its declared GitHub repo, patch-gg/pch, returned 404 to me, so the readable source is the bundle. The API, the MCP server, review, hosting, the asset pipeline and the Windows app are a hosted, closed service. There is no pricing page. Playing is free, and the terms say makers will earn "later" and that the terms will change before that starts.
What "mod the ones on your PC" touches
This half runs only in Patch Desktop, a Windows app (about 115 MB to download, installed in the user's folder without administrator rights). A mod's release carries a recipe (reference) that names its host game, the files, and where they go: {profile}, a folder patch keeps per game and set of mods, or {game}, the game's own install folder. It can require a loader that patch fetches from its publisher at a pinned version (BepInEx, Ultimate ASI Loader, Fabric, Forge and others). Between plays patch switches the mod off by renaming code files and loader hooks with .patch-off and putting back any game file a mod replaced; removing a mod restores the originals.
Each release gets a trust tier that players see: sandboxed for a browser game, game_files_only for data and config, and runs_code for anything that ships a .dll, .exe, .lua, .pak, an archive or a Workshop item. Review is a file scan for secrets and known malware, a recorded test run on the creator's own PC, the creator's agent reviewing that footage, and then an AI model run by patch's providers reading the code; a release with no warnings goes live with no person looking at it. The terms are frank that this is not a guarantee, and they contain one line I would read twice: "For some games, Patch starts the game with its anti-cheat off for that session so that mods can load." Patch's own rules forbid cheats for online play and anything that gets around anti-cheat, and tell players not to take a modded game into official online play. Publishers' own terms are a separate matter, and patch says it cannot grant their permission.
Two more things about installing it. The get-started page tells a user whose PC blocks the installer to turn Windows 11's Smart App Control off, and notes that once off "it stays off until Windows is reinstalled." And pch's installers run pch agent install, which adds patch's MCP server to every coding agent it finds and writes a section headed "Game development: use Patch" into ~/.claude/CLAUDE.md and ~/.codex/AGENTS.md. The section tells the agent to use patch's tools first for any game, to look in patch's toolbox before making or fetching anything, to deploy on patch rather than another host, and to recommend publishing on patch. The CLI docs say each new version puts the section back if you deleted it, unless PCH_NO_AGENT_INSTALL=1 is set; the npm package's postinstall.cjs runs the same command after a global install. The MCP server also tells agents to file feedback reports without asking first. All of this is documented, and none of it is hidden, but a tool that rewrites my global agent instructions on every update is a tool I install with that variable set.
Painted Valley
The repo is at git.patch.gg/blendi/painted-valley: 82 files, three commits, MIT for code and CC0 for art. Its README.md front matter says kind: effect and engine: three.js, and the rest is plain web: three.js 0.186.1 on WebGL2, built by Vite, with Rapier 0.21.0 for physics. There is no game engine and no editor scene; src/valley/main.js builds everything at start-up.

What it downloads
I loaded the published build and logged every response. It made 22 requests for 12.8 MB of decoded bodies, which matches the README's "about 13 MB":
| File | Bytes | What it is |
|---|---|---|
index-*.js | 5,371,097 | the code: three.js, Rapier (with its WebAssembly inlined) and the valley |
starter-man-clips.glb | 2,378,416 | the walker's animation clips (Quaternius' library and patch's anymove) |
starter-man.glb | 1,255,588 | patch's starter figure, a MakeHuman body, textures stripped |
four ambientCG Ground* JPEGs | 1,757,321 | colour and normal maps for the earth of the footpaths |
five ambience .ogg loops | 2,586,678 | wind, leaves, birds, crickets, lake water |
five footstep .ogg | about 43,000 | Kenney, CC0 |
So the scenery is code: the only pictures loaded are two ground textures for the paths, and the only model is the walker. The five ambience loops are not in the repo. MISSING_ASSETS.md explains that they were cut from the Sonniss GDC game-audio bundles, whose licence allows use inside a game but not passing the files on, so a build from the repo has footsteps and silence. That is the most careful licence note I have seen in a demo repo, and it is also a fair test of patch's "50,000+ open-source assets": the five sounds that make the valley feel alive came from outside the library.
The ambientCG ground Ground048 is in patch's library (ambientcg:Ground048, CC0), and LICENCE-NOTES.md says the footsteps came "through Patch's asset library". That is the whole of the library's contribution here: a ground material and five footsteps.
How much is new
LICENCE-NOTES.md says src/lib/ (grass, flowers, ground, the frame's finish) was copied from patch's blendi/touch-grass block and src/figure/ (the walker's controller, camera and cloak) from blendi/oil-paint. Both parents are public, so I cloned them and diffed line by line. Of the valley's 9,675 lines of source, 4,587 are identical to a line in a parent: 4,210 of the 4,633 lines in src/lib/ and src/figure/ (the figure folder is unchanged line for line), plus 377 lines of src/valley/ that match the grass block's demo. The other 5,088 lines match nothing I compared them with, and nearly all of them are in src/valley/: the sky, clouds, backdrop mountains, far woods, village, trees, water, brushwork and the walker's look. That is the scene.
The parents carry agent trailers too. touch-grass's three commits are co-authored by "Claude"; oil-paint's seven by "Claude" and then "Claude Fable 5.2" (and its last by Opus 5.5). So the remix chain is agent work built on agent work, three days deep.
Light and shade, as two paints
A standard shader computes how much light reaches a point, (the cosine between the surface normal and the direction to the sun), and multiplies a single colour by it, so shade is the lit colour made darker. Painted backgrounds and cel animation do neither. A thing is painted in two colours mixed separately, and the boundary between them is a short step, not a gradient.
The walker's fragment shader in src/valley/wanderer.js does exactly that:
// in the light or out of it, and nothing between: a figure in a film is two tones
float lit = smoothstep(0.0, 0.035, dot(N, uSunDir) + 0.06) * open;
...
vec3 col = mix(shadePaint * sky, litPaint * sun, lit * (1.0 - deep));smoothstep(0, 0.035, x) rises from 0 to 1 while moves across 0.035, so on a curved surface the turn from shade to light is a band a few pixels wide instead of a gradient across the whole form. The + 0.06 moves the terminator slightly past the 90-degree line, so a surface that grazes the sun still reads as lit. open is the tree and cloud shadow at that spot. The palette sits beside it, as [lit, shade] pairs, and the shade is never the lit colour scaled: the cloak is [0.14, 0.32, 0.64] in the light and [0.07, 0.13, 0.4] in shade, deeper and bluer, and the shirt's shade [0.52, 0.52, 0.66] is a grey-violet of its own. The shade colour is lit by a desaturated sky (mix(uSkyColor, grey, 0.8)), so shade stays nearly colourless as the hour changes while the lit side warms toward sunset. A third tone, deep, draws fold wedges rising from the cloak's hem.
Trees and houses do the same with their own palettes, and one meadow palette (meadowGreen, meadowLight in world.js) paints the grass, the ground and the far fields, so the valley reads as one picture.
An ink line with no outline geometry
The usual ways to outline a 3D figure are an inverted hull (draw the mesh again, slightly inflated, back faces only, in black) or an edge detector on depth and normals. The first fails on thin parts and costs a second draw of every mesh; the second inks everything, including each blade of grass. Painted Valley uses a third trick. Each part of the walker writes a small number into the frame's alpha channel: cloak 0.03, hat 0.06, hair and eyes 0.09, boots 0.12, trousers 0.15, shirt 0.18, skin 0.21. Everything else in the valley writes more than that. The last full-screen pass in src/lib/frame.js compares each pixel's alpha with its four neighbours:
if (min(a, b) >= 0.23) continue; // neither side is the figure
float db = textureLod(tDepth, uv + o * w, 0.0).r;
if (max(a, b) >= 0.23 && (a < b ? db < da : da < db)) continue; // the other thing is in front
e = max(e, abs(a - b));
...
return smoothstep(0.008, 0.022, e);Two different figure IDs meeting give a line, so the hat is inked where it meets the face and the cloak where it crosses the shirt. A figure pixel next to scenery gives a line only when the scenery is behind it: a blade of grass in front of his legs is nearer, so the depth test skips it and the grass is not inked. The line itself is not black. It is the colour under it multiplied by (0.2, 0.14, 0.15) and mixed in at 0.92, a dark warm version of whatever it crosses. The sampling offset scales with resolution (max(1, 1/(texel.y × 1080))), so the line stays about a pixel at 1080 lines.
The same alpha doubles as a mask. The paint finish, below, leaves alone any pixel whose alpha is under 0.6, so the walker and the sky are never smeared. One channel carries both the outline IDs and the "do not paint me" flag.
Far things painted once
A big part of why the valley costs little per frame is that most of what you see is not drawn per frame at all.
- Mountains (
backdrop.js). The ground out to 86 km is worked out once into a height map. A shader then marches rays across it into a strip of picture that wraps the horizon, 12,288 pixels wide at high quality. It stores paint rather than the picture: each point's lit colour, shade colour, how lit it is and how much air lies in front of it. The sky mixes those with the hour's light, so changing the time of day does not repaint the mountains. - Clouds (
clouds.js). Up to 14 cumulus clouds, each a heap of spheres (up to 44 a cloud) pushed about by billowing noise, are ray-marched into a cube map, one strip a frame, then given flat tones: white top, cool shade, warm underside. After that the sky is one texture lookup per pixel. They stand still on purpose; the README lists "the clouds don't move" among its limits. - The plain (
floor.js,farwoods.js). Fields, hedges, roads and the river are drawn into one texture; orchards, poplars and a mill stand on it as small painted cards.
The near ground is the expensive part, and it is instanced. src/lib/blades.js draws grass in four rings that follow the camera, from blades 5 cm apart with eight rows of vertices near your feet to tufts 62.5 cm apart out to 120 m, each blade's height, lean and colour hashed from the number of the world cell it grows in, so the same blade is there when you come back. Under it, strokes.js paints a 512-pixel tile of brush marks on a canvas at start-up (70 broad patches, 420 strokes, 900 small dabs, 9 groups of stones), which the ground reads at several scales.
On my M1 Max at 1600x900 the live page issued 142 WebGL draw calls a frame, submitted about 10.05 million triangles a frame across all passes, and drew 432,222 instances (grass rings, flowers, tree crowns, stones, houses and far woods are all instanced). It held 60 frames a second, which is the browser's frame cap in my headless setup rather than a ceiling I measured; the README's own numbers are from an RTX 4090 at 1080p.
Air is the last layer before the finish. applyFog in src/lib/glsl.js is exponential fog thinned with height:
where is the distance from the eye, the hour's fog density and the height of the point in metres. The fog colour leans toward the sun's colour as the view turns toward the sun (), so a backlit valley at golden hour hazes warm and the opposite side hazes blue.
The paint finish is a Kuwahara filter
Press P in the valley and the finish goes off. The difference is subtle at full frame and obvious close up.

A Kuwahara filter, from 1970s medical imaging, smooths a picture while keeping its edges. For each pixel take the square window of radius around it and split it into four overlapping quadrants , each , that all contain the pixel. Compute each quadrant's mean colour and its variance (summed over the three channels). The classic filter outputs the mean of the quadrant with the smallest variance: near an edge, at least one quadrant lies entirely on one side of it, so the edge survives, while inside a region all four quadrants agree and the region goes flat. The result looks like loaded-brush strokes.
A hard minimum flickers when two quadrants are close, so the valley's painted() function blends all four with a steep weight:
The fourth power makes the calmest quadrant win almost outright without a hard switch. Colours are compressed with before the statistics and expanded after, so the HDR highlights of the sky do not dominate the variance. The radius is chosen per pixel from depth: 2 in the middle distance, where grass is a mass, and 1 nearer than about 16 m or farther than about 140 m, so blades at your feet keep their strokes and houses a few pixels wide keep their windows. It is a small kernel (at most 25 taps), which is why it costs little.
The order of the final pass matters: paint, then bloom, then the ink line on top (so the line is crisp over painted ground), then a vignette and a "painter's curve" that leaves everything below 0.62 as mixed and only eases the brightest lights toward white, then a tiny dither.
Here are the layers on a small scene of my own, with the valley's constants:
The widget draws a ridge, a hill, a tree, two clouds and a walker per pixel in a 360x200 canvas. The ramp slider runs the step width from 1 (a soft, Lambert-like gradient) to the valley's 0.035; the checkbox swaps the separately mixed shade colour for the lit colour times 0.45, which is how most real-time toon shaders make shade, and you can see the shade go muddy. The ink layer uses the alpha-ID rule above, including the depth test, which is why the four blades in front of the walker stay uninked. The fog and paint layers use the formulas above with the same radius and alpha rules.
Hours, physics and the invisible walls
The time of day is one number, from 12.5 (noon) to 20.4 (sunset), and sky.js interpolates between four keyed sets of colours: sun, ambient, bounce, zenith, horizon, fog, cloud lit, mid, shade and underside, and an exposure. There is no night, which the README says.

The walker is patch's starter man: a MakeHuman body (CC0) on the skeleton of Quaternius' Universal Animation Library, with clips from that library and from patch's anymove. src/figure/player.js moves him as a Rapier capsule driven by a kinematic character controller with auto-step (0.3 m) and a 46-degree slope limit. The collision world is a heightfield of the meadow sampled a metre apart, plus a cylinder for each big stone and tree. Nothing else collides.
That explains a complaint in the replies, "INVISIBLE WAAAAAAALLS", and the question about entering houses, and it is worth reading the code rather than guessing. main.js sets REACH = EXTENT / 2 - 110, with EXTENT = 1280: you can walk 530 m from the start, and past that you are pushed back to the circle's edge. The tarn's bank is a second wall ("no wading"). The village stands at 740 m down the valley and 210 m across it (VILLAGE in world.js), about 769 m from the start, with half-widths of 72 and 88 m. Every house is outside the walkable circle, and so are the six farmsteads (the nearest about 739 m out) and the mill (about 706 m): that is why no building has a collider, and why you cannot reach one, let alone go in. The village is a backdrop you walk toward.
The author's answer, "going into houses can be one prompt away", is true of the walking part: raise REACH, add box colliders from the eight house shapes in village.js, done. It is not true of the interiors. The houses are drawn a size or two bigger than life on purpose, "as a painter draws a far village so that it reads", with their windows, shutters and tiles painted in the wall shader from the wall's own coordinates. They are facades. An interior needs geometry, a second light model for indoors, and a new answer for what the paint finish does in a small room.

The coloured-pencil town
The second scene, at git.patch.gg/blendi/coloured-pencil, is a single commit, co-authored by Claude Fable 5.2, made at 22:12 Pacific on 12 November. It is smaller than the valley: 2,067 lines in src/ outside the figure folder, whose 1,194 lines are again identical to oil-paint's. Its claim is stronger than the valley's, so I checked it the same way. The live page made 5 requests for 8.47 MB: the 5,238,393-byte code bundle, index.html, a 2.5 KB hands file, and the same two starter-man files as the valley (2,378,416 and 1,255,588 bytes). No texture, no model of a thing, no sound, no font (the handwriting at the corner is "whatever cursive face the viewer's own machine has"). The LICENCE-NOTES.md puts it exactly: "the only files loaded are the figure's skeleton and his clips."
There is one wrinkle. The sailor is sewn in code onto the starter man's skeleton and "his body is never drawn", but starter-man.glb still carries that body, so every visit downloads 1.26 MB of mesh that is thrown away. It is the obvious next trim, and the kind of thing the valley's compact-glb.mjs already did for the clip file.
On the same M1 Max the town issued about 96 draw calls a frame and submitted about 1.25 million triangles, with no instancing: createBatch in src/pencil.js merges every piece drawn with one material into one mesh. The README claims "about 2 ms a frame at 1080p on a fast desktop card".

Strokes that belong to the surface
Most "sketch" shaders put hatching in screen space: a pattern of lines laid over the frame, its density chosen by brightness. It is cheap, and it swims: walk and the lines slide across the walls like a texture on a window. One reply under the post asked about exactly this: are the strokes anchored to the objects or to the screen? The code answers it. They are anchored to the objects, and only their density follows the screen.
Every vertex carries a two-component attribute hatch. By default, field() sets it to two dot products with fixed slants:
with the vertex position in the piece's own coordinates. A level line is where the plane perpendicular to at height cuts the surface, so strokes are those slices: straight and parallel on a flat wall, curved on a ball or a barrel, and fixed to the object because is. The pair of slants is "the slant of a right hand"; fieldBy() lets any piece define its own (the roof tiles and the sea use their own fields). The first field carries the object's own colour; the second carries the shadow pencil.
The trick that keeps them stable as you walk is in pcStrokes. If strokes sat at fixed values of , walking toward a wall would make them grow apart on screen until it was striped, and walking away would crush them into grey. Instead the shader measures how fast changes per pixel, (from dFdx, dFdy), and picks a spacing in whole octaves:
Strokes are centred where is a whole number, so in they are apart and on screen pixels apart, which works out to between and . The default is 5. As you walk in, falls, rises, and the strokes spread toward ; at that point steps up, doubles, and a new stroke appears half-way between each pair. The half-way strokes do not pop: they are drawn with width scaled by , so they grow in from nothing over the octave. Every stroke that exists at one distance is still at the same place on the surface at every other; strokes are only ever added or removed, never slid. It is the same idea as the tonal art maps of real-time hatching research twenty-five years ago, done analytically per pixel instead of with a stack of textures.

How light becomes pressure
pcDraw treats the frame as white paper and each layer as wax that removes some of the white. It starts from three.js's own Lambert result, turned into a darkness from 0 (full light) to 1 (full shade) as , then lays four layers, each multiplied over the last:
- A warm yellow, very lightly, only where is low: sunlight as a colour.
- The thing's own colour, lightly all over, a little more toward the shade.
- Strokes of the own colour along , covering of the spacing and pressed harder in shade ().
- A blue-violet shadow pencil (the local colour halved and mixed 55 percent toward
(0.24, 0.2, 0.62)) along , which only starts above and covers up to 0.82.
So light does not change which strokes exist, only how wide and how hard they are. The paper's tooth multiplies every layer: two octaves of 3D noise at the surface point, evened out by fwidth where the grain would be finer than a pixel, so wax "only catches on its high places". A small sine wobble bends each stroke so no two are perfectly straight, and each stroke's width and pressure come from a hash of its own index.
Because it hooks MeshLambertMaterial through onBeforeCompile, replacing only #include <opaque_fragment>, shadows, skinning and instancing still work, which is the most practical design decision in the file.
The widget is pcStrokes and pcDraw ported to a ball and a block of my own, rendered per pixel in an orthographic view. Turn the light: the strokes stay put and only their width and the second pencil change. Walk in: watch the spacing grow to twice px and the in-between strokes fade in. The block's faces get straight strokes and the ball's curve, from the same two vectors.
The page and the town
src/page.js is the last pass. It reconstructs each pixel's view-space position from depth, fits a plane through it from the neighbour on each axis that differs least, and draws a soft graphite line where the other neighbours leave that plane, weighted by depth so far lines fade. It is an outline from depth alone, with no normals buffer and no IDs: it catches silhouettes and creases on everything, which suits pencil, where the valley's per-figure ink would not. Then it leaves flecks of bare paper where the tooth is low, tints everything with a warm sheet, and fades the drawing out toward the page edges with a noisy border, which is the "paper border" one reply credited with making the camera feel like it is walking into a sketchbook.
The town is built from five soft solids in src/shape.js (ball, block, turned, roll, knead), all deliberately a little out of true: knead pushes vertices along their normals by noise and can press thumb dents. houses.js builds the quay's tall houses from those (tiled roofs, chimneys, shutters, balconies, awnings, drainpipes, vines), each in its own pencil colour; hills.js, tower.js, quayside.js and mountains.js add the farms, chapel, windmill, café, bunting and ranges. Small things move: bunting, washing, chimney smoke drawn as a pencil line, boats, gulls, the windmill.

A third scene, the same morning: watercolour that follows you
A few hours after the pencil town, the same author posted a third: a wood, a stream and a meadow that start as a pencil drawing and are painted in watercolour wherever you walk. It is on patch at blendi/watercolour, one commit co-authored by Claude Fable 5.2, MIT and CC0, and it is the pencil town's code taken one step further: src/shape.js, src/pencil.js and src/noise.js are identical to the town's files, and page.js is a modified copy. Its claim of code-only art holds the same way. The live page made 5 requests for 8.47 MB, the same two starter-man files plus a 5,234,067-byte bundle; on my M1 Max it issued 14 draw calls a frame and about 1.29 million instances, and ran at about 42 frames a second, under the cap.
The new idea is a map of time. createWash() in src/wash.js keeps, for every cell of ground, the moment the wash reached it, and paint.touch(x, z, now) writes earlier times into a disc round the walker's feet, spreading at a set speed and slowing past its reach. Every vertex carries a root, the point it takes its paint from, and a rate in seconds per metre. The shader's wcAge reads the map at the root and subtracts the climb:
Ground is its own root, so it fills where you step; a tree's root is its foot, so it fills from the trunk up; a flower bed's is its middle, so it goes off at once. rag is three octaves of noise, so the wet front runs ahead along the grain in places and hangs back in others. Then wcPaint blends from the pencil underdrawing (graphite hatching where the shade will be, the same pcStrokes) to the wash by smoothstep(0, 0.25, age), darkens the wash while it is wet and most of all at its creeping edge, and lays the same kind of cool violet glaze over the shade. It is the pencil town's object-space idea with one more variable on every surface: when.
Two looks, two places to put the style
The brief I set myself was "assets and painterly shading against fully procedural hatching". The source does not support that split: both are almost entirely code, and neither uses patch's library for anything you look at. The real difference is where each one puts its style.
| Painted Valley | Coloured pencil | Our beach houses | |
|---|---|---|---|
| Engine | three.js 0.186.1, WebGL2 | three.js 0.186.1, WebGL2 | Python and Blender, .glb in our viewer |
| Lighting | real time, two-tone step per hour | real time Lambert, mapped to stroke pressure | baked once in Cycles |
| Style lives in | screen space: Kuwahara finish, ink from alpha IDs | object space: hatch fields per vertex | the baked atlas |
| Outline | figure only, from alpha IDs and depth | everything, from depth alone | none |
| Pictures or models loaded | 2 ground textures, 1 figure, clips | figure skeleton and clips only | none |
| Download | 12.8 MB, 22 requests | 8.47 MB, 5 requests | about 5 to 6 MB per house |
| Draw calls per frame (my run) | 142 | about 96 | not measured |
Painted Valley paints the world in screen space and inks only its people. That is cheap, it adapts to whatever is on screen, and it works on any mesh, but it is a filter over a rendered frame, so it needs care at edges (hence the depth-based radius and the alpha opt-out). Coloured pencil puts the style on the geometry, which is why it can promise strokes that never swim and why it cannot be laid over someone else's game: every piece needs its hatch field. Both READMEs make this point in nearly the same words, "It is a starting point, not a filter", and the pencil one is the stricter case.
The comparison with our three beach houses is about light. There, Opus 5.5, Fable 5.2 and Sonnet 5.5 each built a house in Python and baked its light in Blender's Cycles, so the browser draws it unlit and every shadow is a texture. That buys soft shadows and bounce light no browser shader here attempts, and it costs a fixed sun and an offline bake on a GPU for every change. Both patch scenes compute light every frame and then throw most of it away on purpose, down to two tones or a stroke pressure, which is why the hour can change in the valley and why neither needs a bake. Fable 5.2 is credited in both setups, and in the beach house it baked only light and painted the colour after, the same separation of light from paint that the valley's shade palette makes. In both cases the decisive design call was the separation, not the model.
The beach houses also had something these two repos do not show: a critic loop with logs. Our 3D and BIM roundup and the beach-house article could count rounds and minutes because we ran them. For the Open 3D Skills pack I could read the checking scripts. Here I can read the checking scripts too. Painted Valley's tools/ has headless Playwright scripts for stills, frame rate, a throttled first visit (cold.mjs), a per-feature cost A/B (ab.mjs, run with --use-angle=d3d11, so on a Windows PC), a pointer-lock guard and a resize check; the pencil repo adds act.mjs, which puts the walker through his paces and reports how deep the cape gets into his body, and edit.mjs, which "applies a list of exact text replacements to source files and fails loudly if any target is missing". That is the shape of an agent's harness, and it fits the commit trailers. It is not a log.
Browser games on this site usually go the other way: Voxel Musou is a frame table for combat and the Road Rash rebuild runs on the original's decoded tables, with no particular look. These two are a look and little else, and the author says so: "not really a game yet".
What I can't check
- How much Fable wrote. The commits say: Painted Valley 1.0.0 and the walker commit are co-authored by Claude Fable 5.2, release 1.1.1 by Claude Opus 5.5; the pencil town's one commit by Fable 5.2. The licence notes say "Written by Patch". There are no prompts, transcripts,
BRIEF.md,AGENTS.mdorCLAUDE.mdin either repo or its history, and a co-author trailer does not say who typed what. The valley's 1.0.0 commit arrived as one finished commit, so its history before that is not public. - How many prompts, and what they cost. Nothing public. The author was asked about cost in the replies and answered with a question.
- Reference images.
LICENCE-NOTES.mdsays published stills from animated films "and two pictures its author supplied were looked at side by side with it, for colour, light and how much is drawn where", and that none was traced or is in the repo. I can't see those comparisons. - Performance on a laptop. Both READMEs say their numbers are from fast desktop GPUs. A reply measured "almost 30 FPS" for the valley on a Mac; my 60 is a capped headless run on an M1 Max and says only that it reached the cap.
- patch's review and mod handling in practice. I read the docs and terms; I did not install Patch Desktop or
pch, so the anti-cheat, rename-on-switch-off and test flows are as documented, not as observed.
What I think
The scenes are better engineering than the replies give them credit for, and the reason is legible: each one picks a small number of decisions and applies them everywhere. Separate light from paint; ink people, not places; paint the far country once. Strokes belong to surfaces; spacing belongs to the screen. Those are things a reader can take into their own renderer with or without patch, and the code is MIT.
patch is a different question. As a place to find and fork open three.js demos with real licence notes, it is already useful, and the asset API is a decent index of public CC0 and CC-BY work. As a platform, it is early, Windows-first for anything beyond the browser, built around a default licence that keeps work on patch, and keen enough on being every agent's default for games that its installer edits my global agent instructions and puts the edit back on update. The two scenes I liked most here used almost nothing from the library, chose MIT and CC0, and would work on any static host. I'd clone them. I'd install pch only with PCH_NO_AGENT_INSTALL=1.