Signatur
Beschreibung
XRRenderState beschreibt, wie der XR-Kompositor die Bilder einer XRSession zusammensetzt. Ein Objekt dieses Typs bekommt man nur lesend über XRSession.renderState. Es gibt keinen öffentlichen Konstruktor. Die Werte sind schreibgeschützt. Ändern kann man sie ausschließlich mit XRSession.updateRenderState(). Dieser Methode übergibt man ein Wörterbuch vom Typ XRRenderStateInit.
Die wichtigsten Eigenschaften:
baseLayer(XRWebGLLayer | null): die WebGL-Ebene, in die gerendert wird.layers(XRLayer[]): geordnete Liste von Ebenen, wenn das WebXR Layers Module unterstützt wird. Schließt sich mitbaseLayergegenseitig aus.depthNear/depthFar(number): Abstand der nahen und fernen Clipping-Ebene in Metern. Standardwerte sind0.1und1000.inlineVerticalFieldOfView(number | null): vertikales Sichtfeld in Radiant. Gilt nur fürinline-Sitzungen (Standard:π/2), bei immersiven Sitzungen ist der Wertnull.passthroughFullyObscured(boolean | undefined, experimentell): gibt an, ob die Durchsicht auf die reale Umgebung (Passthrough) vollständig verdeckt ist.
Änderungen über updateRenderState() werden nicht sofort wirksam. Sie gelten erst ab dem nächsten Animationsframe. Das Objekt, das session.renderState liefert, ist pro Frame eine Momentaufnahme. Man sollte es deshalb in jedem Frame neu abfragen und nicht zwischenspeichern.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $baseLayer | XRWebGLLayer | null | null | Eigenschaft von XRRenderStateInit für updateRenderState(): die WebGL-Ebene, deren Framebuffer der Kompositor anzeigt. |
| $layers | XRLayer[] | null | null | Liste der Kompositions-Ebenen (WebXR Layers). Darf nicht zusammen mit baseLayer gesetzt werden. |
| $depthNear | number | 0.1 | Nahe Clipping-Ebene in Metern. Sie muss kleiner als depthFar sein. |
| $depthFar | number | 1000 | Ferne Clipping-Ebene in Metern. |
| $inlineVerticalFieldOfView | number | Math.PI / 2 | Vertikales Sichtfeld in Radiant, nur für inline-Sitzungen. Bei immersiven Sitzungen wirft das Setzen einen InvalidStateError. |
Rückgabewert
XRSession.renderState gelesen. Liefert die aktuell aktiven, schreibgeschützten Render-Einstellungen der Sitzung.Beispiele
Immersive Sitzung starten und baseLayer setzen
const startXR = async () => {
if (!(await navigator.xr?.isSessionSupported('immersive-vr'))) {
console.log('immersive-vr wird nicht unterstützt');
return;
}
const session = await navigator.xr.requestSession('immersive-vr');
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });
// Render-Zustand konfigurieren (wirkt ab dem nächsten Frame)
session.updateRenderState({
baseLayer: new XRWebGLLayer(session, gl),
depthNear: 0.05,
depthFar: 500
});
const refSpace = await session.requestReferenceSpace('local');
session.requestAnimationFrame((time, frame) => {
const { renderState } = session;
console.log(renderState.depthNear, renderState.depthFar);
});
};
document.querySelector('#enter-vr').addEventListener('click', startXR);
Render-Zustand in jedem Frame auslesen
const onXRFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
// renderState in jedem Frame neu abfragen, nicht zwischenspeichern
const layer = session.renderState.baseLayer;
if (!layer) return;
gl.bindFramebuffer(gl.FRAMEBUFFER, layer.framebuffer);
const pose = frame.getViewerPose(refSpace);
pose?.views.forEach((view) => {
const vp = layer.getViewport(view);
gl.viewport(vp.x, vp.y, vp.width, vp.height);
// ... Szene mit view.projectionMatrix zeichnen
});
};
Sichtfeld einer inline-Sitzung anpassen
const inlineSession = await navigator.xr.requestSession('inline');
const gl = document.querySelector('canvas').getContext('webgl', { xrCompatible: true });
inlineSession.updateRenderState({
baseLayer: new XRWebGLLayer(inlineSession, gl),
inlineVerticalFieldOfView: Math.PI / 3 // 60°
});
inlineSession.requestAnimationFrame(() => {
const fov = inlineSession.renderState.inlineVerticalFieldOfView;
console.log(`FOV: ${(fov * 180 / Math.PI).toFixed(0)}°`);
});
// Wichtig · Fallstricke
- Verzögerte Wirkung:
updateRenderState()ändertsession.renderStateerst ab dem nächsten Frame. Liest man direkt nach dem Aufruf, erhält man noch die alten Werte. - Nicht zwischenspeichern: Pro Frame kann ein neues
XRRenderState-Objekt entstehen. Deshalbsession.renderStateimmer im Frame-Callback abfragen. - Bildschirmausgabe: Ohne gesetzten
baseLayerbzw.layerszeigt die Sitzung nichts an, und die Callbacks vonrequestAnimationFramewerden nicht ausgeführt. baseLayerundlayersgleichzeitig zu setzen, führt zu einemNotSupportedError.inlineVerticalFieldOfViewbei einer immersiven Sitzung zu setzen, führt zu einemInvalidStateError.- Der WebGL-Kontext muss mit
xrCompatible: trueerzeugt oder nachträglich mitgl.makeXRCompatible()kompatibel gemacht werden. - Kompatibilität: WebXR steht nur in sicheren Kontexten (HTTPS) zur Verfügung und muss gegebenenfalls über die Permissions Policy
xr-spatial-trackingfreigegeben werden. Firefox und Safari (Desktop) unterstützen die API nicht.layersundpassthroughFullyObscuredsind experimentell. Vor der Nutzung immernavigator.xrundisSessionSupported()prüfen.