Builds·16 min read·May 9, 2026

Build a Gaussian Splat House Tour in PlayCanvas (Cut Out the Agent)

Real estate agents take 2.5% to walk buyers around a house. A 5-minute phone capture and a free PlayCanvas project gives buyers a photorealistic walkthrough from their couch. Full build, end to end.

A Gaussian splat house tour is a browser-embeddable photorealistic walkthrough of a real property. The buyer opens the listing, walks the rooms, looks at reflections in the marble bench, sees the actual light hitting the actual hardwood. Phone capture in 5 minutes. Browser render. No app install.

PlayCanvas is the engine. It added native Gaussian splat rendering in 2024 alongside SuperSplat, a free open-source splat editor. Three.js can render splats with gsplat.js, but you spend a week building tooling PlayCanvas already ships.

The original post that started this build: @adiix_official on X.

The problem nobody talks about

Real estate agents charge 2 to 3 percent commission. On a $1.2M Auckland house, that's $30,000 of friction sitting between a seller and a buyer. Most of what the agent does is logistics. Unlock the door, walk three buyers through, repeat next weekend.

The viewing is the bottleneck. Out-of-town buyers fly in. Working buyers burn a Saturday. Sellers stage the house, leave for the afternoon, come back to nothing.

Gaussian splat tours collapse that. Buyers self-serve at 11pm in their pyjamas, and the experience is photorealistic in a way the old LIDAR mesh tours never were. The agent's value drops to negotiation and paperwork, which a flat-fee property lawyer handles for around $2,000.

Listing platforms haven't caught up. Matterport still ships mesh-based scans that murder reflections. Zillow's 3D tours are flat panoramas. PlayCanvas plus splats lets you own the scene, embed it anywhere, and pay $0 if your project stays public.

Why Gaussian splatting beats everything that came before

Photorealistic glass, mirrors, and reflections.Mesh-based scanners (Polycam LIDAR, Matterport) can't capture glossy surfaces. Black couches turn into voids. Glass tables vanish. Splats actually capture the real photons. Marble benches look like marble.

5-minute phone capture. Walk the house with an iPhone, run video through Polycam or Luma. No LIDAR sensor needed. No 200-photo photogrammetry sessions. Process time is faster than the capture.

Tiny file sizes. A 4-bedroom house Gaussian splat is 30 to 80MB compressed. Equivalent-quality mesh plus textures is 400MB+. Mobile data ships it.

Native PlayCanvas support. Drop a .ply or .splat file into the editor, it renders. No custom shader work, no third-party libs.

Step 1: capture the house on your phone

You need video footage covering every angle of every room. Three apps that work:

Polycam Splat mode (iPhone Pro, Android with depth sensor) is the easiest. Open Polycam, switch to Gaussian Splat mode, walk every room slowly. The app processes in the cloud (free for 2 captures/week, $20/month for unlimited). Output is a downloadable .ply file.

Luma AI (iPhone, free) is the highest quality of the free options. Capture mode is "Free Form" or "Orbit". Walk room to room, hold the phone at chest height, keep movement smooth. Cloud processing takes 30 to 60 minutes. Export as .ply.

Postshot(Windows + NVIDIA GPU, $150 one-off) is the pro option. You feed it any video file (drone, DSLR, phone) and it processes locally. No cloud upload, full control over training time and quality. Use this if you're capturing 10+ houses a month or want privacy.

Capture rules that compound:

  • Walk slow. About 1 step per second. Faster motion blurs the training frames.
  • Cover every angle. The splat looks bad from camera angles you never filmed. Walk every room twice, once at chest height, once at knee height.
  • Avoid moving things. People, curtains in the wind, water reflections all create floaters.
  • Even lighting helps. Bright sunny noon is harder than overcast afternoon (harsh shadows confuse the optimiser).

A 4-bedroom house takes about 8 minutes of capture, plus an hour of cloud processing. Output is a .ply file, typically 100 to 300MB pre-compression.

Step 2: clean the splat in SuperSplat

Raw splats have garbage. Floaters in the air, splats outside the house, blurry edges. SuperSplat is a free browser-based editor that fixes this in 5 minutes.

Open superspl.at/editor. Drag your .plyfile in. Tools you'll use:

  • The bounding box crop. Drag the box around just the house, delete everything outside.
  • The lasso tool. Select floaters in the air (the wispy clouds above the ceiling), press delete.
  • The compression export. File > Export > Compressed .ply. A 200MB raw splat drops to 35MB with no visible quality loss.

Save the cleaned, compressed file. This is what you'll load into PlayCanvas.

Step 3: set up the PlayCanvas project

Sign up at playcanvas.com (free). New project, blank template. The editor opens in your browser.

Assets panel > Upload > drop your house.compressed.ply

PlayCanvas auto-detects the splat format. Drag the imported asset into the scene hierarchy as a Gaussian Splat entity. It loads at world origin. Rotate 90° if the floor doesn't sit flat.

You don't need lighting. The splat has lighting baked in from the original capture. Delete the default directional light. Skip the HDRI step entirely. This is one of the wins over mesh-based pipelines.

Step 4: first-person controller

PlayCanvas has a maintained first-person template that works with splats out of the box.

In the editor, hit + Entity > Template > First Person Controller. It drops in a camera rig with WASD movement and mouse-look already wired up. Set the camera height to 1.7m (eye level for an average adult). Set move speed to 2.5 m/s, a normal walking pace, not a quake-style sprint.

For mobile, add the Touch Input plugin from the PlayCanvas store. Left-hand virtual joystick, right-hand drag-to-look. Five-minute install.

Test in editor: the splat should render in real-time as you move the camera. If frame rate is bad, you skipped Step 2's compression. Go back.

Step 5: collision without a mesh

This is the one place splats are awkward. They're point clouds, not geometry. There's nothing to collide against.

The fix: build an invisible low-poly proxy mesh and use that for collision. The buyer never sees it.

Two ways to make the proxy:

Manual boxes (5 minutes). Add invisible Box entities along each wall in the PlayCanvas editor. Set their mesh renderer to Disabled. Add Collision (Box) and Rigidbody (Static). Tedious but bulletproof.

Mesh from your scan (10 minutes). If you also have a Polycam LIDAR scan of the same house, import the .glb, set its visibility to off, and use it as the collision mesh. Best of both worlds: photorealistic splat render, mesh collision.

On the First Person Controller entity, the template already includes a Capsule collision and kinematic rigidbody. You just need to enable physics in Settings > Physics > Enabled.

Step 6: room hotspots with info popups

The dollhouse view is what sells the house. Buyers want to see "kitchen: 12 sqm, oak floors, induction hob" without walking over.

Add an Entity at the centre of each room. Attach a script component called Hotspot.js:

var Hotspot = pc.createScript('hotspot');
Hotspot.attributes.add('label', { type: 'string' });
Hotspot.attributes.add('details', { type: 'string' });

Hotspot.prototype.initialize = function() {
    this.entity.element.on('click', () => {
        document.getElementById('popup-label').innerText = this.label;
        document.getElementById('popup-details').innerText = this.details;
        document.getElementById('popup').style.display = 'block';
    });
};

Add an Element component to the entity, type Image, with a small icon texture. Set Layer to UI so it always renders on top. Fill in the label ("Kitchen") and details ("12 sqm, oak floors, induction hob, north-facing window") in the editor inspector.

The popup itself is plain HTML/CSS sitting on top of the canvas. Don't try to build it inside PlayCanvas's UI system. Slower and uglier.

Step 7: performance tuning for mobile

Splats are GPU-bound, not bandwidth-bound. A 35MB compressed splat downloads fast but renders slow on a 3-year-old Android.

Three changes that compound:

  • Lower the splat count cap. Settings > Rendering > Gaussian Splat Limit = 1,000,000 (default is unlimited). Above 1M splats, mid-range mobile chugs. The visual difference is small.
  • Enable Settings > Rendering > Anti-aliasing > FXAA. Cheaper than MSAA, looks 90% as good.
  • Switch to WebGPU rendering in Settings (vs default WebGL2). 30% to 50% faster on Chrome and Safari 18+. Falls back to WebGL2 on older browsers automatically.

Target budget: under 50MB total scene, under 1.5M visible splats, 50fps minimum. Profile with Chrome DevTools > Performance Monitor on a real Pixel 6, not your M3 MacBook.

Step 8: publish and embed

Hit Publish in the PlayCanvas editor. You get a hosted URL like playcanv.as/p/abc123. Free if your project is public.

If you need a private project:

  1. Pay for a Personal plan ($15/month) to keep the source private.
  2. Or self-host the published build. Publish > Download .zip, then drop it in any static host like Vercel, Netlify, or Cloudflare Pages.

For a Squarespace, Wix, or Webflow listing page, embed via iframe:

<iframe
  src="https://playcanv.as/p/abc123/"
  width="100%"
  height="600"
  frameborder="0"
  allow="fullscreen; xr-spatial-tracking">
</iframe>

The xr-spatial-tracking permission unlocks WebXR if the buyer happens to have a Quest. Splats look incredible in VR. Ten extra characters, free upside.

Step 9: PostHog analytics for per-room dwell time

This is where the disintermediation gets sharp. You want to know which buyers spent 8 minutes in the master bedroom and 30 seconds in the bathroom. Those are your real leads.

Drop the PostHog snippet in the iframe page, then add a tracking script in PlayCanvas:

var Tracker = pc.createScript('tracker');
Tracker.prototype.initialize = function() {
    this.currentRoom = null;
    this.roomEnterTime = 0;
};

Tracker.prototype.update = function() {
    var room = this.detectRoomFromPosition(this.entity.getPosition());
    if (room !== this.currentRoom) {
        if (this.currentRoom) {
            var dwellSec = (Date.now() - this.roomEnterTime) / 1000;
            window.posthog.capture('room_exited', {
                room: this.currentRoom,
                dwell_seconds: dwellSec
            });
        }
        this.currentRoom = room;
        this.roomEnterTime = Date.now();
    }
};

detectRoomFromPosition is just a hardcoded set of bounding boxes per room. Five lines of math.

Now your PostHog dashboard shows per-buyer, per-room dwell time. The seller sees which rooms hold attention, which feel dead. Sort by total tour time, the top 5 buyers are who you call.

Honest limitations

View-dependent quality.Splats look photorealistic from angles you filmed. From angles you didn't film, they smear. Capture every room from at least 3 heights and 8 horizontal angles, or the buyer hits an ugly view and bounces.

You can't relight.The lighting is baked into the splat from capture day. Want the kitchen to look bright on a cloudy listing day? Recapture. There's no equivalent of swapping the HDRI like with mesh.

Movement during capture wrecks splats. Curtains in the wind, ceiling fans, water in a pool, a cat walking through. All become floaters and ghost trails. Capture early morning when the house is still.

Mobile WebGL2 is still flaky on older devices.Splats hit the GPU harder than meshes. iOS Safari pre-version 16 can refuse to render. You'll lose maybe 8% of buyers to "scene won't load" before you optimise.

MLS legal gotcha.In the US, most MLS listings require a licensed agent to publish. Your buyer can self-tour, but the listing itself still flows through an agent unless you're FSBO (For Sale By Owner). NZ and Australia have fewer restrictions. Check your local rules before pitching this as the agent killer.

It doesn't replace vibes. The smell of damp, the noise from the road at 7am, the feel of the neighbourhood. A 3D tour gets buyers to the shortlist. The final decision still wants a real visit. Frame the tour as the filter, not the close.

PlayCanvas free tier means public projects.Anyone can fork your scene. For a one-off house tour this doesn't matter (the house is publicly listed anyway). For a business doing 50 listings, pay the $15/month Personal plan.

Quick reference

  • Splat capture (easiest): Polycam, free 2/week or $20/mo unlimited
  • Splat capture (best free): Luma AI, free
  • Splat capture (pro, local): Postshot, $150 one-off (Windows + NVIDIA)
  • Splat editor: SuperSplat, free
  • Engine: PlayCanvas, free for public projects, $15/mo for private
  • Hosting: PlayCanvas hosting, Vercel, Netlify, or Cloudflare Pages, all free tier
  • Analytics: PostHog, free up to 1M events/mo

Total cost for first ship: $0 if you have an iPhone Pro and a Saturday.

The AI Side Hustle Cookbook

Liked this guide? Shout me a coffee.

$4.99 gets you the full playbook: 50 recipes you can build, ship, and get paid for with Claude Code. Working code in every one. The pricing, the deploy, the pitfalls. Every revision free for life.

Shout me a coffee