DEV Community

Paul Crinigan
Paul Crinigan

Posted on

Making a Babylon.js Game Run Well in a Mobile Browser

If you have a Babylon.js game that runs smoothly on your laptop and falls apart on a phone, this one is for you. Mobile GPUs have less memory, lower fill rates and aggressive thermal throttling, and the browser adds its own overhead on top. The good news is that a handful of changes do most of the work.

Measure Before You Change Anything

A slow frame can come from draw calls, oversized textures, shaders, physics, garbage collection or too many polygons, and each has a different fix. Toggle the Inspector with scene.debugLayer.show() to see FPS, draw calls, active meshes and a frame time breakdown. Then log scene.getLastFrameDuration(). Anything consistently above 16.6ms misses 60fps, and above 33.3ms misses 30.

The Chrome Performance tab tells you where the time goes. Long Scripting bars mean JavaScript, long Rendering bars point to draw calls, and long GPU bars mean the graphics card is overloaded. Frequent GC blocks usually mean you are creating new Vector3 objects in the render loop, so preallocate and reuse them. The Babylon.js performance guide covers the full profiling workflow.

Render Fewer Pixels

Phones have pixel densities of 3x or more, and rendering 3D at native resolution there is impractical. engine.setHardwareScalingLevel(2) renders at half resolution in each direction, a quarter of the pixels, and the browser scales the result to the full screen. Mid range phones do well at 2, high end phones can take 1.5, and low end devices may need 3.

Pick the level at startup by running a few frames and checking engine.getFps(). Then turn on FXAA through the DefaultRenderingPipeline with pipeline.fxaaEnabled = true, which smooths the jagged edges cheaply enough for mobile.

Treat GPU Memory as the Hard Limit

A single uncompressed 4096x4096 texture uses 64MB. A budget Android phone may share 2GB between CPU and GPU, so ten of those textures and the tab is out of room. On mobile, games crash from memory more often than they stutter from frame rate.

KTX2 with Basis Universal compression is the answer. One compressed file transcodes at runtime to whatever the GPU supports, BC7 on desktop and ASTC or ETC2 on mobile, and it cuts texture memory by about 75 percent compared to PNG. Ship smaller texture sets for phones too, 1024 or 512 where desktop uses 2048. The mobile browser walkthrough also covers touch controls and thermal throttling.

Cut Draw Calls

A desktop browser handles roughly 500 to 1000 draw calls at 60fps, while mobile browsers top out around 100 to 300. Merge static meshes that share a material with BABYLON.Mesh.MergeMeshes, so 50 identical wall segments become one draw call. For repeated objects like trees and rocks, createInstance shares geometry and material across copies, and thin instances via thinInstanceSetBuffer handle thousands of identical objects with almost no CPU cost.

The Takeaway

Profile first, then render fewer pixels, compress every texture and batch your draw calls. Those four steps get most Babylon.js games playable on a mid range phone. The full guide to building 3D web games with Babylon.js covers the rest of the engine, from Havok physics to multiplayer.

Top comments (0)