---
id: ground-look-and-levels/007
title: A flank texture for mountains — the faces are wearing floor tiles
epic: ground-look-and-levels
state: ready
priority: 2
blocked_by: []
estimate: M
created: 2026-08-19
updated: 2026-08-20
claimed_by: null
claimed_at: null
delivers: []
review_artifact: null
---

## Why

Mountains became landform on 2026-08-19 (deliverable 16): a contiguous group of one flavour is
now one continuous massif in the floor mesh, with steep faces and a sheer foot. Those faces
currently wear **the flavour's own ground tile** — the same texture the flat floor of that cell
uses. It is honest and it reads as stone, but it is a top-down floor texture standing upright,
and on the steeper part of a face it smears.

The one texture in the game drawn *for* a vertical surface is `client/ground/special/cliff-face.png`,
and it is deliberately not used here: it is authored as exactly one level tall and seamless
left-to-right, so on a mountain flank three or four cells high it bands horizontally. The
shader suppresses it on mountain cells for that reason (`ground.gdshader`, the `mountain_w`
term).

## What to do

- **The brief is written** — `land-of-lor/docs/design/briefs/MOUNTAIN_FLANK_BRIEF.md` (2026-08-19),
  ready for Kris to paste into the session below. What follows is what it asks for, and stands
  as the spec if it needs rewriting: a **mountain flank** texture (or a small set — one per
  mountain flavour that has a shape today: the plain cone, the volcano, the blocky kind).
  **Kris reuses one Claude Design session for tile work** — https://claude.ai/design/p/373a1833-0687-48d5-9ee0-70784f613ff3
  — so this goes there rather than into a fresh project (`docs/design/README.md`).
  The brief goes in `land-of-lor/docs/design/briefs/`, and reads the v3 tile brief first so the
  palette and the "painted = seen, no motifs, one colour per family" rules carry over.
- The brief must state what the shader can actually use: the face is sampled by world position,
  the art must tile seamlessly in both directions (unlike the cliff face, which is one level
  tall by construction), and it must read at a phone's scale — a flank is only ~150 px on
  screen.
- Render candidates with the **area preview kit** (`docs/design/tiles/preview/`) before judging
  them: a single tile tells you nothing about how a whole massif looks. Add a mountain view to
  the kit if the existing two grids don't show one.
- Then wire it: a `flank_tex` uniform beside `face_tex` in `ground.gdshader`, chosen per cell
  by flavour, blended in by the existing slope term rather than a new branch — the mountain
  weight (`mountain_w`) and `cliff` factor are already computed. **No new texture reads on
  fragments that are not mountain**, and no measurable cost on the ground's GPU time (the
  perf readout and `LOR_SHOTS_PERF=1` are the check; the ground is currently 0.69–0.89 ms
  animated on the 60x60 Badlands).
- Re-take the Badlands shots and note the before/after in the handoff.

## Definition of done

The flank art is in the repo, the shader uses it on mountain faces only, `LOR_SHOTS_PERF=1`
shows no regression against the numbers above, the Godot suite is green, and the brief has
moved to `docs/design/historic/` per `docs/design/README.md`.

## Where the work lands

`land-of-lor/docs/design/briefs/`, `land-of-lor/game/world/client/ground.gdshader`,
`client/ground/`, `docs/handoff/ground-look-and-levels.md`.

---

## Experiment log — 2026-08-20 (tried on the phone, then rolled back)

The art came back from Claude Design and was wired in end-to-end as a **local experiment**,
run on Kris's phone, and then **rolled back**. Nothing shipped: no push, no APK upload, no
`/play` change. The three PNGs are still only in the handback package
(`~/Downloads/mountain-back-from-cd/ground/flank/`), not in the repo.

**Verdict (Kris, on the phone): not bad, but not better *enough*, and it came with a
performance cost.** Back to the drawing board.

### What was built

- `flank/{mountain,earth,fire}.png` into `client/ground/`, built by `ground_atlas.gd` into
  one 8x1 strip indexed by flavour (a flavour with no flank art fell back to its own
  mountain floor tile, so it was additive).
- One extra texture read in `ground.gdshader`, inside a branch only mountain fragments
  enter — flat ground, banks, ramps and cliff faces were untouched. The bank's 22%
  darkening stepped aside where the flank took over, so a face was cut once (~25%), not
  twice (~41%).
- Two settings of the slope gate were tried and judged against renders and on the phone.

### What was learned

**The slope gate has no good setting, and that is the finding.** A landform massif is a
shallow dome about a cell tall, so almost none of its surface is truly sheer:

- **Steep gate** (on past ~64 deg): the flank hid in a sliver at the foot. Kris could not
  see that the mountains had changed at all.
- **Gentle gate** (on past ~26 deg): the flank clad the whole cone and the mountains
  clearly changed — but a flat texture projected across a curved surface produced visible
  wavy undulations, and the bedding closed into contour rings over the crown.

Cost was small but real: 0.53-0.62 ms on the 60x60 Badlands (laptop iGPU) against a
0.69-0.89 ms baseline, i.e. inside the noise, plus one texture read per mountain fragment.
Small is not free, and the rule Kris applied is the right one: a cost has to buy a
visible win.

### Root cause, and the recommendation

**The mesh carries no UVs.** `ground_mesh.gd` emits position only; every texture in the
ground — floor tiles, the cliff face, and this flank — is projected from *world position*
in the shader. On flat ground and on a sheer wall that projection is exact. On a curved
mountain face it is not: the texture is projected through the curve rather than laid along
it, which is exactly what the undulations are.

So the fix is **in the mesh, not in the landform's shape**. Kris's instinct here was right
and the first analysis written in-session (that the mountain needed real flat faces to clad)
was the weaker answer — worth noting because it would have sent the next session at the
wrong problem. Unwrapping the massif's surface and giving those vertices real UVs lets a
single texture be laid along the surface, stretching with it, no projection error and no
gate to tune: the whole flank/floor question stops being a slope threshold and becomes
"where does the UV shell start". That is a bigger change than this task assumed, and it
touches the mesh builder that `002` made pure and tested.

**Still worth exploring, and NOT closed off by the above:** different textures for
different results. Only these three were tried, all in the same painted-strata family. A
flank with less directional bedding, or one authored to tolerate curvature, may well read
fine even under the current world-position projection — that is a cheap thing to test and
should be tried before committing to UV work.

### Where to pick this up

Nothing to undo — the repo is at `9f67b74` and the phone was rebuilt back to clean v18.
The brief stays in `land-of-lor/docs/design/briefs/` (it has NOT moved to `historic/`,
because it has not been satisfied). The Claude Design session is unchanged and still holds
the flank work if the art is wanted again.