Johnny Mnemonic (Williams 1995)¶
Four-year from-scratch build (2021-2025) led by sixtoe with tomate80 (Blender/toolkit), apophis79 (scripting/physics), iaakki (mechanics/testing/SSF), and niwak (toolkit author). The build uniquely documents the evolution of the VPX Lightmapper toolkit across multiple re-bakes and versions, showing how toolkit improvements compounded over the long build cycle. Notable for the data glove mechanical toy implementation and detailed GI string research methodology.
Build Story¶
Johnny Mnemonic went through 70+ WIP versions and multiple complete toolkit re-bakes as the VLM toolkit matured. A late-stage re-bake with updated toolkit and NoExp scripts cut polygon count from 2,358,056 faces (219 MiB GPU) to 1,063,488 faces (96 MiB GPU) -- more than halving geometry while improving visual quality.
Table-Specific Details¶
Mechanisms & Hardware¶
Data glove ball capture: For mechanical toys that grab and move the ball (JM's data glove), iaakki used a 1ms timer that continuously moves the active ball to follow the toy's position. The old VP9 approach (destroy ball at capture, create new ball at release) causes visual pops and leaves no physical ball in play. Droppable walls around kicker pockets contain balls that might otherwise escape, and the matrix mechanism uses 9 kickers with different kick angles and slight scatter.
GI string research: JM's GI strings alternate individual bulbs across the playfield to create a "sweep" effect rather than being organized in geographic zones -- unusual for Williams machines. The definitive mapping was achieved by iaakki going to an arcade to capture the ROM's built-in GI string test on video. Wire color tracing was complicated by white-green being used for both GI string 5 and one switch matrix row.
Art & Visuals¶
Movable array convention: When animating toolkit movable objects, always use the generated _BM, _LM, and _BL array suffixes rather than referencing specific lightmap primitives by name. These arrays are auto-generated by the toolkit and stay synchronized after re-rendering. Moving lightmaps and bakemaps in separate timer ticks causes visible flicker.
Insert light dispersal mesh: Toolkit inserts contain an invisible mesh component (only visible in X-ray/mesh view) that disperses light from the point source below. Placing the light above the invisible mesh creates a harsh hotspot instead of a diffused glow. The full insert geometry extends downward much further than it appears in render view.
VPX incandescent fader: niwak documented the VPX 10.8 built-in incandescent fader here -- select "incandescent" fader type for the correct nonlinear fading curve. Working values: 40ms up, 120ms down. Reference measurements showed approximately 40ms fade up/down for flashers.
Lightmap opacity trick: To brighten a specific object's lighting response without re-rendering, set its lightmap primitive opacity above 100 (e.g., 200-300). This amplifies the baked lighting contribution beyond the original bake level. Going too high makes objects look self-emitting.
Physics & Gameplay¶
Refraction performance: Removing ramp refractions reduced GPU load from 100% to 90%, making the table playable on a GTX 1060 at 4K 60Hz. The F12 options menu exposes refraction settings so users can adjust for their hardware.
Refraction probe artifacts: When a single transparent primitive spans multiple depth levels, refraction probes produce ghost/doubling artifacts. sixtoe split ramps into 4 pieces and disabled refraction probes on entrance sections while keeping them on return sections.
Known Issues¶
VSync override shipping bug: JM shipped with VSync override set to 1 instead of -1 in the User properties tab, causing loading crashes and setting persistence failures on some systems.
Negative playfield depth bias breaks ball trails: A negative depth bias on the playfield primitive causes the playfield to render after the ball trail in the depth buffer, making trails invisible. Fix: set playfield depth bias to 0.
NoExp polygon explosion: Screw/bolt models from the Blender library had subdivision modifiers without the NoExp naming prefix. 13 screws inflated from 10K to 42K+ triangles each -- a massive performance drain from tiny barely-visible objects.
Techniques Developed Here¶
- GI string research methodology -- the wire tracing + video frame-stepping + ROM test process was refined here
- Destroy/create ball vs timer-driven movement for mechanical toys was documented here
- Pure black (#000000) breaks rendering -- sixtoe's definitive statement
- Room brightness can only darken -- always bake with room lighting ON
- light_animate subs replacing Lampz for controlling primitive BDL
- Refraction probe splitting to resolve depth-crossing artifacts