Real mountains, glass and paintings made with code and real elevation data. No image model.
Two Claude skills. Name any mountain on Earth and get an engraving, a woodcut, a photograph, or a painting of it.
Try any mountain in your browser · Showcase · Studios · Latest release · Changelog
It started as an attempt to recreate an AI-generated header of Mount Ararat with math instead of a model, drawn from the real mountain's elevation. From there it grew into two skills:
| Skill | What it makes |
|---|---|
| procedural-terrain-art | Any real mountain, range, canyon or island in six print styles, looping orbit videos, and a self-contained interactive studio page. |
| procedural-realism | Photographic terrain (sky, haze, snow, lakes, forests, city lights, sun timelapses), a path tracer for glass and metal still lifes, and a painterly finisher for any image. |
Every terrain pixel comes from SRTM-derived elevation, numpy and physics. Nothing is downloaded except elevation tiles, and no generative model is involved at any step.
Any mountain is the terrain engine as a web page. Type a peak, volcano or canyon, drag the viewpoint on the map, pick a style, and save a 3000 × 1000 header (or a LinkedIn, YouTube or wallpaper size). The page downloads 20 to 40 elevation tiles and measures the landform itself, so there is no server; a copied link reopens the same mountain, view and style. It draws with the same code as the studios below. 94 well-known peaks come with their classic viewpoint; anything else found on OpenStreetMap gets an automatic one.
Masis and Sis (Ararat) seen from Yerevan. Same elevation grid, same hidden-line buffer, six ways of drawing it.
![]() survey |
![]() topo |
![]() nocturne |
![]() stipple |
![]() riso |
![]() woodcut |
The engine measures the ground around the summit before it frames anything: how steep the peak is for its footprint, what stands in front of it, how rough it is, whether it sits below a plateau. Cone volcanoes keep the original framing; horns, ranges, canyons and islands get their own.
![]() Matterhorn · horn |
![]() Grand Canyon · canyon |
![]() Denali · massif |
![]() Fuji · cone |
![]() Tetons · range |
![]() Mauna Kea · island volcano |
Before and after: the Matterhorn
The first engine treated every mountain like Ararat, and the Matterhorn drowned in its own massif (top). Landform-aware framing raises the base from 1429 m to 2441 m and narrows the scene's half-width from 30.7 km to 10.8 km (bottom). Fuji, Ararat and Mauna Kea render identically before and after.
The same elevation, ray-marched through a physical atmosphere: Rayleigh and Mie scattering, soft terrain shadows, valley mist, a lenticular cloud with multiple scattering. Lakes reflect the terrain with Fresnel and ripple normals. Trees, villages, stone walls and fields are placed near the camera, and a city at dusk is lit along its real OpenStreetMap streets.
![]() Blue hour over Yerevan, lamps on the real streets |
![]() A village lane on the Ararat plain, camera 3 m up |
There's also a sunset timelapse along the real sun path for a date and place: every frame is rendered with the sun where it is at that moment, so shadows move across Yerevan as the sun sets behind Ararat and the street lights come on. A 4:5 version suits phones.
A Monte Carlo path tracer in plain numpy. Scenes are small JSON files: spheres, boxes, prisms, cut gems, hollow glasses with liquid in them. Multiple importance sampling and adaptive sampling make glass converge about 6.7× faster and copper 12× faster than a plain sampler.
![]() Wine and marbles |
![]() Pomegranates |
paint.py turns any image into oil, impasto, gouache, watercolour or ink, including a photo you give it. Brushes follow the contours of the picture; watercolour is built from transparent washes with wet edges and granulation.
![]() --style watercolor |
![]() --style oil |
/plugin marketplace add dogum/procedural-art
/plugin install procedural-art@procedural-art
Both skills install together. Updates arrive with /plugin update.
- Download
procedural-terrain-art.skillandprocedural-realism.skillfrom the latest release. - Open Claude.ai → Settings → Capabilities → Skills.
- Upload each file. Re-upload to update.
git clone https://github.com/dogum/procedural-art.git
mkdir -p ~/.claude/skills
cp -r procedural-art/skills/procedural-terrain-art procedural-art/skills/procedural-realism ~/.claude/skills/
pip install -r procedural-art/requirements.txtRequirements: Python 3 with numpy, scipy, pillow, matplotlib and contourpy (requirements.txt); ffmpeg for videos; network access to AWS Terrain Tiles for elevation (no key), and for a city at night to the OpenStreetMap Overpass API (cached after the first run). Everything runs on CPU.
Once installed, just ask. The skills look up the summit and a real viewpoint, fetch the elevation, render a small draft, look at it, then render the final.
- "Make me an X header of Mount Rainier from Seattle in the engraved-line style."
- "LinkedIn banner of the Grand Tetons as a black woodcut, big TETONS title."
- "Show me Denali in every style so I can pick one."
- "A 6-second looping orbit of the Matterhorn at night."
- "Build me an interactive page to play with Mount Hood from Portland."
- "Mont Blanc reflected in Lac Blanc at golden hour, photographic, no image model."
- "Sunset timelapse of Kilimanjaro from Amboseli, into the night."
- "A glass of whiskey with two ice cubes on walnut, window light. No Blender."
- "Turn this photo into a watercolour."
Or run the scripts yourself. From any writable folder, with SK pointing at the installed skill:
SK=~/.claude/skills/procedural-terrain-art
python $SK/scripts/render.py --peak 46.8523,-121.7603 --from 47.6062,-122.3321 \
--style survey --size 3000x1000 --label "Mount Rainier|4392 m" --out rainier.pngThat exact command, unedited, on a mountain none of the tests use (15 s):
Each SKILL.md has the full workflow, and references/ covers the engine, scene format, terrain features and painting presets.
build_studio.py writes one HTML file (about 0.76 MB) with a 512 × 512 elevation grid inside. Orbit the mountain, move the light, change the ink, and save a 3000 × 1000 PNG. No server and no libraries; the only network request is for web fonts. Five are live on the site: Ararat, Fuji, Matterhorn, Denali and the Grand Canyon. The same pages work as claude.ai artifacts, where the Save button uses the artifact download capability: see the Ararat studio and the showcase on claude.ai.
The Ararat studio is also on Artifact Shelf, a gallery of my single-file HTML artifacts.
Prints. Elevation tiles become a grid aligned with the camera, rows running away from the viewer. Rows are projected near to far with a perspective camera, and a floating horizon per pixel column hides anything behind what's already drawn. A G-buffer records which row owns each pixel, so every style can sample height, shade and snow per pixel. Everything is normalised to a reference mountain, so a 1 km hill and an 8 km giant both fill the frame without retuning. Engine notes.
Photographs. Each pixel's ray marches a 40 m heightfield (with Earth curvature) until it hits ground, then asks the sky how much light reaches that point and how much air lies between it and the camera. Near-field instances (water, trees, houses, lights) are traced separately. Renders run in resumable row bands. Terrain features · What we learned.
Glass. Unidirectional path tracing with next-event estimation, MIS, Russian roulette, Fresnel and Beer-Lambert absorption, spectral dispersion, and an adaptive sampler that spends samples where noise is high. Scene format.
One CPU core:
| Output | Time |
|---|---|
| Print style, 3000 × 1000 | 5–15 s |
| All six styles + contact sheet | ~40 s |
| Studio page | ~5 s to build |
| Photographic terrain, 3000 × 1000 | 3–12 min (resumable) |
| Timelapse, 20 s at 1200 × 400, every frame rendered | ~6 hours (resumable; --blend 2 halves it) |
| Clean still life, 2400 × 800 | ~1 hour (resumable) |
| Painting, 3000 × 1000 | 10–60 s |
What works and what doesn't: light, atmosphere, glass, metal and real terrain at a distance look right. Trees, houses and walls within about 60 m look rendered rather than photographed; city buildings are boxes with guessed heights; paintings soften fine detail on noisy sources; organic shapes like petals are out of reach for the path tracer. The skills say so when a request lands there.
.claude-plugin/ plugin.json and marketplace.json (Claude Code)
skills/
procedural-terrain-art/ SKILL.md, scripts/, references/, assets/studio_template.html, evals/
procedural-realism/ SKILL.md, scripts/, references/, scenes/*.json, evals/
evals/ claude plugin eval cases (should-trigger, should-not-trigger)
docs/ GitHub Pages: the showcase, the Any mountain app (docs/app), five studios, media
scripts/ build-skills.sh (the Claude.ai packages), build-app.py (docs/app/engine.js), regression_terrain.py
Both skills ship the same scripts/dem.py; the build refuses to package them if the copies differ.
claude plugin eval . --allow-tools Write BashFour should-trigger cases render real drafts and have an LLM judge look at the PNG; four should-not-trigger cases (Blender settings, a Midjourney prompt, a QGIS how-to, a plain fact) assert neither skill fires. Each skill also carries skill-creator evals. See evals/README.md.
Pictures welcome. See CONTRIBUTING.md: change a skill, render a small before/after, run scripts/build-skills.sh, and if you touched the terrain engine, run the regression sheet. Made something with the skills you're proud of? Open an issue with the image and the prompt.
Elevation data: Terrain Tiles on AWS (SRTM, GMTED, ETOPO1 and other public sources; see the attribution list). Street data for the city lights: © OpenStreetMap contributors, available under the Open Database License. Summit and viewpoint coordinates were looked up from public sources for each example. Built with Claude.





















