Start · Sprachen · JavaScript · Referenz · XRView.recommendedViewportScale

XRView.recommendedViewportScale

Eigenschaft

Schreibgeschützter, vom User-Agent empfohlener Skalierungsfaktor (0–1] für den Viewport einer <code>XRView</code>, gedacht zur Übergabe an <code>requestViewportScale()</code>.

seit JavaScript WebXR Layers / Dynamic Viewport Scaling – experime Kategorie: webapi

Signatur

XRView.recommendedViewportScale

Beschreibung

Die schreibgeschützte Eigenschaft recommendedViewportScale der Schnittstelle XRView liefert einen Skalierungswert, den der User-Agent aufgrund interner Heuristiken (z. B. GPU-Auslastung, Frame-Timing, thermischer Zustand) für den aktuellen Frame empfiehlt. Der Wert liegt im Bereich (0, 1]; 1 bedeutet volle Auflösung. Wenn der Browser keine Empfehlung geben kann, ist der Wert null.

Die Eigenschaft gehört zur Funktion Dynamic Viewport Scaling: Statt den gesamten Framebuffer neu anzulegen (was teuer ist), rendert die Anwendung vorübergehend nur in einen kleineren Ausschnitt des vorhandenen XRWebGLLayer-Framebuffers. Der Compositor skaliert das Ergebnis anschließend hoch. So lässt sich die Bildrate bei hoher Last stabil halten und Übelkeit durch Ruckler vermeiden.

Typischer Ablauf: In jedem Frame liest man für jede XRView view.recommendedViewportScale, übergibt ihn an view.requestViewportScale() und fragt danach mit glLayer.getViewport(view) den tatsächlichen Viewport ab. Die angeforderte Skalierung wird erst beim nächsten getViewport()-Aufruf wirksam.

Rückgabewert

Typ
number | null
Beschreibung
Eine Gleitkommazahl größer 0 und höchstens 1 als empfohlener Skalierungsfaktor, oder null, wenn der User-Agent keine Empfehlung bereitstellt.

Beispiele

Empfohlene Skalierung im Render-Loop anwenden

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) {
    // Empfehlung des Browsers übernehmen (null wird ignoriert)
    if (view.requestViewportScale && view.recommendedViewportScale) {
      view.requestViewportScale(view.recommendedViewportScale);
    }
    // Viewport erst NACH der Anforderung abfragen
    const vp = glLayer.getViewport(view);
    gl.viewport(vp.x, vp.y, vp.width, vp.height);
    drawScene(view.projectionMatrix, view.transform.inverse.matrix);
  }
};

Empfehlung protokollieren und untere Grenze festlegen

const MIN_SCALE = 0.5; // nicht unter 50 % Auflösung fallen

const applyScale = (view) => {
  const recommended = view.recommendedViewportScale;
  if (recommended == null) {
    console.log(`Auge ${view.eye}: keine Empfehlung`);
    return;
  }
  const scale = Math.max(MIN_SCALE, recommended);
  view.requestViewportScale(scale);
  console.log(`Auge ${view.eye}: empfohlen ${recommended.toFixed(2)}, genutzt ${scale.toFixed(2)}`);
};

// im Frame-Callback: pose.views.forEach(applyScale);
Auge left: empfohlen 0.72, genutzt 0.72 Auge right: empfohlen 0.72, genutzt 0.72

Feature-Erkennung

const supportsDynamicScaling = (view) =>
  'recommendedViewportScale' in view &&
  typeof view.requestViewportScale === 'function';

// z. B. im ersten Frame:
// console.log(supportsDynamicScaling(pose.views[0]));
true // bzw. false in nicht unterstützenden Browsern

// Wichtig · Fallstricke

  • Experimentell: Die Eigenschaft ist Teil eines WebXR-Moduls, das nur in Chromium-basierten Browsern (u. a. Chrome für Android, Meta Quest Browser) verfügbar ist. Firefox und Safari unterstützen sie nicht – immer per Feature-Erkennung prüfen.
  • Der Wert kann null sein; requestViewportScale(null) wird zwar ignoriert, eigene Berechnungen mit null ergeben aber 0 bzw. NaN.
  • Die Skalierung wirkt erst beim nächsten Aufruf von XRWebGLLayer.getViewport(). Wer den Viewport vor requestViewportScale() abfragt, rendert mit der alten Größe.
  • Der Wert kann sich von Frame zu Frame ändern – nicht zwischenspeichern, sondern pro Frame neu lesen.
  • Nur für XRWebGLLayer relevant; bei Projektionsschichten der WebXR-Layers-API gibt es eigene Mechanismen.
  • Sehr niedrige Werte verringern die Bildschärfe deutlich (Text wird unlesbar); ggf. eine Untergrenze setzen.