Prefabs draw instanced: the forest and the shipwreck on the ocean floor #14

Merged
agra merged 6 commits from task/3888-prefabs-draw-instanced-the-forest-and-th into master 2026-10-29 13:45:44 +02:00
Owner

Tracker: #3888

Step 6 of plan #3570. The bake keeps each instanced geometry once, with one transform per instance, and hulken draws each of its material groups with one instanced draw. Tree prefabs from Kenney's Nature Kit and the wrecked ship from its Pirate Kit are imported into assets/prefabs/, and the first map gains a forest of 1500 trees on the island's northern half and a shipwreck on the ocean floor off the southern beach. Leaves carry hulken_collide false and do not collide.

Assets

Downloaded on 2026-10-29 (CC0, approved on #3888's comment of 2026-10-29) into a scratch directory outside the checkout. Each .blend and texture has a .md beside it naming the pack, its URL and version, the file it came from and CC0.

  • Kenney Nature Kit (kenney_nature-kit.zip, 10537521 bytes; kenney.nl lists 1.0, its License.txt 2.1): Models/GLTF format/tree_default.glb, tree_oak.glb, tree_pineDefaultA.glb and tree_tall.glb.
  • Kenney Pirate Kit 2.1 (kenney_pirate-kit.zip, 3154665 bytes): Models/GLB format/ship-wreck.glb and its texture Models/GLB format/Textures/colormap.png, written as assets/textures/ship-wreck_colormap.png, 8-bit RGB, texel for texel.

assets/prefabs/kenney.py imports each model into assets/prefabs/<model>.blend as the file's one collection, named for it, keeping the geometry, the UVs, the Base Color and any base-colour image and setting every other material value to a new material's. Each tree's leaf material gets hulken_collide false.

The bake

  • tools/bake/extract.py groups the render depsgraph's instances by their original object and evaluated mesh, read during the walk, and records each geometry's triangles once with every instance's matrix_world. Objects drawn as themselves are recorded as before, every instance's object and instancer are recorded in their roles and compared as before, and it reads each material's hulken_collide.
  • tools/bake/stage.sx writes each instanced geometry into the render file once, by material, with one column-major transform per instance in hulken's axes, and places every instance's triangles into the collision world, but those of a hulken_collide false material.
  • The render file (src/scene/baked_format.sx, version 3) gains prefabs and a per-mesh collides flag.

The renderer

An instanced variant of the scene shader places each vertex by its instance's transform and turns the normal by the cofactor matrix of the transform's 3×3 part, the inverse transpose times the determinant. Each prefab's material groups draw with drawIndexedInstanced over a buffer of its MeshInstance records set with setInstanceBuffer.

The map

assets/scenes/first_map_prefabs.py, run once over first_map.blend, links the prefabs by relative path and adds 1500 trees on forest-floor ground north of the island's centre, clear of the lake, the ruins, the cave and 8 m from every spawn marker, and the wreck at Blender (-20.5, -210.25), 28 m off the southern beach where the floor lies 16.8 m down, listing and half sunk, its deck about 16 m down.

Tests

  • tests/bake_extract.py: a local collection instanced three times, a collection linked from assets/prefabs/ instanced three times, a Geometry Nodes Cone on two points and Cube on two others (two geometries, 62 and 12 triangles, two matrices each), Object Info on three points, hulken_collide read and a non-boolean one refused. A grouped geometry's later instances keep their own rules: the last of the marker's three instancers hidden from the camera is refused, and a water box instanced three times gives a volume at each instancer. #3569's instance cases hold.
  • tests/bake_stage.sx: instance transforms in hulken's axes, each instance's triangles in the collision world, the hulken_collide false material's left out.
  • tests/instanced_draws.sx: five boxes drawn as instances of one box and as static meshes give the same pixels, every pixel opaque and every box's centre drawn. One box is turned and scaled non-uniformly, and one is mirrored, its static copy's corners taken the other way round as the stage takes them. With the shader's normal turned by the plain 3×3 it fails (4634 pixels differ), and so it does with the normal turned by the inverse transpose, the cofactor times the determinant's sign (2635 pixels).
  • tests/first_map_world.sx: the forest's 1500 trees and the wreck in the render file, the floor under the wreck 16 to 20 m deep with land within 30 m, and a body walked into a tree's trunk stops at it while standing in its leaves.
  • The Metal golden passes unchanged.

Mutants of the extract's key (original alone, the temporary object), its grouping, its roles and water volumes for a geometry's first instance only, and its hulken_collide read, of the stage's collision and transform, and of the renderer's draw and normal are each caught by these tests.

Gate full passed at 6723bb6 (gate run 808).

Tracker: [#3888](https://sak.swipelab.com/tasks/3888) Step 6 of plan #3570. The bake keeps each instanced geometry once, with one transform per instance, and hulken draws each of its material groups with one instanced draw. Tree prefabs from Kenney's Nature Kit and the wrecked ship from its Pirate Kit are imported into `assets/prefabs/`, and the first map gains a forest of 1500 trees on the island's northern half and a shipwreck on the ocean floor off the southern beach. Leaves carry `hulken_collide` false and do not collide. ## Assets Downloaded on 2026-10-29 (CC0, approved on #3888's comment of 2026-10-29) into a scratch directory outside the checkout. Each `.blend` and texture has a `.md` beside it naming the pack, its URL and version, the file it came from and CC0. - Kenney Nature Kit (`kenney_nature-kit.zip`, 10537521 bytes; kenney.nl lists 1.0, its `License.txt` 2.1): `Models/GLTF format/tree_default.glb`, `tree_oak.glb`, `tree_pineDefaultA.glb` and `tree_tall.glb`. - Kenney Pirate Kit 2.1 (`kenney_pirate-kit.zip`, 3154665 bytes): `Models/GLB format/ship-wreck.glb` and its texture `Models/GLB format/Textures/colormap.png`, written as `assets/textures/ship-wreck_colormap.png`, 8-bit RGB, texel for texel. `assets/prefabs/kenney.py` imports each model into `assets/prefabs/<model>.blend` as the file's one collection, named for it, keeping the geometry, the UVs, the Base Color and any base-colour image and setting every other material value to a new material's. Each tree's leaf material gets `hulken_collide` false. ## The bake - `tools/bake/extract.py` groups the render depsgraph's instances by their original object and evaluated mesh, read during the walk, and records each geometry's triangles once with every instance's `matrix_world`. Objects drawn as themselves are recorded as before, every instance's object and instancer are recorded in their roles and compared as before, and it reads each material's `hulken_collide`. - `tools/bake/stage.sx` writes each instanced geometry into the render file once, by material, with one column-major transform per instance in hulken's axes, and places every instance's triangles into the collision world, but those of a `hulken_collide` false material. - The render file (`src/scene/baked_format.sx`, version 3) gains prefabs and a per-mesh collides flag. ## The renderer An instanced variant of the scene shader places each vertex by its instance's transform and turns the normal by the cofactor matrix of the transform's 3×3 part, the inverse transpose times the determinant. Each prefab's material groups draw with `drawIndexedInstanced` over a buffer of its `MeshInstance` records set with `setInstanceBuffer`. ## The map `assets/scenes/first_map_prefabs.py`, run once over `first_map.blend`, links the prefabs by relative path and adds 1500 trees on forest-floor ground north of the island's centre, clear of the lake, the ruins, the cave and 8 m from every spawn marker, and the wreck at Blender (-20.5, -210.25), 28 m off the southern beach where the floor lies 16.8 m down, listing and half sunk, its deck about 16 m down. ## Tests - `tests/bake_extract.py`: a local collection instanced three times, a collection linked from `assets/prefabs/` instanced three times, a Geometry Nodes Cone on two points and Cube on two others (two geometries, 62 and 12 triangles, two matrices each), Object Info on three points, `hulken_collide` read and a non-boolean one refused. A grouped geometry's later instances keep their own rules: the last of the marker's three instancers hidden from the camera is refused, and a water box instanced three times gives a volume at each instancer. #3569's instance cases hold. - `tests/bake_stage.sx`: instance transforms in hulken's axes, each instance's triangles in the collision world, the `hulken_collide` false material's left out. - `tests/instanced_draws.sx`: five boxes drawn as instances of one box and as static meshes give the same pixels, every pixel opaque and every box's centre drawn. One box is turned and scaled non-uniformly, and one is mirrored, its static copy's corners taken the other way round as the stage takes them. With the shader's normal turned by the plain 3×3 it fails (4634 pixels differ), and so it does with the normal turned by the inverse transpose, the cofactor times the determinant's sign (2635 pixels). - `tests/first_map_world.sx`: the forest's 1500 trees and the wreck in the render file, the floor under the wreck 16 to 20 m deep with land within 30 m, and a body walked into a tree's trunk stops at it while standing in its leaves. - The Metal golden passes unchanged. Mutants of the extract's key (original alone, the temporary object), its grouping, its roles and water volumes for a geometry's first instance only, and its `hulken_collide` read, of the stage's collision and transform, and of the renderer's draw and normal are each caught by these tests. Gate `full` passed at 6723bb6 (gate run 808).
agra merged commit 71450a5c52 into master 2026-10-29 13:45:44 +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!14
No description provided.