POINT CLOUDS / WEBGPU / TYPESCRIPT

Two hundred million points,
in a browser tab.

That is one 241-million-point survey on a bucket, streamed by HTTP Range: only what the camera can see ever reaches the GPU. The stack behind it is split into a neutral core, a loader, a renderer and thin bindings — WebGPU where the browser has it, WebGL 2 where it does not. Install the pieces you need and keep the rest out of your bundle.

01 / START HERE

Install the pieces you need.
One package per job.

PUBLIC PACKAGES
install

npm install @voxelkloud/react

import { PointCloudViewer } from '@voxelkloud/react'

<PointCloudViewer
  url="/pointclouds/my-cloud/"
  lod={{ pointBudget: 3_000_000 }}
/>

Need the technical reference? The docs page covers the loader contract, LOD selection, culling, and the public package entry points.

Open docs

02 / PACKAGE BOUNDARIES

What each package owns.
Nothing more.

The split is the point: `core` owns the shared types and math, `loader` resolves a URL to a source and tree, `view` renders, and React or Vue only handles lifecycle.

LOADER / VIEW / BINDINGS
  1. 01npm install @voxelkloud/react threeOr use @voxelkloud/vue, or `@voxelkloud/view` and `@voxelkloud/loader` directly. `three` stays a peer dependency because the renderer builds on `WebGPURenderer` and TSL.
  2. 02Load a URL, not a format branchThe loader resolves the URL to the matching driver and returns `source`, `tree`, and `openPoints`. A Potree v2 directory, COPC file, EPT layout, 3D Tiles tileset, or a bare LAZ each lands in the same neutral contract.
  3. 03Pass the objects into the viewThe view owns the renderer, camera, and selection loop. `view.camera` and `view.scene` stay available for controls, picking, measurements, and anything else your app needs.

03 / WHY IT IS SPLIT

Responsibilities stay
separate on purpose.

01

One vocabulary, not six

Bounding boxes, coordinates, transport and octree maths are defined once, in `@voxelkloud/core`, and every other package reads those same definitions. Nothing has to translate between packages, so nothing gets lost translating.

02

Point at a URL

`@voxelkloud/loader` works out the format from the address and hands back the same shape whatever it found. Your code has no branch in it for COPC versus EPT versus Potree.

03

The scene stays yours

`@voxelkloud/view` drives the GPU, but `view.camera` and `view.scene` are ordinary three.js objects. Add a mesh, move the camera, run your own frame loop — the renderer is a participant in your scene, not the owner of it.

04

React and Vue are wrappers, not forks

They handle mounting and unmounting, and nothing else. A feature reaches them the day it lands in the renderer, because there is no second copy of it to update.

05

You can see why a frame looks the way it does

Set a target error and a point budget, then read back what actually bound. `stats.limitedBy` says whether it was quality or the budget — so tuning is reading a number, not guessing.

06

You ship the formats you read

COPC, EPT, Potree v2, 3D Tiles and the no-index tier are separate installs. Read one format and your bundle carries one reader.

07

Click a point, get the point

`pickPoint` turns a screen position into real survey coordinates at full precision, not a rounded guess. `heightAt` answers ground height straight away, with no round trip to a server.

08

Two surveys, one scene

Clouds captured in different coordinate systems line up, because `@voxelkloud/wasm-proj` converts between them. Place a whole cloud at once, or convert every point.

09

There is a command line too

`voxelkloud` inspects a cloud, tells you whether your server is delivering it properly, converts a file that arrived with no index, and renders a thumbnail without opening a browser.

04 / CONFIGURATION

Runtime knobs.

Every setting maps to a real decision in the selection, memory, or shading pipeline.

lod.targetScreenError1.35Screen-space target for selection, in device pixels
lod.pointBudget3,000,000Maximum selected points
material.colorModergbrgb / elevation / level / intensity / classification / flat
edlfalsePotree’s exact 8-neighbour formulation
decompress@voxelkloud/loader/brotliOptional decoder for BROTLI clouds, never auto-imported
sinkMode"auto"Compute on WebGPU, else points on WebGL 2; "compute", "points", "arena", "per-node" pin one
maxResidentBytes512 MiBLeast-recently-selected eviction

05 / SUPPORTED INPUTS

Each input has its own
driver and entry point.

Use the driver that matches the data you already have. The rows below show what each format expects and the package or command that opens it.

FORMATWHAT IT ISENTRYAVAILABILITY
COPCOne LAS 1.4 file with the octree inside it. Cloud Optimized Point Cloud.364M points out of a 2 GB file, opened with three ranged reads totalling 0.79 MB.NonePublic@voxelkloud/format-copc
EPTEntwine Point Tile: a manifest, JSON hierarchy pages, one file per node.Static hosting, no Range support required — which is how the USGS 3DEP archive is published.NonePublic@voxelkloud/format-ept
Potree v2The directory PotreeConverter writes: metadata.json, hierarchy.bin, octree.bin.DEFAULT and BROTLI. The deployment you already serve, read as it is.Already donePublic@voxelkloud/format-potree
LAS / LAZA single file with no index. Drag it onto the page.The octree is built in a worker from the converter's own partitioner, compiled to wasm. 20M points is the ceiling; past that, convert it.In the browserPublic@voxelkloud/format-single
E57The terrestrial-scanner interchange format. FARO, Leica, Trimble.Scan poses applied, spherical coordinates converted, and the no-returns dropped rather than piled at the origin — 215,329 of the 370,530 records in libE57's own pump scan.In the browser, or voxelkloud convertPublic@voxelkloud/format-single
3D TilesOGC tileset, glTF payloads, geometric error rather than point spacing.tileset.json, external tilesets, implicit tiling, and content as .pnts or glTF POINTS. The scheduler holds a tile error the same way it holds a point pitch.NonePublic@voxelkloud/format-3dtiles

Release status. Every driver above is on npm at 0.5.1, and the CLI at 0.5.2. @voxelkloud/loader registers the Potree v2 driver for you; the others install alongside it and register themselves, so a bundle only carries the readers it actually uses.

There is a command line too. voxelkloud convert turns LAS, LAZ, E57 or COPC into an indexed cloud. voxelkloud doctor grades byte ranges, CORS, encoding and MIME on a deployment you already have. voxelkloud optimize re-encodes a cloud for delivery without rebuilding its tree, and voxelkloud snapshot renders a PNG thumbnail on the CPU with no browser involved. npm install -g voxelkloud.

Have a file with no index? Convert it in your browser — drop a .laz in and get a .copc.laz back, with nothing uploaded. The same partitioner the command line runs, compiled to wasm.

Migrating from Potree? Read the migration notes and the switch checklist.

06 / TEST DATA

What was measured
and under which conditions.

Against Potree, on the same cloud

Same origin, same camera, same 3M points on screen, median of 2 cold runs. Seven of nine rows go to voxelkloud:

56 msINP · Potree 104, potree-core 200
522 msfirst ink · Potree 1,233, potree-core 622
66.6 MBJS heap · Potree 254, potree-core 212

Two go the other way, both in the tail rather than the start: Speed Index (1,918 against Potree’s 1,493) and visually complete (23.5 s against 21.4 s). The full table, the conditions, and why the Speed Index row is partly an artefact of the metric.