Signatur
Beschreibung
XRViewerPose.views liefert pro Animations-Frame die Liste der Ansichten, die eine WebXR-Anwendung zeichnen muss. Bei einem VR-Headset mit Stereodarstellung sind das normalerweise zwei Ansichten, eine für das linke und eine für das rechte Auge. Bei einer Inline-Sitzung oder bei Handheld-AR, also einem Smartphone, gibt es meist nur eine Ansicht. Manche Geräte liefern auch mehr als zwei, zum Beispiel für Displays mit mehreren Bildschirmen oder für die Aufnahme durch eine zusätzliche Kamera.
Jedes XRView enthält die Angaben, die man zum Rendern braucht: eye ("left", "right" oder "none"), projectionMatrix und transform. Aus transform.inverse.matrix ergibt sich die View-Matrix. Mit XRWebGLLayer.getViewport(view) erhält man den Bildausschnitt im Framebuffer, in den diese Ansicht gezeichnet wird.
Man nutzt die Eigenschaft im Callback von XRSession.requestAnimationFrame(). Dort ruft man zuerst mit frame.getViewerPose(referenceSpace) die Betrachter-Pose ab und durchläuft dann die Ansichten in einer Schleife. Man sollte sich nicht auf eine feste Anzahl oder Reihenfolge der Ansichten verlassen, sondern immer über das ganze Array iterieren.
Rückgabewert
FrozenArray<XRView>) mit einem XRView für jede Ansicht, die in diesem Frame gerendert werden muss. Es enthält immer mindestens ein Element.Beispiele
Alle Ansichten pro Frame rendern (WebGL)
const session = await navigator.xr.requestSession('immersive-vr');
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const layer = new XRWebGLLayer(session, gl);
session.updateRenderState({ baseLayer: layer });
const refSpace = await session.requestReferenceSpace('local');
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return; // Tracking verloren
gl.bindFramebuffer(gl.FRAMEBUFFER, layer.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
for (const view of pose.views) {
const vp = layer.getViewport(view);
gl.viewport(vp.x, vp.y, vp.width, vp.height);
// drawScene ist die eigene Zeichenfunktion der Anwendung
drawScene(view.projectionMatrix, view.transform.inverse.matrix);
}
};
session.requestAnimationFrame(onFrame);
Anzahl und Augen der Ansichten protokollieren
const logViews = (time, frame) => {
const pose = frame.getViewerPose(refSpace);
if (pose) {
console.log(`Ansichten: ${pose.views.length}`);
pose.views.forEach((view, i) => console.log(i, view.eye));
}
};
session.requestAnimationFrame(logViews);
Kameraposition einer Ansicht auslesen
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
const [first] = pose.views;
const { x, y, z } = first.transform.position;
console.log(`Auge ${first.eye}: ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
};
session.requestAnimationFrame(onFrame);
// Wichtig · Fallstricke
- Keine feste Anzahl annehmen: Die Zahl der Ansichten hängt vom Gerät und vom Sitzungstyp ab (
inline,immersive-vr,immersive-ar) und kann sich sogar während einer Sitzung ändern. Iterieren Sie immer über das ganze Array, statt direkt aufviews[0]undviews[1]zuzugreifen. - Nur im aktuellen Frame gültig:
XRViewerPoseund die zugehörigenXRView-Objekte gelten nur innerhalb des aktuellenrequestAnimationFrame-Callbacks. Speichern Sie sie nicht für spätere Frames. getViewerPose()kannnullliefern, zum Beispiel wenn das Tracking verloren geht. Prüfen Sie das, bevor Sie aufviewszugreifen.- Das Array ist eingefroren. Versuche, es zu verändern, schlagen fehl.
- Kompatibilität: WebXR ist nur in sicheren Kontexten (HTTPS) verfügbar. Unterstützt wird es vor allem in Chromium-Browsern und im Meta Quest Browser. Firefox und Safari unterstützen WebXR bisher nicht oder nur eingeschränkt, etwa Safari auf der Apple Vision Pro. Prüfen Sie vorher mit
navigator.xr?.isSessionSupported(), ob WebXR verfügbar ist.