Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.makeXRCompatible()

WebGLRenderingContext.makeXRCompatible()

Methode

Macht einen bestehenden WebGL-Kontext kompatibel zum aktuellen XR-Gerät und gibt ein <code>Promise</code> zurück, das erfüllt wird, sobald der Kontext für WebXR-Rendering bereit ist.

seit JavaScript WebXR Device API; Chromium-Browser (Chrome/Edge 79 Kategorie: webapi

Signatur

WebGLRenderingContext.prototype.makeXRCompatible()

Beschreibung

makeXRCompatible() sorgt dafür, dass ein WebGL-Kontext auf derselben Grafikhardware (GPU) läuft wie das angeschlossene immersive XR-Gerät, z. B. ein VR-Headset. Erst ein XR-kompatibler Kontext darf an einen XRWebGLLayer übergeben werden, der die Szene in eine XRSession rendert.

Gebraucht wird die Methode, wenn der Kontext ohne das Kontextattribut xrCompatible: true erzeugt wurde. Das ist typisch, wenn eine Seite erst normal im Browser rendert und XR nur bei Bedarf startet, etwa wenn jemand auf „VR starten“ klickt. So muss der Kontext nicht schon beim Laden der Seite an die XR-GPU gebunden werden. Das würde bei Geräten mit mehreren GPUs unnötig Strom und Leistung kosten.

Muss der Browser dafür die GPU wechseln, geht der Kontext verloren (webglcontextlost) und wird auf dem passenden Adapter neu erzeugt (webglcontextrestored). Alle WebGL-Ressourcen wie Texturen, Puffer und Shader sind danach ungültig und müssen neu angelegt werden. Deshalb sollten Anwendungen beide Ereignisse immer behandeln.

Die Methode gibt es auch bei WebGL2RenderingContext. Sie ist asynchron und sollte mit await oder .then() ausgewertet werden, bevor ein XRWebGLLayer erzeugt wird.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das ohne Wert erfüllt wird, sobald der Kontext XR-kompatibel ist. Es wird mit einem InvalidStateError abgelehnt, wenn der Kontext verloren ist und nicht wiederhergestellt werden kann. Mit einem AbortError wird es abgelehnt, wenn der Wechsel zu einem kompatiblen Grafikadapter scheitert.

Beispiele

VR-Sitzung auf Knopfdruck starten

const canvas = document.querySelector('#scene');
const gl = canvas.getContext('webgl2'); // ohne xrCompatible erzeugt

document.querySelector('#enter-vr').addEventListener('click', async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.warn('Immersives VR wird nicht unterstützt.');
    return;
  }

  const session = await navigator.xr.requestSession('immersive-vr');
  await gl.makeXRCompatible(); // Kontext an XR-GPU binden

  const layer = new XRWebGLLayer(session, gl);
  session.updateRenderState({ baseLayer: layer });
  console.log('XR-Layer bereit');

  const refSpace = await session.requestReferenceSpace('local');
  const onFrame = (time, frame) => {
    session.requestAnimationFrame(onFrame);
    gl.bindFramebuffer(gl.FRAMEBUFFER, layer.framebuffer);
    gl.clearColor(0.1, 0.2, 0.3, 1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // ... Szene pro Auge anhand frame.getViewerPose(refSpace) rendern
  };
  session.requestAnimationFrame(onFrame);
});
XR-Layer bereit

Kontextverlust beim GPU-Wechsel behandeln

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

let program = null;
const initResources = () => {
  // Shader, Puffer, Texturen (neu) anlegen
  program = gl.createProgram();
  console.log('Ressourcen initialisiert');
};

canvas.addEventListener('webglcontextlost', (event) => {
  event.preventDefault(); // Wiederherstellung erlauben
  console.log('Kontext verloren');
});

canvas.addEventListener('webglcontextrestored', () => {
  initResources(); // alte Objekte sind ungültig
});

initResources();

const prepareForXR = async () => {
  try {
    await gl.makeXRCompatible();
    console.log('Kontext ist XR-kompatibel');
  } catch (err) {
    console.error(`XR-Kompatibilität fehlgeschlagen: ${err.name}`);
  }
};

prepareForXR();
Ressourcen initialisiert Kontext ist XR-kompatibel

Alternative: gleich XR-kompatibel erzeugen

// Wenn XR sicher gebraucht wird, kann das Attribut direkt gesetzt werden
const gl = document.createElement('canvas').getContext('webgl2', { xrCompatible: true });
console.log(gl.getContextAttributes().xrCompatible);

// makeXRCompatible() erfüllt sich dann sofort
gl.makeXRCompatible().then(() => console.log('bereits kompatibel'));
true bereits kompatibel

// Wichtig · Fallstricke

  • Browser-Unterstützung: Nur in Browsern mit WebXR Device API, vor allem Chrome/Edge (Desktop und Android) und dem Meta-Quest-Browser. Firefox und Safari auf dem Desktop unterstützen die Methode nicht. Vorher mit typeof gl.makeXRCompatible === 'function' prüfen.
  • Sicherer Kontext: WebXR verlangt HTTPS (oder localhost). In iframes muss zusätzlich die Berechtigungsrichtlinie xr-spatial-tracking erlaubt sein.
  • Kontextverlust: Ein GPU-Wechsel kann webglcontextlost auslösen. Ohne event.preventDefault() im Handler wird der Kontext nicht wiederhergestellt, und das Promise wird mit InvalidStateError abgelehnt.
  • Einen nicht kompatiblen Kontext an new XRWebGLLayer() zu übergeben, löst einen InvalidStateError aus.
  • Ist XR vorher sicher gewollt, ist getContext('webgl', { xrCompatible: true }) einfacher und verhindert einen späteren Kontextverlust.