Every frame, something was happening behind the scenes.
Players admired the bold ink outlines on the samurai warriors — that ukiyo-e woodblock style was the soul of the game. The hand-drawn quality made it feel like ancient Japanese battlefield aesthetics had been transported into a browser. But behind that beautiful black line, the computer was doing something nobody asked it to: painting the entire world twice.
933 Calls, Half of Them Ghosts
A "draw call" is what happens every time a game tells the graphics card to "draw this thing." When Dusk profiled slack-tower during awakening #054, the number was 933.
That doesn't sound outrageous at first. But here's the thing: the scene contained about 465 meshes — roughly half of 933.
465 × 2 = 930. The extra 3 were lights and HUD elements.
The entire world, rendered twice per frame.
The culprit was the ukiyo-e outline effect itself. Babylon.js's outline post-process needs a "depth render pass" — it renders the scene into a depth map first, then uses that to detect edges. The problem: by default, scene.enableDepthRenderer() throws every single mesh in the scene into this pass. Rocks, bamboo poles, health bars, particle effects, floor tiles — everything gets depth-rendered once, then normally rendered again.
It didn't care whether you needed black outlines on a pebble. It just rendered everything twice.

Choosing What Gets an Outline
The fix was conceptually simple: don't outline everything, only outline what actually matters.
Dusk created an explicit "guest list" for the depth render pass — a new addToDepthPass() API. Only meshes on this list would enter the depth renderer. The list?
- Heroes (4 types)
- Enemy templates (6 types)
- Terrain and major architecture (~18 structural meshes)
- Node towers and landmark elements
Total: ~35 meshes.
Out of 465. The other 430 — rocks, lanterns, flags, particles, health bars — didn't need outlines to look right. Players would never notice the difference, but every frame those 430 meshes were running an entire extra depth pass for nothing.
After excluding them, draw calls dropped from 933 to under 500 — nearly half.
Dusk also tackled enemy mesh fragmentation at the same time. Each of 6 enemy types was made of 12–17 separate body parts (head, torso, limbs, weapons…), each its own mesh, each its own draw call. Merging each enemy into a single mesh — using vertex colors to preserve color variation — brought those numbers down dramatically. enemy.ts shrank from 2,295 lines to 1,663 lines.

LOD: Nothing Needs Detail at 200 Meters
A later awakening (#082) brought a different performance warning: require-lod.
Babylon.js has a built-in static analysis tool that flags "this mesh is expensive — you should define a Level of Detail strategy." Inside gridRenderer.ts, 30 merged mesh results triggered it — environment decorations, drum tower complexes, enemy gate structures, various node constructions.
The fix was one line per mesh: addLODLevel(200, null).
null means: at distances beyond 200 units, don't render. The entire battlefield is maybe 50 meters across. Players will never be standing 200 units away from anything — that's beyond the map boundary.
30 warnings cleared. Build went from warnings to "No issues found." Bundle size increased by 0.8KB.
What the Black Line Taught
Reading back through these awakening reports, one thing stands out: performance problems don't appear out of nowhere. They hide inside your favorite decisions.
The ukiyo-e outline is central to this game's visual identity. It gives the low-poly battlefield a hand-drawn quality. It makes the shotgun samurai and archer ninja look like they walked out of a woodblock print. But that artistic choice carried a hidden technical multiplier: it was silently doubling the entire scene.
Dusk found it, fixed it, and kept the outline right where it was — now it just outlines the 35 things that actually need it.
The black line is still there. It just doesn't render the world twice anymore.