Babylon-thin-instance-outline — outline a single thin-instance (the case HighlightLayer / EdgesRenderer can't)


The demo for the lib


Running inside my alpha game project.

I ran into a snag on my project and so i did a thing to resolve it.  thought it worth sharing.

Thin instances are perfect for high-volume repeated geometry — but there's a
known gap: you can't outline **one** thin-instance among many. `HighlightLayer`,
`OutlineRenderer`, and `EdgesRenderer` are all-or-nothing on a thin-instance host
(outline one, outline them all), and `InstancedMesh` can't use those layers at all.

I hit this doing per-member selection on OAR-imported linksets, so I packaged the
workaround into a small, focused, zero-Babylon-patch library:

**`@poqpoq/babylon-thin-instance-outline`**

**How it works:** a parallel inverted-hull outline mesh that is *itself* a
thin-instance host — its matrix buffer mirrors the source's at the same indices.
To highlight instance `i`, copy the source matrix into the outline buffer at `i`;
to clear it, write a scale-zero matrix. Per-instance show/hide via matrix scale is
the natural Babylon idiom, so it composes cleanly.

**What's in it (v1.3):**
- Per-thin-instance outline + **per-instance color**
- **Smooth-normals preprocess** so hard-edge meshes (cubes) get continuous outlines
- **Animated silhouette effects** — pulse, colorCycle, edgeFlow, sizzle, rimFlow —
  with live param tuning (no recompile)
- Works on plain single-mesh outlines too (zero thin-instances)

**Links**
- Demo reel: 

https://www.youtube.com/watch?v=7lqRXxegcow

- live interactive demo

https://poqpoq.com/babylon-outline/

- npm: `

npm install @poqpoq/babylon-thin-instance-outline

- GitHub (MIT, ADRs, 62 tests): 

https://github.com/increasinglyHuman/babylon-thin-instance-outline

- to see it live in my alpha build - fair warning, it's definitely alpha - expect a wild ride if you to in to explore. It's implemented on geometry selection - or OAR import selection - you'd have to create your own sim and make some stuff - then select in build mode.

https://poqpoq.com/

**On prior art:** this is deliberately *not* a screen-space selection outliner — for a
unified group/selection outline, the native `SelectionOutlineLayer` and @noname0310's
excellent [Selection Outliner](https://forum.babylonjs.com/t/selection-outliner-blender-style-outlines/61598)
are the right tools. This fills the complementary gap: per-thin-instance,
silhouette-following, one outline per instance.

Feedback, edge cases, and PRs very welcome — curious whether others have run into the
same thin-instance limitation.
3 Likes

Super cool!

1 Like

v1.4.0 — now actually works on WebGPU :slightly_smiling_face:

Two fixes, and the second one is worth sharing regardless of whether you use this library.

1. refresh() served stale matrices. thinInstanceGetWorldMatrices() is memoised, and the cache has exactly one invalidation site (thinInstanceSetBuffer). thinInstanceBufferUpdated('matrix') doesn’t touch it — so if you move instances by writing into your own Float32Array, the getter keeps handing back pre-move data. Outlines silently froze in place. Also note thinInstanceSetMatrixAt syncs that cache by reference, so reusing one scratch Matrix across a loop makes every cached slot alias the last value written.

2. The library never worked on WebGPU. Since v1.0. Cause, and the generalizable bit:

// ❌ world0..3 duplicated — ShaderMaterial already adds them
new ShaderMaterial('outline', scene, path, {
  attributes: ['position', 'normal', 'world0', 'world1', 'world2', 'world3', 'myInstanceAttr'],
})

// ✅ let Babylon do it
new ShaderMaterial('outline', scene, path, {
  attributes: ['position', 'normal', 'myInstanceAttr'],
})

ShaderMaterial appends your attributes verbatim, then calls PushAttributesForInstances() when the mesh uses instances — so listing world0..3 yourself registers them twice, both resolving to shader location 2. WebGL binds attributes by name and tolerates it. WebGPU validates the vertex state and rejects the pipelineAttribute shader location (2) is used more than once — which took down the entire scene, not just the outline.

If you have a custom ShaderMaterial on a thin-instance host and haven’t tried WebGPU: worth a look.

My demo had hardcoded new Engine(...) since day one, so no run had ever exercised WebGPU. It now takes ?webgpu, and that’s what surfaced it — within minutes.

:video_game: babylon-thin-instance-outline — demo
:package: npm i @poqpoq/babylon-thin-instance-outline (≤1.3.1 deprecated — WebGPU-fatal)

Both of these trace back to a generous and very thorough review from @labris, who went through the library line by line and got me looking in the right place. Thank you.

2 Likes