Using Tiled and multileveled splats in three.js

By Emeric Beaufays — Oct 7, 2025

This article is for developers who want to render tiled and multileveled 3DGS in three.js via threedtiles.

ContextSplat lets you drag & drop local splat files (.ply, .splat, ...) to be automatically tiled and multileveled into an OGC 3D Tiles tileset (with splat content) and packaged for download so you can serve the tileset over HTTP.

on-the-fly tiling

The tiling performed inside the app is fast and convenient but coarse by design. it's meant for previews and quick sharing. For production-grade tiling, better decimation and support for unlimited size datasets, I provide an offline tiling service that produces higher-quality multilevel tilesets.

How the browser tiler works (high level)

At a high level the pipeline executed in the browser is:

  1. Read the dropped splat file and decode positions & attributes
  2. decimate and compute an octree partitioning
  3. Generate tiles with splats (Gaussian splats) and emit glTF content with a small extension for splat compression
  4. Bundle tiles and a root tileset.json into a ZIP for download

Using the app — drag & drop

Load or Drop your splat files (.ply, .splat, .ksplat, .spz) onto the page. the file is processed and the app produces a ZIP containing:

Drop area screenshot placeholder
Load PLY
Tiling result placeholder
Download OGC3DTiles or three.js starter app

Examples — loading OGC3DTiles in a three.js app

Below are simple examples illustrating common patterns. The exact API objects and names come from the threedtiles project; these snippets are illustrative — consult the threedtiles README for the definitive API.

Load a tileset and add it to a three.js scene

import * as THREE from 'three';
// Import the threedtiles loader/renderer from the library
import { TileLoader, OGC3DTile } from '@jdultra/threedtiles';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(60, innerWidth/innerHeight, 0.1, 10000);
const renderer = new THREE.WebGLRenderer({antialias:true});
document.body.appendChild(renderer.domElement);

// Load a tileset.json hosted on a server
const tilesetUrl = 'https://example.org/tileset.json';

// Tile Loader handles the strategy for loading tiles
const tileLoader = new TileLoader({
    renderer: renderer,
    maxCachedItems: 50, // max cached tile content
    timeout: 5000 // timeout before removing tile content from cache
});

// OGC3DTile is a three.js Object3D containing the tiles and content
const ogc3DTile = new OGC3DTile({   
    url: "http://localhost:8082/tileset.json", //UM
    renderer: renderer,
    geometricErrorMultiplier: 0.5, // load more or less detail
    tileLoader: tileLoader,
    centerModel: true,
    splatsQuality: 0.75,
});

scene.add(ogc3DTile);

// In the render loop call the library update so it can load/unload tiles based on the camera
function animate(){
  requestAnimationFrame(animate);
  tileLoader.update();
  ogc3DTile.update(camera);
  renderer.render(scene, camera);
}
animate();

Splats, points and mesh

The tiler and runtime focus on splats (Gaussian splats) but The same threedtiles library supports mesh and point-cloud OGC3DTiles

Where to host your tileset

Any static HTTP server works: GitHub Pages, an S3 bucket, or a small Node/Express server serving the tileset directory. After downloading the ZIP produced by the app, unzip it into a folder and ensure the tileset.json and tile files are reachable over HTTP.

References