# Terrain Material Layers And Weight Painting (#24)

> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.

## Scope

- Persist up to four shared Material/Material Instance references on each `TerrainDesc`.
- Store normalized RGBA8 layer weights per height sample with an implicit channel-zero default.
- Blend layer albedo, normal, metallic, and roughness in the project-owned raster material path.
- Assign, clear, reorder, and tile layers from the Terrain inspector.
- Paint or erase one selected layer from the existing horizontal viewport toolbar.
- Preserve one reflected history transaction per completed pointer stroke and exact cancel restore.

## Implementation

1. Extend the backward-compatible terrain schema with four layer descriptors and compact weights.
2. Emit normalized weights as terrain chunk vertex colors and attach a runtime-only material binding.
3. Build a terrain-specific `ExtendedMaterial` in `blacksite_surface`; keep invalid references on the visible fallback path with diagnostics.
4. Add inspector layer controls and a mutually exclusive modal paint operator beside Sculpt.
5. Cover serialization, validation, blend transport, paint normalization, cancel, undo, and redo.
6. Update ADR 0040, terrain workflow docs, the implementation checklist, and live evidence.

## Acceptance

- Two or more project materials visibly blend on one terrain.
- Layer weights remain exactly normalized and survive scene save/load.
- Live paint preview follows the sampled terrain surface.
- Escape/right-click restores exact pre-stroke weights; release creates one undo entry.
- Missing or invalid material references remain visible as fallback and produce clear diagnostics.
- Formatting, workspace check/clippy/tests, level validation, and live native-Wayland QA pass.
