Building a Real-Time WebGL Property Viewer on PlayCanvas

Building a Real-Time WebGL Property Viewer on PlayCanvas

When we set out to build the Brouse Viewer, the core requirement was non-negotiable: photorealistic Gaussian splat rendering at 60fps in a browser tab, on devices as modest as a three-year-old mid-range Android phone.

Why PlayCanvas?

We evaluated Three.js, Babylon.js, and a fully custom WebGPU renderer before settling on PlayCanvas. The deciding factors were its mature entity-component system, first-class WebGL 2 support, and an asset pipeline that handles the kind of large splat files we're producing — some exceeding 800 MB uncompressed.

The Rendering Pipeline

Gaussian splats are rendered as a sorted array of 3D Gaussians projected onto screen-space quads. Sorting is the bottleneck — we moved the depth sort to a WebGL compute pass using transform feedback, cutting sort time from 22ms to under 4ms on a mid-tier device.

"Moving sort to GPU transform feedback was the single biggest performance win. Frame times dropped from 28ms to 11ms on the same scene." — Mira Solis, CTO

Navigation Controller

We implemented a WASD + mouse-look controller with a virtual joystick fallback for touch devices. The key insight was baking the navigation graph into the splat scene at capture time — this lets us snap the camera to valid floor positions and prevents users from clipping through walls.

Mobile Optimisations

On mobile we drop to a 0.75× render scale and use aggressive frustum culling on splat clusters. Battery-aware throttling kicks in when the device reports less than 20% charge, halving the target frame rate to 30fps. These two changes extended average session length on mobile by 3.2 minutes.

Building a Real-Time WebGL Property Viewer on PlayCanvas | Brouse Blog