Skip to content

Latest commit

 

History

3,184 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trillion3D

Virtualized geometry for the web — a native Rust compiler, a WebGPU/WebGL2 runtime in TypeScript, and a bench that proves every number.

Rust TypeScript strict WebGPU WebGL2 Node 22 pnpm Quality Tests License

Documentation ↗ · Live report ↗ · Why · Quick start · Compiler · SDK · Architecture · Bench · The reference in numbers · Roadmap

Create a world: createWorld(canvasOrId), add objects or scene.load a compiled model, onFrame for per-frame work. It owns the scene, the camera, the renderer and the loop, and pauses once the image is stable.


Why Trillion3D

The best desktop engines changed what a scene can hold: geometry is streamed by clusters, one cut through a DAG per frame, drawn through a visibility buffer, resolved by temporal antialiasing, held under a fixed memory budget. None of that exists for the browser. Trillion3D builds it for the web's constraints — no hardware ray tracing, bounded and unreadable GPU memory, one browser frame — from the published literature only, and measures itself against the numbers those engines publish. The geometry is the foundation; the lighting is what it is for.

Parity means four things, and none of them is a pixel count:

Fixed budgets memory in bytes and frame time in milliseconds are set, not discovered on the machine
Residency by the frame what stays on the GPU is what the frame actually read, pages and texture tiles alike
Compression at cook time the compiler pays once; the runtime decodes pages, it never recomputes them
No work in a still scene a fixed camera redraws zero pages — measured, not assumed

What it does

Area Implemented scope
Native compiler glTF/GLB, FBX, OBJ, USD/USDZ, Alembic, .blend, Maya ASCII and Unity scenes and packages, with a dozen image formats, read by its own drivers (no external tool); verified source hashes; a cluster DAG that reaches a single root — clusters grouped, simplified and welded level by level, each carrying its screen error; a flat culling hierarchy; streaming bundles; a bounded worker pool; DAG warnings reported to the CLI and to the engine
Cache SHA-addressed page, geometry-page and bundle objects; every persisted entry validated before reuse; formatVersion separate from compilerVersion, unknown formats rejected
WebGPU page raster GPU frustum + lodScore cut in compute, conservative backface cones, two-phase Hi-Z occlusion, visibility-buffer encode through at most six non-indexed drawIndirect commands, deferred material shading, temporal antialiasing
Textures virtual texturing: a bounded tile pool, per-tile feedback read back by rank, residency driven by what the frame sampled
Lighting Cook-Torrance GGX, no fixed ambient term — ambient only comes from a declared light.ambient/light.hemisphere, and a surface no light reaches stays black; sun and lamps through virtual shadow maps — a page table over a fixed pool, the level chosen per pixel, only the pages the image reads drawn — under a 1 ms budget; per-tile light rejection — the stochastic and screen-space stages are the roadmap
Memory fixed reservoirs for pages and tiles like the reference, adjustable in session without losing residency; no image cap; a cpu-timing diagnostic and per-step CPU profile
Fallbacks a world takes WebGPU pages by default when the machine grants a device, WebGL2 pages otherwise; the CPU cut stays the A/A oracle; a forced renderer the machine lacks is refused by name, never swapped
Jobs immutable progress snapshots, subscriptions, bounded cancellation, explicit failure semantics

Quick start

Requirements: Node.js 22.18 or newer, pnpm, and a Rust toolchain with Cargo on your path.

pnpm install
pnpm run build           # TypeScript → dist/ (ESM + declarations)
pnpm run build:native    # → packages/asset-compiler-rust/target/release/trillion3d-compiler
pnpm test                # unit and integration tests (node --test)
pnpm run test:native     # cargo test

The package is private and consumed locally; it is not published to npm. Scene assets are supplied by the host and are not part of this repository.

import { createWorld, object, geometry, material, light } from 'trillion3d';

const world = createWorld('viewer'); // a canvas element, or its id

const ball = object.mesh(geometry.sphere(1), material.meshStandard({ color: 0x8899aa }));
world.scene.add(ball);
world.scene.add(light.directional({ intensity: 3, position: [5, 10, 2] }));

await world.scene.load('assets/city/manifest.json'); // a compiled model, added like anything else

world.onFrame(({ delta }) => {
  ball.rotation.y += delta;
  world.invalidate();
});

Native compiler

All preparation happens in one executable, trillion3d-compiler. It reads the source, writes the cache to disk and talks to its host through three streams only: JSON events on stderr, a small pointer on stdout, cancel requests on stdin.

packages/asset-compiler-rust/target/release/trillion3d-compiler scenes/city/city.obj cache/city full 150000 8 8192 /assets/city/ qem-endpoints
packages/asset-compiler-rust/target/release/trillion3d-compiler --jobs jobs.json   # many models, bounded workers, one process

trillion3d (prepare, prepareMany in Node) is a thin relay over it; any other host (Electron, a CI script, another language) can drive it the same way. Full reference: docs/COMPILER.md.

Public SDK

Every consumer imports trillion3d. Conditional exports provide common maths and contracts in all environments, rendering APIs to browser bundlers, and native preparation APIs to Node.

Environment Available API
Common and worker Versioned contracts, maths, jobs, diagnostics and safety policy
Node Common API plus native compiler process adapter and compilation jobs
Browser bundler Common API plus createWorld and its families (geometry, material, light, camera, object, page, budget, metric, diagnostic, capability, capture, pose, batch, …)

An application owns the canvas, its resource URLs and controller disposal; the world owns its own loop by default (interactive: false + world.render() for a host-led loop instead). Node hosts own source/cache directories and process configuration. React and Electron integrations use these boundaries without bringing a framework into the core. Consumers use public exports, never internal source paths. See the SDK guide and the architecture notes.

Architecture

Host-owned source assets
          │
          ▼
Node adapter → Native Rust compiler
                      │
                      ▼
          Versioned manifest + cached pages
                      │
                      ▼
              Browser adapter (WebGPU page raster · WebGL2 fallbacks)
                      │
                      ▼
             Host-owned canvas

Core: contracts · jobs · cancellation · diagnostics · safety policy
Directory Responsibility
packages/asset-compiler-rust Preparation library and native CLI
packages/page-codec Reference geometry-page encoder used to test the browser decoder
packages/sdk-core Platform-independent TypeScript contracts and policies
packages/sdk-node Native process and filesystem integration
packages/sdk-browser Browser rendering and GPU resource adapters
bench/runner The bench: one harness, campaigns and the HTML report
tests Public package integration tests and GPU proofs

Measuring

Nothing is optimised before it is measured, and no claim outlives its measurement.

node bench/runner/bench.ts --moteur webgpu --avant <git-ref|dist> --apres <git-ref|dist> \
     --vues generale,sol,rue --images 60 --pixelError 0,1
node bench/runner/campaign.ts        # the whole campaign
node bench/runner/summaryGlobal.ts   # one HTML report
  • One harness, Playwright driving the machine's Chrome, nothing on disk beyond .mesure/assets/.
  • Before/after in one run, same poses, lights, caches and server — and the engine facing two witnesses: bare Three.js and Three.js with a three-level THREE.LOD (the classic method).
  • The measurement rules — identical budgets, null for the unmeasured, CPU and GPU never added, differences read on the frame envelope — are in CONTRIBUTING.md.

See bench/runner/README.md and docs/TESTS.md.

Quality bar

Every source file fits 200 lines, no block is duplicated, core packages never see the DOM, and pnpm run validate — format, lint, Clippy, unused code, builds, declarations, links, every JS/TS/Rust test — gates each pull request in CI (quality.yml); pnpm run test:gpu adds the proofs on a real GPU. The gates, one by one: docs/TESTS.md. The rules a contribution follows: CONTRIBUTING.md.

Documentation

Every document, and what it is for, is listed once in docs/README.md. The documentation, the code, its identifiers and this page are in English.

Roadmap

The geometry, the temporal antialiasing and the memory budgets are the foundation. What they are for is real-time dynamic global illumination, reflections and shadows — reached by stages, each measured before the next (lighting strategy):

Stage Content State
L0 Direct lighting and sun costed on the bench done — the sun costs its shadow sampling, not its cascades
L1 Screen traces: reflections and short bounce from the rendered HDR, depth and normal next
L2 Stochastic direct lighting denoised by TAA: dozens of lights at the price of one planned
L3 Virtual shadow pages from the hardware raster, only the pages seen, cached planned
L4 Cooked global distance field traversed in compute, reading a surface cache planned
L5 World radiance probes in cascades planned
L6 Reflections through the distance field reading the cache planned

Open tasks are tracked as GitHub issues; an issue is closed once it is done.

Current limits

  • Not yet a general-purpose engine: scene.load reads a versioned source manifest and the source it names; non-triangle primitives and non-standard glTF extensions are unsupported. A world built in code — geometry/material/object/light — does not go through the compiler at all.
  • Delivered simplification and page compression are those documented in docs/FORMAT.md; the compiler's RAM option is an admission estimate, not an enforced peak-memory limit.
  • Specular environment-map IBL, full device-loss recovery and cross-API fallback are not implemented; a missing visbuffer format falls back to the untextured page raster with Hi-Z off.
  • No N-API binding of the compiler, published packages, signed native distributions or cross-platform performance CI yet; WebAssembly serves the page decoder, three math kernels and the physics.
  • Physics (docs/SDK.md) steps Jolt on its thread pool when the page is cross-origin isolated, on one worker elsewhere; what 10,000 boxes landing at once cost is measured there.

Licence

Trillion3D is published under the PolyForm Noncommercial License 1.0.0: free for noncommercial use, study, research and personal projects. Commercial use requires a separate licence from the copyright holder — open an issue or contact the author.

Copyright © 2026 Alban Pasquelin.

The physics is Jolt Physics (MIT), built from its official sources: see THIRD_PARTY_NOTICES.md.

About

Trillion3D — virtualized geometry and real-time rendering for the web: GPU-driven cluster culling, streaming under a fixed memory budget, temporal antialiasing and dynamic lighting. Docs and live demos: https://www.trillion3d.com

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages