Arena Performance Optimizations
Overview
The duel arena rendering system underwent major performance optimizations in February 2026, reducing draw calls by ~97% and eliminating expensive per-pixel lighting calculations.Performance Improvements
Before Optimization
- ~846 individual mesh draw calls - Each fence post, rail, pillar component rendered separately
- 28 dynamic PointLights - Per-pixel lighting calculations every frame
- Severe FPS drops - Especially noticeable with multiple arenas visible
After Optimization
- ~22 draw calls - InstancedMesh batching for repeated geometry
- 0 dynamic lights - Replaced with GPU-driven TSL emissive materials
- Smooth 60 FPS - Consistent performance across all arena views
Technical Changes
1. InstancedMesh Conversion
Converted ~846 individual meshes to InstancedMesh batches:| Component | Before | After | Reduction |
|---|---|---|---|
| Fence posts | 288 meshes | 1 InstancedMesh | 99.7% |
| Fence caps | 288 meshes | 1 InstancedMesh | 99.7% |
| Fence rails (X) | 36 meshes | 1 InstancedMesh | 97.2% |
| Fence rails (Z) | 36 meshes | 1 InstancedMesh | 97.2% |
| Pillar bases | 32 meshes | 1 InstancedMesh | 96.9% |
| Pillar shafts | 32 meshes | 1 InstancedMesh | 96.9% |
| Pillar capitals | 32 meshes | 1 InstancedMesh | 96.9% |
| Brazier bowls | 24 meshes | 1 InstancedMesh | 95.8% |
| Border strips (N/S) | 12 meshes | 1 InstancedMesh | 91.7% |
| Border strips (E/W) | 12 meshes | 1 InstancedMesh | 91.7% |
| Banner poles | 12 meshes | 1 InstancedMesh | 91.7% |
2. Dynamic Lighting Removal
Replaced all 28 PointLights with GPU-driven TSL emissive materials: Old approach (CPU-intensive):- Zero CPU cost per frame
- Per-instance phase offset for natural variation
- Runs entirely on GPU via emissiveNode
3. Fire Particle Improvements
Unified fire rendering on enhanced “fire” preset: Removed:"torch"particle preset (redundant)- Separate torch/fire particle systems
- Smooth value noise fragment shader (bilinear interpolated hash lattice)
- Soft radial falloff designed for additive blending
- Per-particle turbulent vertex motion for natural flickering
- Height-based color gradient (white-yellow core → orange-red tips)
- Overlapping particles merge into cohesive flame body
4. Dead Code Removal
Removed unused functions:createArenaMarker()- Arena number markers (unused)createAmbientDust()- Dust particles (unused)createLobbyBenches()- Lobby benches (unused)
Performance Metrics
Draw Call Reduction
- Before: ~846 draw calls per frame
- After: ~22 draw calls per frame
- Improvement: 97% reduction
Lighting Performance
- Before: 28 PointLights × per-pixel calculations
- After: 0 dynamic lights (GPU emissive only)
- Improvement: Eliminated per-pixel lighting overhead
Frame Rate
- Before: Variable FPS, drops to 30-40 FPS in arena areas
- After: Consistent 60 FPS across all arena views
- Improvement: 50-100% FPS increase in arena areas
Implementation Details
InstancedMesh Pattern
TSL Emissive Animation
Migration Notes
Breaking Changes
GlowPresettype no longer includes"torch"- use"fire"insteadMAX_RISE_SPREADparticle pool increased from 256 to 896 (supports more fire particles)
API Changes
GlowParticleManager.registerTorch()removed - useregisterFire()instead- Fire particles now use turbulent vertex motion (phase parameter in dynamics array)
Troubleshooting
Grey/White Materials After Update
If braziers or pillars appear grey after updating:- Clear browser cache and IndexedDB
- Restart the client
- Materials should restore with proper colors
Missing Fire Effects
If fire particles don’t appear:- Check that particle system is initialized
- Verify
MAX_RISE_SPREADpool has capacity (now 896) - Ensure emitter IDs are unique
Performance Still Poor
If FPS is still low after update:- Check GPU compatibility (WebGPU required for TSL)
- Verify InstancedMesh is being used (check draw calls in DevTools)
- Ensure old PointLights were removed (check scene graph)
Related Files
packages/shared/src/systems/client/DuelArenaVisualsSystem.ts- Main arena rendering systempackages/shared/src/entities/managers/particleManager/GlowParticleManager.ts- Fire particle systempackages/server/src/systems/StreamingDuelScheduler/managers/DuelOrchestrator.ts- Victory emote timing
References
- PR #938: perf(arena): instance arena meshes and replace dynamic lights with TSL fire particles
- Commit c20d0fc: Arena instancing implementation