feat(client): cliff legibility via ambient occlusion (#245) #247

Merged
panda merged 10 commits from feat/cliff-faces into main 2026-08-01 21:08:11 +02:00
Collaborator

Summary

Makes hard terrain Z-steps read as cliffs — so relief is legible and you can tell where you
can't walk — procedurally, with no art, keeping the clean hillshade look (#245).

The same per-vertex hillshade the ground already computes is now multiplied by an ambient-occlusion
term: the foot of a steep step is darkened by how much the surrounding higher ground towers over it
(distance-weighted, non-directional), so a cliff reads as depth from every iso angle — no new
geometry, pass, shader, or asset. TerrainOcclusion (Client.Core, MonoGame-free, unit-tested) holds
the maths; GroundBlendRenderer.Hillshade multiplies it in.

Two richer approaches were built and rejected on the live client before this one (see the design
doc for the full story): rock-textured vertical skirt faces (only S/E faces exist in the fixed iso
camera → empty corners) and rock-textured slopes (too artificial — worse than plain hillshade). AO is
the smallest, cleanest fix and the one the owner signed off on live.

Design + the rejected-approaches history: docs/superpowers/specs/2026-08-01-cliff-ambient-occlusion-design.md.

Client-only — no wire/protocol/server/persistence change; MaxStepZ walkability is untouched.

Screenshots / recording

Debug harness, fresh DB, admin test, at asterra volcanic relief (~7559,4956). The terraced relief
reads as raised blocks with shadowed feet; the lava edge gets a soft occlusion ring — the clean
hillshade look, now with the steps legible from every angle.

cliff ambient occlusion

How it was tested

  • Unit (tests/IsoMmo.Client.Core.Tests/TerrainOcclusionTests.cs): flat = unoccluded; the foot of
    a tall step darkens to the strength floor; a cell that towers over its neighbours is open; farther
    high ground occludes less (distance-weighted).
  • Visual gate (Windows, fresh DB): piloted the client to asterra relief and tuned the constants
    (AoRadius 4 / AoScale 8 / AoStrength 0.6) live to the owner's sign-off.
  • Gates: dotnet csharpier check . clean · dotnet build IsoMmo.slnx 0 warnings / 0 errors ·
    dotnet test IsoMmo.slnx all green (743 tests).

Checklist

  • just lint passes (CSharpier + analyzers, zero warnings)
  • just test is green
  • The whole solution builds (client and tools included)
  • Multi-platform preserved (pure MonoGame + Client.Core, no shader change, no OS-specific deps)
  • Tests added/updated for this change (TerrainOcclusionTests)
  • Linked the related issue (#245) and its Definition of Done is met
## Summary Makes hard terrain **Z-steps read as cliffs** — so relief is legible and you can tell where you can't walk — **procedurally, with no art**, keeping the clean hillshade look (#245). The same per-vertex hillshade the ground already computes is now multiplied by an **ambient-occlusion** term: the foot of a steep step is darkened by how much the surrounding higher ground towers over it (distance-weighted, **non-directional**), so a cliff reads as depth **from every iso angle** — no new geometry, pass, shader, or asset. `TerrainOcclusion` (Client.Core, MonoGame-free, unit-tested) holds the maths; `GroundBlendRenderer.Hillshade` multiplies it in. Two richer approaches were built and **rejected on the live client** before this one (see the design doc for the full story): rock-textured vertical skirt faces (only S/E faces exist in the fixed iso camera → empty corners) and rock-textured slopes (too artificial — worse than plain hillshade). AO is the smallest, cleanest fix and the one the owner signed off on live. Design + the rejected-approaches history: `docs/superpowers/specs/2026-08-01-cliff-ambient-occlusion-design.md`. **Client-only** — no wire/protocol/server/persistence change; `MaxStepZ` walkability is untouched. ## Screenshots / recording Debug harness, fresh DB, admin `test`, at asterra volcanic relief (~7559,4956). The terraced relief reads as raised blocks with shadowed feet; the lava edge gets a soft occlusion ring — the clean hillshade look, now with the steps legible from every angle. ![cliff ambient occlusion](https://git.homelab.devncode.it/attachments/2e642719-a1a2-4d55-bdf4-7d358345187f) ## How it was tested - **Unit** (`tests/IsoMmo.Client.Core.Tests/TerrainOcclusionTests.cs`): flat = unoccluded; the foot of a tall step darkens to the strength floor; a cell that towers over its neighbours is open; farther high ground occludes less (distance-weighted). - **Visual gate** (Windows, fresh DB): piloted the client to asterra relief and tuned the constants (`AoRadius 4` / `AoScale 8` / `AoStrength 0.6`) live to the owner's sign-off. - **Gates**: `dotnet csharpier check .` clean · `dotnet build IsoMmo.slnx` 0 warnings / 0 errors · `dotnet test IsoMmo.slnx` all green (743 tests). ## Checklist - [x] `just lint` passes (CSharpier + analyzers, zero warnings) - [x] `just test` is green - [x] The whole solution builds (client and tools included) - [x] Multi-platform preserved (pure MonoGame + Client.Core, no shader change, no OS-specific deps) - [x] Tests added/updated for this change (`TerrainOcclusionTests`) - [x] Linked the related issue (#245) and its Definition of Done is met
panda merged commit 4e6d092ccc into main 2026-08-01 21:08:11 +02:00
panda deleted branch feat/cliff-faces 2026-08-01 21:08:11 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!247
No description provided.