Signatur
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
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);
});
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();
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'));
// 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 Berechtigungsrichtliniexr-spatial-trackingerlaubt sein. - Kontextverlust: Ein GPU-Wechsel kann
webglcontextlostauslösen. Ohneevent.preventDefault()im Handler wird der Kontext nicht wiederhergestellt, und das Promise wird mitInvalidStateErrorabgelehnt. - Einen nicht kompatiblen Kontext an
new XRWebGLLayer()zu übergeben, löst einenInvalidStateErroraus. - Ist XR vorher sicher gewollt, ist
getContext('webgl', { xrCompatible: true })einfacher und verhindert einen späteren Kontextverlust.