---
id: ground-look-and-levels/001
title: The look — unshaded ground, sink depths, tile pointers with a flat fallback
epic: ground-look-and-levels
state: done
priority: 1
blocked_by: []
estimate: S
created: 2026-08-18
updated: 2026-08-18
claimed_by: null
claimed_at: null
delivers: []
review_artifact: land-of-lor/docs/handoff/ground-look-and-levels.md
---

## What to do

Decisions 1, 2 and 10 of the workshop note (`land-of-lor/docs/design/2026-08-18-ground-look-and-levels-workshop.md`).

- `game/world/client/ground.gdshader`: `render_mode unshaded`; the shading the ground needs is
  drawn here — darken by slope (the normal is available), a darker rim where a surface steps
  down (bank of water/lava/sand; later the cliff faces of 002), so a step reads as a drawn edge.
- `game/shell/elements.js` (`sync-elements.sh` after): the ground *type* carries a `sink`
  (cells: water and lava 0.25, sand 0.125, the rest 0) in place of `kind: sunken`; keep
  `kind` for `mountain` only if something still needs it — prefer one field with one meaning.
  Each hexagram's `groundVariant` gains an optional `tile` (a `<lower>/<upper>` file id;
  several hexagrams may point at one file); no `tile` → the flat `colour`. Delete the
  `pattern` fields and the procedural pattern painter in `ground_atlas.gd` (`draw_tile`) — dead
  the moment tiles are pointers; the atlas is: PNG if pointed at and present, else a flat fill.
- `ground_mesh.gd` / `world_units.gd`: `SUNKEN_DEPTH` becomes the per-type sink; the standing
  height on sand is the sand's own surface (no submerging — `ENTITY_SINK` is for water/lava).
- Shots: `_shots.gd` gains `LOR_SHOTS_ONLY=ground` (only the ground shots) — the lab in the
  workshop session needed it; note in `game/README.md` that Godot re-imports changed PNGs only
  from the editor or `godot --headless --path world --import`.

## Definition of done

`test_runner.gd` green (mesh rules updated for sink), the ground shots on the Badlands and the
Village show sand a step down with a drawn rim and no lighting lift, `sync-elements.sh` run,
director tests green (the TS table reader follows the field change). Committed and pushed.

## Where the work lands

`land-of-lor/game/world/client/`, `game/shell/elements.js`, `game/director/src/groundTypes.ts`.

## What was done (2026-08-18, laptop workshop session)

Built and shipped the same day (APK v15, `/play` at `e34e8ba`). The ground shader is
`unshaded` — painted = seen — and shades banks, ramps and cliff faces itself; sand sinks an
eighth (`sink` per type in `elements.js`, `kind: flat|liquid|mountain`, `plain` per type); tiles
are `tile` pointers (28 named; no tile = flat colour, deliberately) and the pattern painter is
gone; bodies carry a blob shadow and the sun's shadow pass is off (an unshaded ground can't
receive shadow maps — the build's call, in the handoff); `LOR_SHOTS_ONLY=ground`, and the
re-import gotcha is in `game/README.md`. Handoff: `land-of-lor/docs/handoff/ground-look-and-levels.md`.