Mo Tawfik Khalifa · Product leader and builder
All notes

Gaussian splatting on a website: how to put a 3D scan on your site

8 min read · Mo Tawfik Khalifa
Try it below

A Gaussian splat is a 3D scan made of hundreds of thousands of soft, coloured, see-through blobs, built from ordinary photos or a phone video. To put one on a website, capture it with a phone app, export a .spz or .ply file, and load it with a free web viewer such as Spark on three.js, in about 20 lines of code.

The method comes from a paper by Kerbl, Kopanas, Leimkühler and Drettakis, published in ACM Transactions on Graphics in July 2023 and shown at SIGGRAPH 2023. Before it, the authors wrote, no method could show a complete, unbounded scene at 1080p in real time. Theirs ran at 30 frames a second or more (abstract on arXiv).

I built one you can try: tawfik.tv/window. It renders a splat live in your browser with Spark, and the screen behaves like a pane of glass: the room shifts as you move the cursor on a laptop, or drag or tilt a phone. If you allow the camera, it follows your head instead, worked out on your own device. To be clear about the scene: it is Spark’s own sample, a fireplace, not a scan of mine. It holds 301,000 splats in a 4.4 MB .spz file.

What is a Gaussian splat, in plain words?

Picture a 3D photo made of blobs instead of triangles. Each blob has a position, a size, a stretch and a direction, a colour, and how see-through it is. Blend enough of them from back to front and they add up to a photo-real picture you can walk round.

Three things make splats different from the 3D models in games:

How do you capture a Gaussian splat with a phone?

  1. Pick an app. Scaniverse from Niantic Spatial has a free tier, runs on iPhone and Android, and exports splats as SPZ or PLY. Polycam builds a splat from 20 to 200 photos or an MP4 video.
  2. Light it evenly. Overcast daylight or soft room light. Hard shadows get baked into the scan.
  3. Walk a full circle, slowly. Keep the subject in the middle of the frame and overlap each shot with the last. Then walk a second circle, higher or lower.
  4. Cover every side people will see. The software can only rebuild what the photos saw. Try “front half only” in the demo below and look round the back.
  5. Avoid what moves and what shines. People walking through, leaves in the wind, mirrors and glass all turn to blur.
  6. Clean it before you publish. Most scans have stray blobs floating at the edges. SuperSplat, a free, open-source editor that runs in the browser, crops them away.

Here is the whole pipeline in one place. Walk round the pot to take photos, train it, then see what a real scan weighs.

Try it: capture, train, export

Walk round a plant pot, then watch photos turn into blobs.

A tiny splat engine in plain JavaScript, with about 3,000 blobs where a real scan has hundreds of thousands. Drag the picture to walk round the pot and take photos. Then train it, and see what a real scan weighs and which devices can run it.

0 photos

Drag sideways to walk round the pot. The app takes a photo every 10 degrees and lights a tick on the ring.

Your photos appear here.

Which file format: .ply, .splat or .spz?

PlayCanvas published a real example in December 2023: their guitar scan was 132.8 MB as a PLY and 8.7 MB compressed. Spark reads PLY, compressed PLY, SPZ, SPLAT, KSPLAT and PlayCanvas’s newer SOG format.

My rule: ship .spz to the browser and keep the .ply as the master.

How do I put a Gaussian splat on my website?

Pick a viewer first.

With Spark, this is a complete page. It is Spark’s own getting-started code, trimmed, with your scan in place of their sample:

<style> body { margin: 0; } </style>
<script type="importmap">
{ "imports": {
    "three": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js",
    "@sparkjsdev/spark": "https://sparkjs.dev/releases/spark/2.3.1/spark.module.js" } }
</script>
<script type="module">
import * as THREE from "three";
import { SparkRenderer, SplatMesh } from "@sparkjsdev/spark";

const renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.01, 1000);
scene.add(new SparkRenderer({ renderer }));

const scan = new SplatMesh({ url: "/scans/room.spz" });
scan.quaternion.set(1, 0, 0, 0);   // turns the scan the right way up, as in Spark's example
scan.position.set(0, 0, -3);
scene.add(scan);

// the window effect, simplest version: the camera follows the cursor
addEventListener("pointermove", (e) => {
  camera.position.x = (e.clientX / innerWidth - 0.5) * 0.4;
  camera.position.y = (0.5 - e.clientY / innerHeight) * 0.2;
});

renderer.setAnimationLoop(() => renderer.render(scene, camera));
</script>

Source: Spark getting started. My live version goes one step further: the glass stays fixed and the eye moves in front of it, so the picture bends the way a real window does. Three things I hit shipping it:

Will a Gaussian splat run on a phone?

Yes, if you keep the count down. Spark’s performance guide gives rule-of-thumb budgets:

Over budget, turn on level of detail. With Spark 2.0, new SplatMesh({ url, lod: true }) renders a smaller set of splats sized to the device: by default 1 million on Android, 1.5 million on iOS and 2.5 million on desktop (level-of-detail guide). For big scans, build the level-of-detail file ahead of time and stream it.

Two more settings matter. Keep antialiasing off, as Spark advises, because splats gain nothing from it. And watch the pixel ratio: my demo times its own frames, and when 60 frames average slower than 25 ms it lowers the resolution a step, then raises it again when there is room. It also shows a loading percentage, so nobody waits on a blank screen while the 4.4 MB scan arrives.

What is a Gaussian splat website good for?

Where splats fall short: anything you need to relight, offer in different colours as a product option, or drop into a game as a solid object. That still needs a modelled 3D asset.

Questions people ask

What is 3D Gaussian splatting?

A way to turn photos of a real place or object into a 3D scene made of soft, coloured blobs that render in real time. It comes from a 2023 research paper by Kerbl and colleagues.

Can I view or edit a Gaussian splat online without code, in SuperSplat?

Yes. Open the file in SuperSplat in your browser, or use the viewer in your scan app. To show it on your own site, in your own design, use a web viewer such as Spark.

How big is a Gaussian splat file?

About 248 bytes a splat as a raw PLY, so a million splats is about 248 MB. As SPZ it is roughly a tenth of that. My demo scene is 301,000 splats in 4.4 MB.

Do Gaussian splats work on iPhone and Android?

Yes, in a browser with WebGL2. Spark says it works on almost all devices, through WebGL2, and suggests 1 to 3 million splats on an iPhone and 1 to 2 million on an Android phone.

Is a splat better than photogrammetry?

They do different jobs. Photogrammetry gives you a mesh you can relight and use in a game engine. A splat looks more like the photos, but its lighting is fixed.

If you need a 3D scan on your site, or a whole 3D web experience around it, see 3D web experiences or write to me at m@tawfik.tv.

Read next

See all notes