islaApocalypse/Client/README.md
beezm 3b5bc5e5d6 docs: water at rest across the Core/Client/Server READMEs (terrain-water task 13)
Core: BlockRegistry gains WATER, with the reason it is wire-safe (block IDs
are never serialized) AND the reason it is a registry identity only rather
than a voxel the terrain path writes. Corrects the now-false line "Nothing
at runtime consumes the water data yet" -- it does, as of this task.
ChunkData's new per-column water fields and the Constants tunables.

Client: how the water sheet is built and, more importantly, WHY it is a
second mesh instead of a block in the density field -- the trap here is
that writing water into a Marching-Cubes field fuses it into the terrain
instead of laying it on top, and that is not obvious until you have done
it. Notes translucency came free from the separate material.

Server: the per-column water rule, which section is the authority for what
(WBID presence, WSRF level, WBTB fallback), that an unknown body leaves the
column dry rather than guessing, and why depth for shading comes from
blueprint heights rather than the clamped rendered geometry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 02:33:06 -04:00

44 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Client Module
The visual layer. Takes finished chunk data and turns it into Godot nodes. It calculates nothing —
no densities, no terrain, no collision.
## `ChunkRenderer.cs`
A `MeshInstance3D` created per chunk by the server, which then calls `RenderChunk(data)`.
- **Mesh generation.** Calls `MarchingCubes.GenerateMesh()`, passing the density field, the block
IDs, and the per-column data the mesher needs to colour correctly: the true (unrounded) surface
heights, the biome per column, and the road surface material per column.
- **Vertex colouring.** Creates a `StandardMaterial3D` with `VertexColorUseAsAlbedo = true`, so Godot
renders the per-vertex colours the mesher assigned rather than a texture. Colours fade between
materials across a tunable band instead of switching at whole-metre steps.
- **World positioning.** `ChunkPosition × CHUNK_SIZE × VOXEL_SCALE` on X and Z, `y = 0` — chunks are
placed by their footprint and carry their full height internally.
- **Backface rendering.** `CullMode` is disabled, so the world is still visible from underneath or
from inside terrain.
- **Water at rest** (task 13). `BuildWaterSurface` adds a second `MeshInstance3D` as a child, a flat
sheet at each cell's water level, from the per-column water data the server read out of the
blueprint. Skipped entirely for chunks with no water.
**Why a separate mesh rather than a water block.** The terrain is a Marching-Cubes iso-surface
over the density field. Putting water into that field would not lay a sheet on top of the seabed —
it would move the iso-surface, fusing the sea into the terrain as if it were solid ground. A
second surface is the only way water can sit at *its* level independent of the ground beneath it.
That also makes translucency nearly free: a distinct `MeshInstance3D` carries its own
`StandardMaterial3D`, so alpha is one flag and Godot sorts transparent surfaces after opaque ones
itself. Colour and alpha both ramp with depth (shallow teal and clearer → deep navy and near
opaque), so the shelved coast stays readable.
Water is **flat and static** — no waves, no displacement, no animation. Those are Phase C2+.
## Notes
- **One material instance per chunk.** Each renderer builds its own `StandardMaterial3D`. Since they
are all identical, a single shared material would do — an easy win whenever performance work starts.
- Chunk positioning is relative to this node's parent, so **moving the `World` node in the scene
moves the entire rendered world** with it.
## Not here yet
No textures or UV mapping (raw vertex colour only), no LOD, no player, no UI, no input handling.