Start · Sprachen · JavaScript · Referenz · XRLightProbe: reflectionchange

XRLightProbe: reflectionchange

Ereignis

Wird an einem <code>XRLightProbe</code> ausgelöst, sobald die WebXR-Laufzeit eine neue geschätzte Reflexions-Würfelkarte der realen Umgebung bereitstellt.

seit JavaScript Experimentell: Chrome/Edge 90+ (Android, ARCore); Kategorie: webapi

Signatur

xrLightProbe.addEventListener("reflectionchange", handler)

Beschreibung

Das Event reflectionchange gehört zur WebXR Lighting Estimation API. Es wird an einem XRLightProbe-Objekt ausgelöst, sobald die XR-Laufzeit (z. B. ARCore) eine neue Reflexions-Würfelkarte (Cube Map) der realen Umgebung berechnet hat. Mit dieser Karte lassen sich spiegelnde oder metallische virtuelle Objekte in AR-Szenen so darstellen, dass sie die echte Umgebung plausibel spiegeln.

Das Event ist ein einfaches Event ohne zusätzliche Eigenschaften. Die neue Würfelkarte ruft man im Handler mit XRWebGLBinding.getReflectionCubeMap(lightProbe) ab. Diese Methode liefert eine WebGLTexture, die man anschließend in den eigenen Shader (z. B. als Umgebungs-Map in einem PBR-Material) einbindet.

Da die Würfelkarte nur gelegentlich aktualisiert wird, sollte man getReflectionCubeMap() nicht in jedem Frame aufrufen, sondern nur, wenn dieses Event eintrifft. Das spart GPU-Speicher und Rechenzeit. Den Handler kann man entweder mit addEventListener("reflectionchange", …) registrieren oder über die Eigenschaft onreflectionchange zuweisen.

Voraussetzung ist eine immersive AR-Sitzung ("immersive-ar") mit dem Feature "light-estimation" sowie ein Lichtsensor-Objekt, das man über XRSession.requestLightProbe() erhält.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Event-Typ, hier immer "reflectionchange".
$handler Pflicht (event: Event) => void Callback, der bei jeder neuen Reflexions-Würfelkarte aufgerufen wird. event.target ist das auslösende XRLightProbe.
$options boolean|AddEventListenerOptions false Optionale Listener-Optionen wie once, passive oder signal (zum Entfernen per AbortController).

Rückgabewert

Typ
void
Beschreibung
addEventListener() gibt nichts zurück. Das an den Handler übergebene Objekt ist ein einfaches Event ohne Zusatzdaten.

Beispiele

Reflexionskarte bei Änderung neu laden (addEventListener)

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });

const startAR = async () => {
  const session = await navigator.xr.requestSession('immersive-ar', {
    requiredFeatures: ['light-estimation']
  });
  session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });

  const lightProbe = await session.requestLightProbe({
    reflectionFormat: session.preferredReflectionFormat
  });
  const glBinding = new XRWebGLBinding(session, gl);

  let reflectionTexture = null;

  lightProbe.addEventListener('reflectionchange', () => {
    // Neue Würfelkarte nur bei Bedarf abholen
    reflectionTexture = glBinding.getReflectionCubeMap(lightProbe);
    console.log('Neue Reflexions-Würfelkarte erhalten');
  });

  // reflectionTexture später im Render-Loop als Environment-Map binden
};

document.querySelector('#ar-button').addEventListener('click', startAR);
Neue Reflexions-Würfelkarte erhalten

Handler über die onreflectionchange-Eigenschaft

const setupReflections = (lightProbe, glBinding, material) => {
  lightProbe.onreflectionchange = (event) => {
    const cubeMap = glBinding.getReflectionCubeMap(event.target);
    if (cubeMap) {
      material.envMap = cubeMap; // eigenes Material-Objekt
      material.needsUpdate = true;
    }
  };
};

// Handler wieder deaktivieren:
// lightProbe.onreflectionchange = null;

Listener beim Sitzungsende entfernen (removeEventListener)

const watchReflections = (session, lightProbe, glBinding) => {
  const onReflectionChange = () => {
    const tex = glBinding.getReflectionCubeMap(lightProbe);
    console.log('Cube Map aktualisiert:', tex !== null);
  };

  lightProbe.addEventListener('reflectionchange', onReflectionChange);

  session.addEventListener('end', () => {
    lightProbe.removeEventListener('reflectionchange', onReflectionChange);
    console.log('reflectionchange-Listener entfernt');
  }, { once: true });
};
Cube Map aktualisiert: true reflectionchange-Listener entfernt

// Wichtig · Fallstricke

  • Experimentell: Das Event wird derzeit nur von Chromium-Browsern auf Android mit ARCore unterstützt (ab Chrome 90). Firefox und Safari unterstützen die WebXR Lighting Estimation API nicht. Vorher mit navigator.xr?.isSessionSupported('immersive-ar') prüfen und das Feature besser als optionalFeatures anfordern, wenn die App auch ohne Lichtschätzung laufen soll.
  • Sicherer Kontext: WebXR funktioniert nur über HTTPS (oder localhost). Außerdem muss die Sitzung durch eine Benutzeraktion wie einen Klick gestartet werden.
  • Kein Aufruf pro Frame: getReflectionCubeMap() kann bei jedem Aufruf eine neue Textur anlegen. Nur im reflectionchange-Handler aufrufen und alte Texturen gegebenenfalls mit gl.deleteTexture() freigeben.
  • Format: Der Aufruf requestLightProbe() mit reflectionFormat: 'rgba16f' schlägt fehl, wenn dieses Format nicht session.preferredReflectionFormat entspricht. Die Standardeinstellung 'srgba8' ist immer gültig. Für HDR-Texturen braucht man WebGL 2 bzw. die passenden Half-Float-Erweiterungen.
  • Datenschutz: Die Würfelkarte kann Bildinformationen über die reale Umgebung des Nutzers enthalten. Die Laufzeit liefert sie deshalb oft nur mit niedriger Auflösung oder verzögert. Man sollte sich nicht darauf verlassen, dass das Event sofort nach dem Start auslöst.
  • Das Event-Objekt hat keine eigenen Daten. Die Textur muss aktiv über XRWebGLBinding abgerufen werden.