The forest grows Poly Haven's scanned firs and island trees, their leaves cut out from alpha textures and their trunks blocking through low-poly proxies #16

Merged
agra merged 6 commits from task/3896-the-forest-s-trees-look-like-toys-flat-c into master 2026-10-29 20:06:40 +02:00
Owner

Tracker: #3896

The first map's forest of Kenney toy trees becomes 900 of Poly Haven's CC0 scanned trees at their real heights, with bark and leaf textures: 603 firs (fir_tree_01, 12 to 16 m tall) and 297 small coastal broadleaves (island_tree_02, 3 to 4.5 m).

  • Trees. assets/prefabs/polyhaven_tree.py makes each prefab from the tree's downloaded Poly Haven .blend, reduced to what a forest can draw: the fir from its 54927-triangle LOD2 to 26507 triangles (trunk decimated to a tenth, branches to a half, every needle card kept), the island tree from its 322050-triangle LOD1 to 41009 (trunk and twigs decimated, 12% of its leaf clusters kept, each grown 2.2 times). Each texture is an 8-bit PNG under assets/textures/, the leaf ones RGBA from the diffuse and alpha maps; every .blend and texture has a .md naming its source URL, size, MD5, publication date and CC0 licence. The Kenney tree prefabs are gone; the shipwreck stays Kenney's.
  • Alpha-cut leaves. A material whose Principled Alpha is fed by the Alpha of the Image Texture feeding its Base Color is a cut-out. hulken draws it in the opaque pass, discarding fragments whose alpha, raised a quarter per mip level so far leaves stay full, is under one half: no sorting. Both faces are lit, each with its own facing normal. The stage stores a texel's colour times its alpha, so that a mip averages only the covered texels' colours, and the cut-out shader divides the alpha out: a cut-out draws its texture's own colour at every distance, as Blender draws a cut-out's straight colour, rather than darkening with each mip level. The stage refuses a non-opaque image to a material that is not a cut-out.
  • Collision proxies. A mesh whose custom property hulken_collision is true, every ray visibility off so Blender renders nothing of it, collides and draws nothing. Each tree's trunk collides through an 8-sided, 22-triangle frustum; nothing the tree draws collides. The first map's world file shrinks from 17.9 to 12.5 MB.
  • Cost. tools/forest_bench.sx draws 672 views (a 20 m grid of eyes standing in the forest, 8 yaws each) at 1280x800 offscreen on Metal, keeps each view's fastest of 3 frames, begun to drained, and prints the slowest. On m5, in one session: the Kenney forest of master's first_map.blend 0.62 ms slowest (0.24 ms mean); this branch 4.29 ms slowest (3.20 ms mean), within the 8.3 ms budget. The trees need no distance LODs at this cost, so the bake reads none.
  • Lighting stays in gamma space, as the rest of the scene lights.
  • Tests. tests/bake_extract.py gains 13 cases (the cut-out read and its refusals, among them a texture's Color into Alpha, the proxy read, instanced, and its refusals), its water case feeds the water's Alpha from the texture feeding its Base Color, and its linked-prefab case links the fir and its proxy; tests/bake_stage.sx pins the cut-out flag, the premultiplied texel, the refusal and the proxies' triangles in the world alone; tests/cutout_draws.sx draws a checker of opaque and clear texels minified to mip levels 2 and 3 as a cut-out, which must draw the opaque colour as a quad of that colour does; tests/first_map_world.sx pins a fir's trunk keeping a walker clear of its axis and a body falling through its crown to the ground; tests/first_map_views.sx compares a forest view with tests/pixels/forest-metal.png, which fails on master's Kenney forest (138882 of 144000 pixels). Each of 25 mutants of the new rules fails a test.

Agra's check in the app, that the forest looks realistic, is still to come.

Tracker: [#3896](https://sak.swipelab.com/tasks/3896) The first map's forest of Kenney toy trees becomes 900 of Poly Haven's CC0 scanned trees at their real heights, with bark and leaf textures: 603 firs (`fir_tree_01`, 12 to 16 m tall) and 297 small coastal broadleaves (`island_tree_02`, 3 to 4.5 m). - **Trees.** `assets/prefabs/polyhaven_tree.py` makes each prefab from the tree's downloaded Poly Haven `.blend`, reduced to what a forest can draw: the fir from its 54927-triangle `LOD2` to 26507 triangles (trunk decimated to a tenth, branches to a half, every needle card kept), the island tree from its 322050-triangle `LOD1` to 41009 (trunk and twigs decimated, 12% of its leaf clusters kept, each grown 2.2 times). Each texture is an 8-bit PNG under `assets/textures/`, the leaf ones RGBA from the diffuse and alpha maps; every `.blend` and texture has a `.md` naming its source URL, size, MD5, publication date and CC0 licence. The Kenney tree prefabs are gone; the shipwreck stays Kenney's. - **Alpha-cut leaves.** A material whose Principled Alpha is fed by the Alpha of the Image Texture feeding its Base Color is a cut-out. hulken draws it in the opaque pass, discarding fragments whose alpha, raised a quarter per mip level so far leaves stay full, is under one half: no sorting. Both faces are lit, each with its own facing normal. The stage stores a texel's colour times its alpha, so that a mip averages only the covered texels' colours, and the cut-out shader divides the alpha out: a cut-out draws its texture's own colour at every distance, as Blender draws a cut-out's straight colour, rather than darkening with each mip level. The stage refuses a non-opaque image to a material that is not a cut-out. - **Collision proxies.** A mesh whose custom property `hulken_collision` is true, every ray visibility off so Blender renders nothing of it, collides and draws nothing. Each tree's trunk collides through an 8-sided, 22-triangle frustum; nothing the tree draws collides. The first map's world file shrinks from 17.9 to 12.5 MB. - **Cost.** `tools/forest_bench.sx` draws 672 views (a 20 m grid of eyes standing in the forest, 8 yaws each) at 1280x800 offscreen on Metal, keeps each view's fastest of 3 frames, begun to drained, and prints the slowest. On m5, in one session: the Kenney forest of master's `first_map.blend` 0.62 ms slowest (0.24 ms mean); this branch 4.29 ms slowest (3.20 ms mean), within the 8.3 ms budget. The trees need no distance LODs at this cost, so the bake reads none. - **Lighting** stays in gamma space, as the rest of the scene lights. - **Tests.** `tests/bake_extract.py` gains 13 cases (the cut-out read and its refusals, among them a texture's Color into Alpha, the proxy read, instanced, and its refusals), its water case feeds the water's Alpha from the texture feeding its Base Color, and its linked-prefab case links the fir and its proxy; `tests/bake_stage.sx` pins the cut-out flag, the premultiplied texel, the refusal and the proxies' triangles in the world alone; `tests/cutout_draws.sx` draws a checker of opaque and clear texels minified to mip levels 2 and 3 as a cut-out, which must draw the opaque colour as a quad of that colour does; `tests/first_map_world.sx` pins a fir's trunk keeping a walker clear of its axis and a body falling through its crown to the ground; `tests/first_map_views.sx` compares a forest view with `tests/pixels/forest-metal.png`, which fails on master's Kenney forest (138882 of 144000 pixels). Each of 25 mutants of the new rules fails a test. Agra's check in the app, that the forest looks realistic, is still to come.
A material whose Principled Alpha is fed by the Alpha of the Image Texture
feeding its Base Color is a cut-out: hulken discards the fragments whose
texel alpha, raised a quarter per mip level, is under one half, and the
stage scales a clear texel's colour by its alpha, as Blender draws it. A
mesh whose custom property hulken_collision is true, every ray visibility
off, is a collision proxy: the stage puts its triangles into the world file
alone.
assets/prefabs/polyhaven_tree.py makes fir_tree_01 and island_tree_02 from
Poly Haven's .blend files: the wood decimated, the island tree's leaf
clusters thinned and grown, the bark and leaf textures as 8-bit PNGs, the
leaves cut out, nothing drawn colliding, and each trunk colliding through a
22-triangle proxy. first_map_prefabs.py replaces the Kenney forest with 900
of them. first_map_world pins a trunk that keeps a walker out and a crown a
falling body passes through, and first_map_views a golden of the forest.
Decimated to a tenth with the trunk, the branches collapsed into flat
wedges up to 0.96 m² where none of the source's passes 0.01 m²; each wood
material now takes its own share, the branches' largest triangle 0.018 m².
agra merged commit 4d035736da into master 2026-10-29 20:06:40 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
sx/hulken!16
No description provided.