Signatur
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
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);
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 });
};
// 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 alsoptionalFeaturesanfordern, 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 imreflectionchange-Handler aufrufen und alte Texturen gegebenenfalls mitgl.deleteTexture()freigeben. - Format: Der Aufruf
requestLightProbe()mitreflectionFormat: 'rgba16f'schlägt fehl, wenn dieses Format nichtsession.preferredReflectionFormatentspricht. 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
XRWebGLBindingabgerufen werden.