Start · Sprachen · JavaScript · Referenz · XRWebGLLayer.framebufferWidth

XRWebGLLayer.framebufferWidth

Eigenschaft

Schreibgeschützte Eigenschaft von <code>XRWebGLLayer</code>, die die Breite des WebXR-Framebuffers in Pixeln als Ganzzahl liefert.

seit JavaScript WebXR Device API – Chrome/Edge 79+, Samsung Intern Kategorie: webapi

Signatur

XRWebGLLayer.framebufferWidth

Beschreibung

framebufferWidth gibt die Breite (in Pixeln) des Framebuffers an, den eine XRWebGLLayer für das Rendern einer immersiven oder Inline-Sitzung bereitstellt. Der Framebuffer selbst ist über XRWebGLLayer.framebuffer zugänglich. Bei stereoskopischen Geräten enthält er meist alle Ansichten nebeneinander, also z. B. linkes und rechtes Auge. Die Breite umfasst dann beide Augenbereiche zusammen.

Der Wert hängt von der nativen Auflösung des Geräts und vom Parameter framebufferScaleFactor ab, der beim Erzeugen der Ebene angegeben wird. Nach dem Erzeugen der Ebene bleibt der Wert gleich. Soll sich die Auflösung ändern, musst du eine neue Ebene anlegen und per session.updateRenderState() setzen.

In der Praxis brauchst du framebufferWidth (zusammen mit framebufferHeight) vor allem, um passende Offscreen-Ressourcen anzulegen, etwa Render-Targets für Post-Processing, Tiefen-Texturen oder Multisample-Renderbuffer. Außerdem hilft der Wert beim Debuggen und Protokollieren der tatsächlichen Render-Auflösung. Für das Setzen des Viewports pro Auge verwendest du dagegen XRWebGLLayer.getViewport(view). Die Viewport-Werte beziehen sich auf genau diesen Framebuffer.

Rückgabewert

Typ
number
Beschreibung
Eine positive Ganzzahl: die Breite des Framebuffers der Ebene in Pixeln. Bei einer XRWebGLLayer einer Inline-Sitzung entspricht sie in der Regel der Breite des zugehörigen Canvas (drawingBufferWidth).

Beispiele

Framebuffer-Größe nach dem Start einer immersiven Sitzung ausgeben

const startXR = async () => {
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl2', { xrCompatible: true });

  const session = await navigator.xr.requestSession('immersive-vr');
  const layer = new XRWebGLLayer(session, gl);
  await session.updateRenderState({ baseLayer: layer });

  console.log(`Framebuffer: ${layer.framebufferWidth} x ${layer.framebufferHeight} px`);
};

document.querySelector('#vr-button').addEventListener('click', startXR);
Framebuffer: 3664 x 1920 px (gerätabhängig, z. B. Meta Quest 2)

Auswirkung von framebufferScaleFactor vergleichen

const compareScales = async (session, gl) => {
  const nativeScale = XRWebGLLayer.getNativeFramebufferScaleFactor(session);
  const standard = new XRWebGLLayer(session, gl);
  const reduced = new XRWebGLLayer(session, gl, { framebufferScaleFactor: 0.5 });

  console.log('Native Skalierung:', nativeScale);
  console.log('Standard-Breite:', standard.framebufferWidth);
  console.log('Halbe Skalierung:', reduced.framebufferWidth);

  // Die leistungsschonende Ebene verwenden
  await session.updateRenderState({ baseLayer: reduced });
};
Native Skalierung: 1.25 Standard-Breite: 3664 Halbe Skalierung: 1832

Passendes Offscreen-Render-Target für Post-Processing anlegen

const createPostProcessTarget = (gl, layer) => {
  const width = layer.framebufferWidth;
  const height = layer.framebufferHeight;

  const texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0,
    gl.RGBA, gl.UNSIGNED_BYTE, null);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

  const depth = gl.createRenderbuffer();
  gl.bindRenderbuffer(gl.RENDERBUFFER, depth);
  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT24, width, height);

  const fbo = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
  gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depth);

  console.log(`Render-Target ${width}x${height} erstellt`);
  return { fbo, texture };
};
Render-Target 3664x1920 erstellt

// Wichtig · Fallstricke

  • Schreibgeschützt: Eine Zuweisung wie layer.framebufferWidth = 1024 wird ignoriert, im Strict Mode wirft sie einen TypeError. Die Auflösung änderst du nur über eine neue Ebene mit einem anderen framebufferScaleFactor.
  • Nicht die Breite eines Auges: Bei Stereo-Sitzungen umfasst der Wert meist alle Ansichten. Für den Viewport pro Auge verwendest du immer layer.getViewport(view). Die Breite halbieren und dabei eine bestimmte Anordnung annehmen ist fehleranfällig.
  • Keine feste Größe: Der Wert unterscheidet sich je nach Gerät, Browser und Skalierungsfaktor. Der Browser kann den gewünschten Faktor außerdem auf einen erlaubten Bereich begrenzen.
  • Leistung: Große Framebuffer kosten viel Füllrate. Auf mobilen Headsets kann ein framebufferScaleFactor unter 1 die Bildrate spürbar verbessern.
  • Kompatibilität: WebXR funktioniert nur in sicheren Kontexten (HTTPS). Unterstützt wird es in Chromium-Browsern und im Meta Quest Browser, nicht aber in Firefox und Safari auf dem Desktop. Prüfe die Unterstützung vorher mit 'xr' in navigator. Den WebGL-Kontext erzeugst du mit xrCompatible: true oder bereitest ihn per gl.makeXRCompatible() vor.