demo · v139
Depth Data Visualizer
Visualize a WebXR depth buffer as a false-colour heatmap. Toggle between raw and smoothed (3-frame rolling average), switch data format and usage mode, and watch performance stats update in real time. No headset needed — a synthetic scene runs the simulation.
Live WebXR depth sensing requires an AR-capable device and headset. This page simulates the depth buffer on a synthetic scene so the full visualization and format/usage controls are interactive everywhere. The WebXR call shape is shown in the code section.
feature detection
Checking…
depth heatmap — stopped
near
far
—
depth fps
320×240
texture size
—
buffer (KB)
—
format/usage
Performance tips:
Fastest path: gpu-optimized + float32 — depth texture uploaded directly to GPU, no CPU readback, no format conversion.
Most compatible: cpu-optimized + luminance-alpha — required on devices where GPU path is unavailable; also better for CPU-side occlusion checks.
Smoothing cost: 3-frame rolling average adds ~1ms CPU per frame; prefer the runtime smooth mode (depthType: "smooth") which uses the sensor's hardware denoising at zero CPU cost.
Fastest path: gpu-optimized + float32 — depth texture uploaded directly to GPU, no CPU readback, no format conversion.
Most compatible: cpu-optimized + luminance-alpha — required on devices where GPU path is unavailable; also better for CPU-side occlusion checks.
Smoothing cost: 3-frame rolling average adds ~1ms CPU per frame; prefer the runtime smooth mode (depthType: "smooth") which uses the sensor's hardware denoising at zero CPU cost.
the code
// Request a WebXR AR session with depth sensing
const session = await navigator.xr.requestSession("immersive-ar", {
requiredFeatures: ["depth-sensing"],
depthSensing: {
usagePreference: ["gpu-optimized", "cpu-optimized"],
dataFormatPreference: ["float32", "luminance-alpha"],
},
});
// Per-frame depth access (Chrome 139: improved performance)
session.requestAnimationFrame((time, frame) => {
const depthInfo = frame.getDepthInformation(frame.getViewerPose(refSpace).views[0]);
if (!depthInfo) return;
// depthInfo.width, depthInfo.height — texture dimensions
// depthInfo.rawValueToMeters — scale factor
// depthInfo.getDepthInMeters(x, y) — CPU path (cpu-optimized)
// depthInfo.texture — GPU path (gpu-optimized)
for (let y = 0; y < depthInfo.height; y++) {
for (let x = 0; x < depthInfo.width; x++) {
const depthMeters = depthInfo.getDepthInMeters(x / depthInfo.width,
y / depthInfo.height);
// map depthMeters to heatmap colour…
}
}
});