perf(render3d): the terrain's height and normal in R32F + RG16F, 128 MB where one RGBA32F was 256

The first generation pass's R32F height is kept as ter_height_tex (not copied into an RGBA32F),
so every reader of the height - placement, the read-back, physics, selftest16's 9 mm - sees the
same 32 bits. ternormal.frag writes the baked normal's x and z into ter_normal_tex (RG16F), and
the six places that read it (terrain.frag twice, tersun.frag, grass.vert, grass.mesh,
grass_cull.comp, which takes a third texture at binding 6) rebuild y. SPIR-V regenerated.

Maroon Lake's play, headless Vulkan: 2793 -> 2647 MB. The camp's frame: 0.066% of pixels differ by
more than 8 (mean 0.024/255), isolated grass blades at the slope gate. ludic-dev test 307/307.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 02:31:18 +03:00
parent f1049953c4
commit 1675eb451f
26 changed files with 77 additions and 36 deletions

View file

@ -0,0 +1,8 @@
bump: patch
type: perf
**The terrain's height field takes half the GPU memory.** The baked height and surface normal
shared one 4096^2 RGBA32F (256 MB); the height now stays alone in its R32F - the same 32 bits
every placement, the CPU read-back and physics read - and the normal goes beside it as x and z in
an RG16F (`ter_normal_tex`, bound as `u_ter_normal`), y rebuilt where it is read: 128 MB. The grass
cull takes it as a third texture (binding 6). In Maroon Lake's play: 2793 -> 2647 MB; the camp's
frame differs in 0.066% of pixels by more than 8, single grass blades at the slope gate.