render3d: a README note on painted ground layers, and the changeset
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
54e267dfa6
commit
530956889b
2 changed files with 48 additions and 0 deletions
13
changes/ground-painted-zones.md
Normal file
13
changes/ground-painted-zones.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
bump: minor
|
||||||
|
type: feat
|
||||||
|
**`ludic.render3d`: painted ground layers grow solid things, with ids, and the trample is data.**
|
||||||
|
`ground_fill`'s candidate is its own function, `ground_candidate` (pure `gf_*` steps with the density read
|
||||||
|
between them, into a caller-held `GroundCand`), and `ground_fill` draws exactly its answers - the same
|
||||||
|
operations in the same order as before, so every cover layer grows bit for bit what it did. A layer with
|
||||||
|
`solid: true` is filled at `step0` with band 0's hashes whatever the camera, a far band drawing a stable
|
||||||
|
subset; each thing has an int id from (layer, chunk, cell) (`ground_solid_id`), and `ground_solid_list` /
|
||||||
|
`ground_solid_at` answer a chunk's things or one by id for physics, the nav bake and saves.
|
||||||
|
`r3d_ground_clearing(x, z, r_in, r_out, floor)` hands the trample over as discs the editor can see, beside
|
||||||
|
the `r3d_on_ground_trample` callback, which still works. `tests/ground_fill_test.ludic` holds all of it to
|
||||||
|
`tests/ground_fill_golden.json` (written by `tests/gen/ground_fill_golden.ludic`), the file the studio's
|
||||||
|
TypeScript generator is tested against.
|
||||||
35
packages/ludic.render3d/README.md
Normal file
35
packages/ludic.render3d/README.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# ludic.render3d
|
||||||
|
|
||||||
|
A physically based 3D renderer over Vulkan. `FEATURES.md` lists what is implemented and where.
|
||||||
|
|
||||||
|
## Painted ground layers
|
||||||
|
|
||||||
|
A ground layer is a density painted over the map (R the chance a cell keeps one, G its scale, 2 m texels
|
||||||
|
baked into an LGD2 file, `ground_density.ludic`) and a `GroundFill` row of numbers. Everything it grows is
|
||||||
|
a pure function of those two - the same on every machine and in the editor's preview.
|
||||||
|
|
||||||
|
- **The candidate** (`ground_cand.ludic`): for (layer, chunk, band, cell) `ground_candidate` answers
|
||||||
|
whether one stands there and its x, z, scale, yaw, seed and wind, into a `GroundCand` the caller holds.
|
||||||
|
Its steps are pure: `gf_along` (the jitter, draws 0 and 1), `gf_keeps` (draw 2 under the chance),
|
||||||
|
`gf_scale` (G and draw 6), `gf_yaw` (3), `gf_seed` (4), `gf_wind` (5). `ground_fill` draws exactly
|
||||||
|
these. Numbers are IEEE single precision, `Math.lerp` is `a + (b - a) * t`, `gf_hash` is 32-bit
|
||||||
|
integer arithmetic with a logical `>>`, and the model shader turns local (x, z) to
|
||||||
|
`(c x + s z, -s x + c z)` - three.js's rotation about +Y.
|
||||||
|
- **Cover and solid.** A cover layer (grass, flowers, pebbles) is filled at its band's step, so a far
|
||||||
|
band is a different, sparser sample. A layer with `solid: true` (rocks, trees) is filled at `step0`
|
||||||
|
with band 0's hashes whatever the band, and a far band draws the subset whose draw 7 falls under
|
||||||
|
`(step0 / step_band)^2`; its scale ignores `band_grow`. Nothing solid moves with the camera.
|
||||||
|
- **Solid ids** (`ground_solid.ludic`): `ground_solid_id(layer, cx, cz, i, j, cells)` =
|
||||||
|
`((layer * 256 + cz + 128) * 256 + cx + 128) * 512 + i * cells + j`, a positive 31-bit int, stable
|
||||||
|
while the painting under it is. It holds chunks -128 .. 127 about the stream's corner and at most 22
|
||||||
|
cells a chunk side (a step of at least 32 / 22 m on 32 m chunks); a cell past that has no id and is
|
||||||
|
not grown. `ground_solid_list` fills a caller's `GroundSolids` (made once, `ground_solids_new`) with a
|
||||||
|
chunk's things for physics, the nav bake or a save; `ground_solid_at` answers one by id.
|
||||||
|
- **The trample as data** (`ground_clear.ludic`): `r3d_ground_clearing(x, z, r_in, r_out, floor)` hands
|
||||||
|
over a clearing - `floor` inside `r_in`, back to full at `r_out` on a smoothstep, the shape of the
|
||||||
|
camp's ring and the town's yard. A layer with `trample` multiplies its chance by the game's callback
|
||||||
|
(`r3d_on_ground_trample`, kept for now) and then by every clearing. A game should use one or the other.
|
||||||
|
- **Conformance**: `tests/ground_fill_test.ludic` holds the package to `tests/ground_fill_golden.json`
|
||||||
|
(gf_hash, lerp, yaw, one cover chunk and one solid chunk over a hand-written density), which the
|
||||||
|
studio's own test reads. After a deliberate change, rebuild it from the repository root:
|
||||||
|
`bin/ludic run packages/ludic.render3d/tests/gen/ground_fill_golden.ludic --headless`, and commit it.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue