Start · Sprachen · JavaScript · Referenz · XRViewport.height

XRViewport.height

Eigenschaft

Schreibgeschützte Eigenschaft, die die Höhe des Viewports in Pixeln angibt, in dem eine WebXR-Ansicht auf der Zeichenfläche gerendert werden soll.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

XRViewport.height

Beschreibung

XRViewport.height gibt die Höhe des rechteckigen Bereichs der Zeichenfläche (des Framebuffers einer XRWebGLLayer) in Pixeln an, in den eine einzelne XRView gerendert wird. Zusammen mit x, y und width beschreibt sie genau den Ausschnitt, den du an gl.viewport() übergibst.

Bei stereoskopischen Geräten wie VR-Headsets teilen sich meist zwei Ansichten (linkes und rechtes Auge) einen Framebuffer. Jede Ansicht bekommt ihren eigenen Viewport. Typischerweise liegen die Viewports nebeneinander und sind gleich hoch, aber verlassen solltest du dich darauf nicht: Frag die Werte in jedem Frame über XRWebGLLayer.getViewport(view) neu ab.

Der Wert ist eine Ganzzahl (long) und kann sich zur Laufzeit ändern, etwa wenn der Browser die Auflösung dynamisch anpasst (requestViewportScale()) oder wenn du die Ebene mit einem anderen framebufferScaleFactor neu anlegst.

Beispiele

Viewport pro Auge im Render-Loop setzen

const onXRFrame = (time, frame) => {
  const session = frame.session;
  session.requestAnimationFrame(onXRFrame);

  const pose = frame.getViewerPose(refSpace);
  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);
    // x, y, width und height direkt an WebGL übergeben
    gl.viewport(vp.x, vp.y, vp.width, vp.height);
    drawScene(view.projectionMatrix, view.transform.inverse.matrix);
  }
};

Seitenverhältnis einer Ansicht berechnen

const logViewportInfo = (glLayer, view) => {
  const { width, height } = glLayer.getViewport(view);
  const aspect = width / height;
  console.log(`${view.eye}: ${width}×${height} px, Seitenverhältnis ${aspect.toFixed(3)}`);
  return aspect;
};

// Aufruf innerhalb eines XRFrame-Callbacks:
// pose.views.forEach((view) => logViewportInfo(glLayer, view));
left: 1440×1584 px, Seitenverhältnis 0.909 right: 1440×1584 px, Seitenverhältnis 0.909

Scissor-Test auf den Viewport begrenzen

const clearViewOnly = (gl, glLayer, view, color) => {
  const vp = glLayer.getViewport(view);
  gl.enable(gl.SCISSOR_TEST);
  gl.scissor(vp.x, vp.y, vp.width, vp.height);
  gl.viewport(vp.x, vp.y, vp.width, vp.height);
  gl.clearColor(...color);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.disable(gl.SCISSOR_TEST);
};

// Nur das linke Auge rot einfärben (Debugging):
// clearViewOnly(gl, glLayer, pose.views[0], [1, 0, 0, 1]);

// Wichtig · Fallstricke

  • Schreibgeschützt: Wenn du viewport.height zuweist, passiert nichts. Die Auflösung änderst du über framebufferScaleFactor beim Anlegen der XRWebGLLayer oder über XRView.requestViewportScale().
  • Nicht mit der Canvas-Höhe verwechseln: height bezieht sich auf den XR-Framebuffer (glLayer.framebufferHeight), nicht auf canvas.height oder die CSS-Größe.
  • Pro Frame neu abfragen: Viewports können sich zwischen Frames ändern. Wenn du Werte zwischenspeicherst, führt das bei dynamischer Auflösung zu verzerrten Bildern.
  • Der Ursprung (x/y) liegt wie bei WebGL üblich unten links. Die Höhe wird von dort aus nach oben gemessen.
  • Kompatibilität: WebXR steht nur in sicheren Kontexten (HTTPS) zur Verfügung. Unterstützt wird es in Chromium-basierten Browsern und XR-Browsern wie dem Meta Quest Browser. Firefox und Safari auf dem Desktop unterstützen es nicht. Prüfe die Unterstützung vorher mit navigator.xr?.isSessionSupported().