Signatur
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
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);
Feature-Erkennung
const supportsDynamicScaling = (view) =>
'recommendedViewportScale' in view &&
typeof view.requestViewportScale === 'function';
// z. B. im ersten Frame:
// console.log(supportsDynamicScaling(pose.views[0]));
// 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
nullsein;requestViewportScale(null)wird zwar ignoriert, eigene Berechnungen mitnullergeben aber0bzw.NaN. - Die Skalierung wirkt erst beim nächsten Aufruf von
XRWebGLLayer.getViewport(). Wer den Viewport vorrequestViewportScale()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
XRWebGLLayerrelevant; 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.