Dataset source URL (?src=...). Null when not provided.
Theme override (?theme=light etc). Null when not provided.
Browser tab title (?title=...). luxar serve --open derives it from
the dataset file name so several open viewer tabs are tellable apart;
a scene's authored viewer_config.title overrides it at load.
Remote-control socket URL, already resolved and validated
(?control, or ?control=ws://host/control to split the origin).
Null when control is off — which is the default — or when the supplied
value was refused. See normalizeControlSocketUrl.
Shared secret presented to the hub as ?token= (?controlToken=...),
matching luxar serve --control-token. Null when the hub is open.
A token in a query string lands in browser history and in the address bar of whatever tablet is driving the display. That is acceptable for a LAN kiosk and is not a substitute for not exposing the hub to a network you do not trust.
Permit a cross-origin control socket (?controlAllowCrossOrigin). Off by
default so a crafted link cannot point the display at someone else's hub.
Alternative control-panel module (?panel=/my-panel.js), resolved and
validated same-origin. Null when absent or refused.
Read only by control.html; the viewer itself ignores it. See
normalizePanelModuleUrl.
Enable the window.__luxarDebug interface (?debug).
?kiosk — lock this display down for unattended public use.
A hard override over the scene's authored ui.kiosk block, because this
is the OPERATOR's channel: a store that predates the block, or one
borrowed for an exhibit it was never authored for, still has to be
lockable from the launch command. See config/kiosk.ts.
Disable all cache layers (?noCache).
Disable only the SliceCache / S-cache (?noSliceCache).
Disable only the L2 OPFS persistent tier (?noOpfs); L0/L1/S-cache
stay on. The deterministic sibling of the OPFS circuit breaker — use
it in environments whose OPFS is known to stall (automated Chromium).
Override the page-wide OPFS read cap (?opfsReadConcurrency=N).
Verbose cache logging (?cacheDebug).
Clear caches on init (?clearCache).
Whether the substitutive-LOD cross-fade is enabled: blend adjacent LOD
levels' opacity as the camera zooms across their boundary instead of a hard
visibility swap, for blendable (additive/luminous/volumetric) layers
(anti-popping). On by
default; pass ?noLodFade to disable it (e.g. to compare against the
hard swap or isolate a rendering issue).
Whether a picked element's authored link may be opened on left-click
(issue #1917). On by default; pass ?noLinks to disable it.
The switch an embedder showing third-party scenes wants: .zattrs is
untrusted, so this guarantees no navigation can originate in the data. It
suppresses the navigation, the two link items in the right-click menu and
the pointer cursor; Copy still works, since the clipboard is not
navigation.
Whether streaming brightness compensation is enabled: as a blendable
(additive/luminous/volumetric)
LOD leaf's additive ladder streams in, scale its opacity by 1/e(k) so the
partial prefix renders at full-level brightness instead of brightening up as
chunks arrive (anti-popping on the time axis, orthogonal to lodFade's
distance axis). On by default; pass ?noLodEnergy to disable it (e.g.
to compare against the uncompensated brightening ramp).
Force the finest LOD level regardless of projected screen coverage
(?lodFinest). For high-quality still/video capture — the gallery
harness appends it — where a coarse level would look blurry even though
the subject is small in frame. Off by default (opt-in, unlike the
three on-by-default flags above).
Session-wide replacement-LOD bias (?lodBias=<positive number>), in
screen-area units. 2 advances an occupancy-halved ladder by one level;
4 by two. Null keeps the neutral 1 default.
WebGL-only blend warm-up. On by default; pass ?noBlendWarmup
to disable the off-interaction-path pre-linking of reachable
blend-mode program variants.
Whether gsplat depth sorting is enabled (depth-sorting Phases 2-3): the
async worker sort that keeps normal-mode splats composited back-to-front,
plus the per-frame camera-motion re-sort scheduler. On by default; pass
?depthSort=0 (also false/off) to disable it — normal-mode gsplats
then keep the identity (storage) order, which pins deterministic output for
E2E/visual runs and reproduces pre-Phase-2 behavior for comparison.
Projected-density guard (per-node keep-fraction thinning + refinement
rung cap on over-drawn nodes; config.densityGuard). On by default;
?noDensityGuard disables it for the session — the A/B lever for
the audit bench and for reproducing an overdraw report.
Session-only override of the density guard's blendable cap
(?densityCap=8, elements per drawing-buffer pixel;
config.densityGuard.capElementsPerPixel is 4). Both consumers follow
it — the shader keep-fraction ladder and the refinement rung gate — so
a threshold sweep is one URL edit per arm, no rebuild and nothing
persisted. The non-blendable cap (1) only moves when the override is
below it, so it stays the tighter of the two. Null/invalid ⇒ the
configured cap.
Disable adjacent-chunk prefetching (?noPrefetch).
Verbose prefetch logging (?prefetchDebug).
Auto-open the data-loading monitor in expanded mode on the Cache tab
(?cacheStats). Useful for measuring L0/L1/L2 hit rates without
having to find the monitor's keyboard shortcut first.
Force a specific rendering backend regardless of the default resolution. Useful for per-load A/B comparisons and for diagnosing TSL-vs-GLSL divergences without restarting the dev server.
?renderer=webgl — THREE.WebGLRenderer + GLSL ShaderMaterial
(the production default).?renderer=webgpu — opt into WebGPURenderer + TSL
NodeMaterial. The renderer internally dispatches to a real
WebGPU adapter when available or falls back to its WebGL2
backend otherwise.null) — fall back to the build-time
VITE_LUXAR_USE_WEBGPU env var (opt-in to WebGPU); if that is
also unset, the default is webgl.Any other value is normalized to null (defer to env / default).
Diagnostic flag (?webgpuForceWebgl) that keeps the
WebGPURenderer / TSL NodeMaterial pipeline selected but asks
Three.js to back it with its internal WebGL2 backend instead of a
native WebGPU adapter. Ignored when renderer resolves to webgl.
Opt-in to GPU timestamp queries (?perfTimestamp). Only honored
under WebGPURenderer with a backend that exposes the
timestamp-query feature. When set, the renderer is constructed
with { trackTimestamp: true } and the perf bench reads
per-frame GPU time via renderer.resolveTimestampsAsync('render').
Has a small runtime cost so the perf bench is the only intended
caller; never set on the production viewer URL.
Override the adaptive GPU-geometry byte budget, in megabytes
(?gpuBudgetMB=1536). Pins the single VRAM budget shared by the
buffer pool and LOD-group retention, bypassing the auto-size
heuristic. Useful for large scenes on high-VRAM machines (raise it)
or for testing eviction on constrained ones (lower it). 0 disables
the byte budget (unbounded resident geometry). Null/invalid (missing
or negative) ⇒ auto-size from navigator.deviceMemory.
Override the total in-memory cache pool (L0 + L1 + S-cache), in megabytes
(?cacheBudgetMB=1536). Used where performance.memory is unavailable —
WKWebView (the native app) and Safari — so heap-aware sizing has a real
budget to split instead of the tiny fixed fallback. The native launcher
injects it automatically. Its implied non-cache remainder also replaces
the heap-derived GPU-geometry signal in either direction. Null/invalid ⇒
fall back to the measured heap, then to the fixed config sizes. See
cache/heap-budget.ts.
Pin a fixed device pixel ratio and disable adaptive DPR for the
session (?dpr=1). The value is clamped to [0.25, native DPR] at
apply time and the adaptive-resolution toggle is locked off so
persisted settings can't silently re-enable it. Primarily for
deterministic E2E/visual-regression runs, agent:debug sessions,
and bug repros. Null/invalid (missing, non-numeric, <= 0) ⇒ normal
adaptive behavior.
Force the session's JS input profile (?input=touch|mouse): pointer flags,
hover capability, touch points, and device tier. This changes device-class
fallback budgets (touch only — mouse keeps the detected tier),
primary-tip pen routing, the Safari gesture-canceller gate, and whether the
help overlay lists its Touch section; touch additionally applies the
mobile rendering budgets (adaptive-DPR floor and refresh ceiling, high-DPR
cap, GPU-byte and element-texture ceilings, data-worker count) and skips
the blend-variant program warm-up. Stylesheets and non-pen gesture routing
keep following the real media features and PointerEvent.pointerType, so a
faithful check still needs device emulation or a real device. null
(missing or unrecognised) ⇒ detect from the browser. See
utils/input-capabilities.ts.
Force a line join style for the session (?lineJoin=none|miter).
Overrides whatever each node authored, which is exactly its purpose: it is
a debugging and workaround lever, so it must win over the scene file.
Precedence is ?lineJoin= > authored node attribute > the built-in
default. null (missing or unrecognised) means "no override" — distinct
from 'none', which is an explicit request for no join geometry. See
types/line-join.ts.
Select the line rendering primitive for the session
(?linePrimitive=screen-space|capsule, issue #1352). The session's
strongest word: it overrides the Advanced → Line primitive policy
setting (whose auto mode otherwise sizes the scene before material
build — see types/line-primitive.ts).
capsule (the default) profiles the 2D point-to-segment distance in
pixel space — direction-stable end-on, bisector-cut joins;
screen-space is the classic flat quad. Session-wide by design (a
renderer implementation choice, not scene content — there is no
authored per-node attribute). null (missing or unrecognised) means
the built-in default. See types/line-primitive.ts.
Bake the scene environment (?bakeEnv, driven by luxar env bake): once
the load settles, capture the scene-derived cube map at probe /
envResolution, expose the container on __luxarDebug.environment.lastBake
and download it. See rendering/environment/bake.ts.
Probe for the bake (?probe=auto|node:<path>|x,y,z). Null → the scene's config or auto.
Cube face size for the bake (?envResolution=128). Null → the scene's config or 128.
All URL parameters recognized by the viewer, as a typed snapshot.
Produced once by readUrlParams and threaded through the app; every consumer that wants a URL-derived value accepts the relevant field via options rather than reading
window.locationitself. Adding a new recognized parameter means adding a field here and a line to readUrlParams.