@realitycollective/xrblocks-environment
The Google XR Blocks adapter for the Reality Collective WebXR Environment Extensions. EXPERIMENTAL, in the same sense as the other XR Blocks adapters in this estate: it is written against the shape of XR Blocks rather than importing it, and XR Blocks is moving quickly.
It re-exports @realitycollective/threejs-environment, which re-exports the engine-free core, so this is the only package you install.
npm install @realitycollective/xrblocks-environment three
Use
import {
createXRBlocksEnvironment,
DEFAULT_OCCLUSION,
STOCK_PRESETS,
} from "@realitycollective/xrblocks-environment";
const { director } = createXRBlocksEnvironment(
xb.core.scene,
{ depth: xb.core.depth, lighting: xb.core.lighting },
{ presets: STOCK_PRESETS, initial: STOCK_PRESETS.noon },
);
director.setPassthrough(true);
director.setOcclusion(DEFAULT_OCCLUSION); // real-world depth hides your content
director.setLightEstimation(true); // the real room lights it
// From your XR Blocks Script's own update. Nothing here ticks itself, and on
// this host that matters more than on the others: both sensors are polled here.
director.update(deltaMs);
What the adapter does
- Sky, fog, lights and image-based lighting come from the three.js adapter it extends. XR Blocks renders through three.js, so reimplementing four slots would only let them drift.
- Depth occlusion - registers as a client of XR Blocks'
Depthmanager (resumeDepth/pauseDepth), turns its occlusion pass on, and chooses the depth-texture blur from the requested mode and softness. - Light estimation - reads the
Lightingmanager, which already owns the WebXR half, and turns its directional light and ambient probe into the same specs an app writes by hand. The director then lays them over the ambient, key and ibl slots. - The room -
createXRBlocksWorldSensing(xb.core.world)reads XR Blocks'PlaneDetectorandMeshDetector. Anchors and hit testing reportunsupported: XR Blocks hasplaceOnSurfaceandanchorObjectAtReticle, which move an object for you and hand nothing back, so neither can answer where a ray would land.
Two things worth knowing
XR Blocks is configured before you get here. Its depth and lighting managers are set up during xb.init, so this adapter can start and stop them and cannot conjure an occlusion pass that was never built. Anything it arrives too late to change is named in a sensing report - which option to set, which preference the session was actually requested with - rather than silently dropped. Read them with director.getSensing("occlusion") and director.onSensing(...).
Do not light the room twice. If XR Blocks' own estimated lights are on (useAmbientSH, useDirectionalLight), and this package applies the same estimate to the ambient and key slots, you get both. Turn the XR Blocks lights off and let the director own them; the adapter says so in the report if it sees both.
Peer dependency
three >= 0.170.0, plus an XR Blocks build to hand in. xrblocks itself is not a dependency: the depth and lighting managers are described structurally, so nothing here pins a version of it. Verified against xrblocks 0.21.1.
Licence
MIT.
Classes
| Class | Description |
|---|---|
| AudioDirector | - |
| EnvironmentDirector | - |
| ThreeAudioPort | Plays sounds. |
| ThreeEnvironmentPort | Applies an environment to a scene. |
| ThreeWorldSensingPort | What an adapter implements. Everything except observe is optional, because every host has a different subset and a missing method is reported rather than thrown. |
| WorldSensingDirector | - |
| XRBlocksEnvironmentPort | Applies an environment to a scene. |
| XRBlocksWorldSensingPort | What an adapter implements. Everything except observe is optional, because every host has a different subset and a missing method is reported rather than thrown. |
Interfaces
| Interface | Description |
|---|---|
| AmbientLightSpec | Uniform illumination from every direction. |
| AudioCone | A directional sound, in this package's own terms. |
| AudioCue | A sound the app knows how to make. Registered once, played by id. |
| AudioDirectorOptions | - |
| AudioPort | Plays sounds. |
| AudioSpatial | How a positional voice gets quieter with distance. |
| AudioVoice | A sounding voice. Opaque to the app apart from the fields shown. |
| AudioVoiceRequest | A play request with every decision already made: which file, how loud in absolute terms, looping or not, and where from. An adapter implementing AudioPort has no mixing left to do. |
| ColourLike | A THREE.Color, seen through the two things this adapter reads. |
| EnvironmentDirectorOptions | - |
| EnvironmentPort | Applies an environment to a scene. |
| EnvironmentPortHost | What a port is handed so it can talk back. Implemented by the director. |
| EnvironmentSpec | A PARTIAL description of the environment. |
| EquirectLoader | Anything that can turn a URL into a texture: TextureLoader, RGBELoader. |
| EstimatedLighting | Lighting the host measured from the real world. |
| FogExponential | Fog that thickens exponentially with distance. |
| FogLinear | Fog that ramps between two distances. |
| HitTestRequest | A standing question: "where does this ray meet the room". |
| IblEstimated | The reflections the HOST measured from the real room. |
| IblGradient | Image-based lighting: what the world reflects and how it lights everything that is not lit by the key light. |
| IblRoom | The host's built-in neutral room probe. Neither authored nor measured. |
| IblTexture | @realitycollective/webxr-environment - the engine-free core. |
| KeyLightSpec | The one directional light most scenes need: a sun, a moon, a work lamp. |
| LightEstimationSpec | Which slots a live estimate may take over. |
| OcclusionSource | How the app would like the depth sensor configured. |
| OcclusionSpec | - |
| PlayOptions | Per-play overrides. Everything here beats the cue's own value. |
| ResolvedEnvironment | Every slot decided. This is what the director holds and adapters receive. |
| ResolvedLightEstimation | spec with every default filled in, which is what a port receives. |
| ResolvedWorldDetection | - |
| SensingReport | - |
| SkyGradient | A vertical gradient sky. top sits at the zenith and bottom at the nadir; horizon is where they meet, as a fraction of the way up the sphere. |
| SkySolid | A single flat colour behind everything. The cheapest sky there is. |
| SkyTexture | An authored sky: an equirectangular image wrapped around the world. |
| ThreeAudioPortOptions | - |
| ThreeAudioSetup | - |
| ThreeEnvironmentPortOptions | - |
| ThreeEnvironmentSetup | - |
| ThreeWorldSensingPortOptions | - |
| ThreeWorldSensingSetup | - |
| TransitionOptions | - |
| Vec3Like | - |
| WorldAnchor | A point in the real world the runtime promises to keep track of. |
| WorldChange | What moved since the last flush, per feature. Ids only; read the lists. |
| WorldDetectionSpec | Which of them to turn on. Everything defaults OFF: each one costs. |
| WorldHit | Where a ray met the world. |
| WorldMesh | Scanned geometry: furniture, walls, whatever the room-scan produced. |
| WorldPlane | A flat surface the host found: a floor, a wall, a table top. |
| WorldPose | Where something is, in whatever reference space the app is using. |
| WorldSensingDirectorOptions | - |
| WorldSensingPort | What an adapter implements. Everything except observe is optional, because every host has a different subset and a missing method is reported rather than thrown. |
| WorldSensingPortHost | What a port is handed so it can report what the room looks like. |
| XBDepthLike | xb.core.depth. |
| XBDepthOptionsLike | DepthOptions, of which this adapter writes only the blur flags. |
| XBDetectedMeshLike | DetectedMesh. |
| XBDetectedPlaneLike | DetectedPlane: a mesh built from the polygon, with the label beside it. |
| XBLightingLike | xb.core.lighting. |
| XBLightingOptionsLike | LightingOptions. |
| XBMeshDetectorLike | - |
| XBObject3DLike | The three.js object XR Blocks builds for a detected surface or mesh. |
| XBPlaneDetectorLike | - |
| XBWorldLike | xb.core.world. Both detectors are absent unless enabled at init. |
| XrAnchorLike | One XRAnchor. |
| XRBlocksAudioSetup | - |
| XRBlocksEnvironmentContext | What an app hands this adapter. Both members are optional and both degrade. |
| XRBlocksEnvironmentSetup | - |
| XRBlocksWorldSensingSetup | - |
| XrFrameLike | - |
| XrHitTestResultLike | - |
| XrLightEstimateLike | One XRLightEstimate. The three products WebXR's light estimation makes. |
| XrManagerLike | The part of renderer.xr this port uses. |
| XrMeshLike | One XRMesh. The buffers are the runtime's and are never copied here. |
| XrPlaneLike | One XRPlane. polygon points are in the plane's own space, metres. |
| XrPoseLike | What frame.getPose hands back: a transform, or null when tracking is lost. |
| XrRendererLike | A WebGLRenderer, seen through the keyhole this port looks through. |
| XrSessionLike | - |
Type Aliases
| Type Alias | Description |
|---|---|
| AudioBus | A mix group. Any string works; the conventional set is below. |
| CuePolicy | What a second play request does while a cue is already sounding. |
| EasingFunction | t in 0..1 -> eased t in 0..1. |
| EasingName | The named easing curves. A transition may also carry its own function. |
| EnvironmentBlendMode | How the host composites what is rendered over the real world. |
| EnvironmentListener | Fired whenever what the port holds, or what the app asked for, changes. |
| EnvironmentSlot | @realitycollective/webxr-environment - the engine-free core. |
| FogSpec | @realitycollective/webxr-environment - the engine-free core. |
| IblSpec | @realitycollective/webxr-environment - the engine-free core. |
| OcclusionMode | How hard the edge between real and virtual is drawn. |
| OcclusionScope | Which content the real world is allowed to hide. |
| Quat | A rotation as [x, y, z, w]. Normalised; the adapters guarantee that. |
| RampGradient | A gradient with or without a horizon stop, from either slot. |
| Rgb | An sRGB colour, one channel per component, each in 0..1. |
| SensingFeature | - |
| SensingListener | - |
| SensingState | How a feature is doing, in the order things usually go wrong: |
| SkySpec | @realitycollective/webxr-environment - the engine-free core. |
| Vec3 | A direction or position in world space, metres. Need not be normalised. |
| WorldChangeListener | - |
| WorldFeature | - |
| WorldPlaneOrientation | Roughly which way a surface faces. |
| XrLightProbeLike | An XRLightProbe. Opaque: it is only ever handed back to getLightEstimate. |
Variables
| Variable | Description |
|---|---|
| ALL_WORLD_DETECTION | Everything on: what setDetection(true) means. |
| DAWN | - |
| DEFAULT_BUS | The bus a cue lands on when it does not name one. |
| DEFAULT_BUSES | The buses a director starts with, each at unity gain. Any other name works too - a bus springs into existence at unity the first time it is named. master is NOT in here: it is a separate scalar over all buses, so that "duck everything" and "turn the music down" never fight over one number. |
| DEFAULT_LIGHT_ESTIMATION | - |
| DEFAULT_OCCLUSION | Soft edges over everything, from a GPU texture. |
| DUSK | - |
| EMPTY_ENVIRONMENT | An environment with nothing in it: a black void with no light. |
| ENVIRONMENT_SLOTS | The slot names, in the order the director pushes them to the port. |
| NIGHT | - |
| NOON | - |
| OVERCAST | - |
| SENSING_FEATURES | The sensor-backed features an adapter can report on. |
| SH_DC_TO_IRRADIANCE | The L0 band of a spherical-harmonic probe, scaled to irradiance. |
| SKY_TEXTURE_HEIGHT | Default rows. Sixty-four is smooth to the eye and 512 bytes of texture. |
| SKY_TEXTURE_WIDTH | Columns in the generated texture. Two, because a 1px-wide equirect filters badly. |
| STOCK_PRESETS | All of the above, ready to hand to EnvironmentDirector's presets. |
| VOID | Nothing at all: black, unlit, empty. The starting point of a void scene. |
| WORLD_FEATURES | The world features an app can ask for. They are named separately from the environment's because a host can have any subset: Quest has planes, meshes and anchors; a phone AR runtime may have only planes and hit test. |
Functions
| Function | Description |
|---|---|
| ambientFromSphericalHarmonics | The ambient term of an estimate, or null when the runtime sent no probe. |
| clamp | Clamp to an arbitrary range. |
| clamp01 | Clamp to the unit interval. |
| clearedFog | The same fog, pushed far enough away to be invisible. |
| createSkyTexture | Build the equirectangular background texture for a gradient sky. |
| createThreeAudio | Wire an audio director to a three.js AudioListener (the one on your camera). Remember port.resume() from a user gesture. |
| createThreeEnvironment | Wire an environment director to a three.js scene. |
| createThreeWorldSensing | Wire a world-sensing director to a three.js renderer. |
| createXRBlocksAudio | Wire an audio director to an XR Blocks scene. |
| createXRBlocksEnvironment | Wire an environment director to an XR Blocks scene. |
| createXRBlocksWorldSensing | Wire a world-sensing director to XR Blocks' world module. |
| deepEquals | Structural equality for the plain-data specs. |
| estimatedFromLighting | One reading of the XR Blocks lighting manager, as environment specs. |
| gradientColourAt | The colour at a height up the sphere. |
| gradientPixels | RGBA bytes for the gradient, nadir row first. Pure - no three.js, no DOM. |
| interpolateEnvironment | Blend two resolved environments. t is the EASED progress in 0..1; the director has already applied the curve, so this stays linear per channel. |
| keyFromEstimate | The primary light of an estimate, or null when there is not one. |
| lerp | Linear interpolation. t is NOT clamped - the callers already clamp it. |
| lerpRgb | Component-wise colour interpolation. |
| resolveEasing | Resolve an easing name or function to a function. Unknown names are linear. |
| resolveLightEstimation | - |
| resolveWorldDetection | - |
| rgbEquals | True when two colours are identical channel for channel. |
| rgbFromHex | 0xff8800 -> [1, 0.533…, 0]. Convenience for authoring presets. |
| rgbToHex | [1, 0.533…, 0] -> 0xff8800. The inverse, for adapters that want a hex. |
| skyMix | The blend weight for bottom -> top at a given height up the sphere. |
| toEstimatedLighting | One estimate, as the slots it is allowed to take over. |
| unsupported | The report a feature has before any adapter has said otherwise. |
| worldEntryChanged | Has this entry changed since the last one with the same id? |