Overlapping transmissive shells at near-equal depth swapped transparent draw order frame-to-frame (per-object back-to-front sort) — reads as z-fighting whenever marbles press together, which in a pack is always. Each racer's shell now carries renderOrder 10+idx: a fixed, stable order (occasionally 'wrong', never flickering). The residual transmission limitation (a glass shell cannot refract another glass shell behind it — only opaques land in the transmission buffer) remains; escalation if ever needed is a MeshTransmissionMaterial-style shared-buffer port. 116 tests green.
- commit
- ec5616b8a4e61633baf91d51f14207061e8766d6
- parent
- 50ebd75285829207194ea4fa3f3cfe25a9ef7225
- author
- Dami <dami.etoile@gmail.com>
| M | src/ | 8 | +++++++- |
@@ -474,8 +474,10 @@ class Session {
474474 const m = child as THREE.Mesh;475475 if (!m.isMesh) return;476476 const cloneOne = (mat: THREE.Material): THREE.Material => {477- // Hero shell: clear real glass (neutral phenotype).477+ // Hero shell: clear real glass (neutral phenotype); stable478+ // transparent order (see buildRacerVisual).478479 if (mat.name === "glass" && physics) {480+ m.renderOrder = 10;479481 const g = glassShellMaterial(ctx.renderer, {480482 meshId: MARBLE_PIECE,481483 tint: null,@@ -1438,6 +1440,10 @@ class Session {
14381440 // phenotype (Beer–Lambert), while identity tint + effects14391441 // stay on the opaque CORE the glass refracts.14401442 if (mat.name === "glass") {1443+ // STABLE transparent order per racer: overlapping shells at1444+ // near-equal depth otherwise swap draw order frame-to-frame1445+ // (reads as z-fighting when marbles press together).1446+ m.renderOrder = 10 + index;14411447 const g = glassShellMaterial(this.ctx.renderer, identity);14421448 materials.push(g);14431449 return g;