Examples
All demos below are live, deployed pages — not screenshots or embeds. Every one needs a WebGPU browser (Chrome/Edge stable, Safari 26+, Firefox rolling out); see Introduction if a demo shows a "needs WebGPU" banner instead of running.
Hello world
The 10-line story: a noisy render → Denoiser.create() → denoise() → canvas. No
three.js, no build tricks — the page shows the exact source next to the result.
Start here. Walkthrough: Quick start.
Gallery
The flagship quality demo. Pre-rendered path-traced scenes at 1–16 samples per pixel (plus aux buffers and a converged reference), denoised live in the browser: drag the before/after divider (there is no camera to orbit), step the noise ladder, toggle albedo+normal guidance on the same frame. For an interactive scene, use the three.js path tracer demo.
Aux inputs
What the network actually sees. Shows color, albedo, and normal exactly as fed to the model, alongside examples of the real mistakes that degrade aux quality — environment-hit normals, alpha-blended normals, HDR albedo clamping. The live companion to Models & weights and the aux-inputs guide.
webgpu-raw
Proof of engine-neutrality: a single-file WGSL toy path tracer with no framework —
no three.js, no Babylon, no bundler magic — feeding denoiseTextures on the same
GPUDevice. The reference for integrating a custom engine that isn't three.js.
Pipeline Lab
The full offline pipeline in one page: three-gpu-pathtracer renders below the output
size, this library denoises it, and @pmndrs/upscaler (FSR1) scales it back up, all on one
GPUDevice through the path tracer's own setDenoiser / setUpscaler hooks. Every
stage is tweakable, there are four scenes (or drop in your own .glb), and a benchmark
times each stage and scores it against a high-sample reference. See
Benchmarking on your machine. Upscaling is spatial only for
now: the temporal (FSR3) path needs a fresh, jittered render every frame, and the path tracer
accumulates one image instead (pmndrs/upscaler#93).
three.js path tracer
three r186 WebGPUPathTracer and this library sharing one GPUDevice: progressive
path tracing, denoised live while it accumulates, CPU-copy and zero-copy paths
side by side. See The GPUDevice for how the shared
device works. ?fsr=1 path-traces and denoises at half resolution, then upscales 2x with
@pmndrs/upscaler's FSR1 (EASU + RCAS).
The WebGPU path tracer is early-stage upstream work in three-gpu-pathtracer
(main, 0.0.27), pinned to a commit SHA for this demo — expect rough edges.
LDraw Eiffel Tower
A LEGO Eiffel Tower on a table: fast raster preview while you orbit, path-trace + denoise the moment the camera comes to rest. Same pinned-pathtracer caveat as above.
Benchmark
The performance harness behind the numbers in Performance: cold + warm timings, per-stage stats, and fp16-vs-fp32 PSNR across image sizes — reproducible in your own browser, on your own hardware.
Real-time (temporal) denoising
These use the FidelityFX denoisers (denoiser/ffx, denoiser/three), not OIDN. See
Which denoiser do I need?
Ray-traced shadows and reflections in a raster app
The "when would I use this?" demo. A furnished room in a normal three.js raster
pipeline, with two effects ray traced at 1 ray per pixel: area-light shadows,
traced against the real scene meshes with three-mesh-bvh's WebGPU BVH, and glossy
SSR. ffxShadows() and ffxReflections() denoise them every frame. Toggle each
one against what three.js does without ray tracing (a VSM shadow map, env-map-only
reflections) and against a converged reference. Use the light-size slider to see
contact hardening. A live table shows each pass's GPU cost. There's an optional
half-resolution + FSR3 path.
Reflections, explained: probe, SSR, ray tracing
An explainer for the three ways a real-time renderer finds reflections, and the hybrid that
mixes them: a box-projected reflection probe (captured once, prefiltered per roughness), three's
SSR, and rays traced against the scene with three-mesh-bvh. A guided tour sets up one situation
per weakness (a mirror, things off screen, moving objects, contact, rough surfaces) and shows two
methods split-screen; a "where reflections come from" view tints every pixel by what answered
it. Every noisy mode takes one sample per pixel, denoised by ffxReflections(), with a cost
table and a "which one should I use?" guide.
Reflections in two rooms: probes, SSR and rays
The two rooms from Ben Houston's reflection probes example, with a polished floor, lights that
change colour and a mirror ball rolling through the doorway. One probe per room plus a doorway
probe give every surface its own room's reflection for almost nothing per frame. SSR and one
traced ray per pixel (three-mesh-bvh), denoised by ffxReflections(), add what probes can't
have: the moving ball (kept out of the captures), contact, and what the probe never saw. A guided
tour compares the modes split-screen; the probes re-bake when the lights change (about 2 ms for all
three) or can be frozen to show them going stale. A cost table times each pass.
Reflection probes on r186 (preview of three.js #35046)
Ben Houston's reflection probes (three.js #35046)
running on three r186 until that PR lands: probes you place per room, box-projected onto the
walls, blended at their edges, with smaller probes (a doorway) taking priority and
scene.environment filling the rest. Same API and scene as the PR's example. r186 can't bind
cube arrays, so the cubes live in a 2D array texture and the lookup picks the face itself, with
a seam fix so rough surfaces don't show face edges. Matches the PR's output to within 8-bit
noise; three probes bake in 3–5 ms. This is example code, not part of the denoiser package:
when #35046 ships, swap the imports for three's and re-bake.
Baked + dynamic shadows: when to split
The static / dynamic split engines use for lightmaps, in the browser: the static half of the
shadow baked once into a lightmap (16 rays per texel, cleaned by OIDN) or gathered in a
world-space cache, and 1 ray per pixel against only the moving objects, denoised every frame by
ffxShadows(). Explains what the split buys (converged, steady static shadows; rays that only
test moving objects) and costs (bake time, UVs, memory, a light that can't move), with measured
numbers and when to use it. Both denoisers on one page: OIDN at bake time, FFX live.
three.js SSR: FidelityFX vs recurrentDenoise
three's webgpu_postprocessing_ssr_denoise example with ffxReflections() swapped
in, split-screen against three's own temporal denoiser.
FidelityFX denoisers, raw WGSL
The test bed behind the numbers in Real-time (temporal) denoising: 1-sample shadows and reflections, noisy / denoised / reference panels, no three.js.