feat: actors stage 1

This commit is contained in:
Dan Finch 2026-08-07 16:58:24 +02:00
parent bd88d3cbd6
commit 4869db01e5
5 changed files with 112 additions and 60 deletions

View file

@ -116,13 +116,15 @@ rules live in `.agents/rules/*.md`.
`TREE_/BOULDER_/BUSH_/FLOWER_COUNT`/`_SEED`/`_REACH`) and the roaming mobs
scattered (`placeMobs`; `FROG_/BEE_COUNT`, `MOB_SEED`, `MOB_REACH` — mobs move,
so they carry no baked colliders), then `buildChunks` bakes
terrain + props into a `CHUNK_GRID` x `CHUNK_GRID` grid of `Chunk`s (each =
per-texture meshes grass/bark/birchBark/leaf/needle/rock/flowers + a tight AABB) that
`main` frustum-culls; bushes fold into the leaf mesh, flowers get their own
(drawn double-sided). Trees + boulders are baked **twice** — full geometry and
a low-poly impostor (`barkFar/leafFar/needleFar/rockFar`, via the builders'
`lod` arg) — so a far chunk can swap to the cheap set with no per-frame work
(see `chunkFar` / `RenderConfig.lodDistance`). `Aabb` colliders (walls, crate, grown trunks, big
terrain + props into a `CHUNK_GRID` x `CHUNK_GRID` grid of `Chunk`s (each = a
tight AABB + two `DrawGroup[]` lists, `near`/`far`, where a `DrawGroup` is a baked
mesh + its `Material` = texture + cull; the renderer just loops them and knows no
content by name) that `main` frustum-culls; bushes fold into the leaf mesh,
flowers get their own (double-sided) group. Trees + boulders are baked **twice**
full geometry into `near` and a low-poly impostor into `far` (via the builders'
`lod` arg) — so a far chunk swaps to the cheap group set with no per-frame work
(see `chunkFar` / `RenderConfig.lodDistance`). `buildLevel(textures)` binds the
ground/prop materials once and shares them across chunks. `Aabb` colliders (walls, crate, grown trunks, big
boulders), NPC position, `TERRAIN`/`TERRAIN_SUBDIV`/`GROUND_UV`, sky/cloud config. The stone floor is lifted by `FLOOR_LIFT` (a z-bias) so it
stays clean over the terrain skirt that laps under the room edges. Room surfaces
are single flat quads -- no subdivision needed since texturing is
@ -164,11 +166,12 @@ whole window (cost grew with window size); present is now ~0.2ms.
`renderBand` runs `renderScene.renderBand` for rows [y0,y1): `Sky.render` at
1/`SKY_STEP` res (fills color + resets depth, replaces a clear) → `Rasterizer.draw`
floor/walls/crate (room, always) → for each visible `Chunk` draw grass, then —
per chunk via the pure `chunkFar` test (dist² from camera to the chunk AABB vs
`lodDistance²`) — either the full rock/bark/leaf/needle + flowers, or the cheap
`rockFar/barkFar/needleFar/leafFar` impostor meshes (foliage detail dropped).
All backface-culled except double-sided flowers → `Sprite.billboard(npc)`
floor/walls/crate (room, always) → for each visible `Chunk`, loop its draw-groups —
`near` or `far` chosen by the pure `chunkFar` test (dist² from camera to the chunk
AABB vs `lodDistance²`): `near` is grass + full trees/rocks + flowers, `far` is grass
+ the cheap impostors (foliage/flowers dropped). Each group draws with its own
`Material` (cull per-material, so solids backface-cull and flowers stay double-sided)
`Sprite.billboard(npc)`
the roaming mobs (each: shared local mesh × its `Mat4.compose` model matrix,
double-sided) → `Framebuffer.quantize`. `chunkFar` is pure (camera + baked bounds + config
only), so every worker band picks the same LOD for a chunk → no horizontal seam.