Signatur
Beschreibung
Die Eigenschaft y eines XRViewport-Objekts gibt an, wie weit der Viewport einer XR-Ansicht (XRView) von der unteren Kante der Zeichenoberfläche entfernt ist. Der Wert wird in Pixeln angegeben. Zusammen mit x, width und height beschreibt er das Rechteck, in das die Szene für ein bestimmtes Auge oder eine bestimmte Ansicht gezeichnet wird.
Die Koordinaten folgen der Konvention von WebGL: Der Ursprung liegt unten links, und die y-Achse zeigt nach oben. Deshalb lassen sich die vier Werte direkt an gl.viewport() und gl.scissor() übergeben, ohne sie umzurechnen.
Einen XRViewport erhältst du pro Frame über XRWebGLLayer.getViewport(view) für jede Ansicht in XRViewerPose.views. Bei stereoskopischen Headsets liegen die Viewports für linkes und rechtes Auge oft nebeneinander im selben Framebuffer. Dann ist y für beide meist 0, und nur x ist verschieden. Bei anderen Anordnungen (zum Beispiel übereinander) kann y aber auch andere Werte haben. Verlass dich deshalb nie auf feste Werte.
Rückgabewert
Beispiele
Viewport pro Ansicht im Render-Loop setzen
// Voraussetzung: gl ist ein XR-kompatibler WebGL-Kontext, xrRefSpace ist ein XRReferenceSpace
const onXRFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
const pose = frame.getViewerPose(xrRefSpace);
if (!pose) return;
const glLayer = session.renderState.baseLayer;
gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
for (const view of pose.views) {
const vp = glLayer.getViewport(view);
// y wird direkt übernommen – Ursprung unten links wie in WebGL
gl.viewport(vp.x, vp.y, vp.width, vp.height);
drawScene(view.projectionMatrix, view.transform.inverse.matrix);
}
};
Viewport-Daten zur Fehlersuche ausgeben
const logViewports = (frame, refSpace) => {
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
const layer = frame.session.renderState.baseLayer;
pose.views.forEach((view) => {
const { x, y, width, height } = layer.getViewport(view);
console.log(`${view.eye}: x=${x}, y=${y}, ${width}x${height}`);
});
};
Scissor-Test auf den Viewport begrenzen
// Nur den Bereich des aktuellen Auges löschen, z. B. mit Hintergrundfarbe pro Auge
const clearView = (gl, vp, color) => {
gl.enable(gl.SCISSOR_TEST);
gl.scissor(vp.x, vp.y, vp.width, vp.height);
gl.clearColor(...color);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.disable(gl.SCISSOR_TEST);
};
// Aufruf im Frame-Loop:
// clearView(gl, glLayer.getViewport(view), [0.1, 0.1, 0.2, 1]);
// Wichtig · Fallstricke
- Ursprung unten links:
ywird von der unteren Kante aus gemessen und nicht von oben wie bei DOM- oder Canvas-2D-Koordinaten. Willst du die Werte mit CSS-Koordinaten oderreadPixels-Auswertungen im Bildschirmformat vergleichen, musst du umrechnen:top = framebufferHeight - (y + height). - Nicht zwischenspeichern: Die Viewports können sich zwischen Frames ändern, zum Beispiel nach einer Änderung von
framebufferScaleFactoroder bei dynamischer Auflösung. FraggetViewport()deshalb in jedem Frame neu ab. - Keine festen Annahmen: Dass
ygleich0ist, ist üblich, aber nicht garantiert. Nutze immer den gelieferten Wert. - Kompatibilität: WebXR läuft nur in sicheren Kontexten (HTTPS). Unterstützt wird es vor allem von Chromium-Browsern und dem Meta Quest Browser. Firefox und Safari auf dem Desktop unterstützen es nicht. Prüf die Verfügbarkeit mit
navigator.xr?.isSessionSupported().