Signatur
Beschreibung
Der Konstruktor XRWebGLBinding() erzeugt eine Verbindung (Binding) zwischen einer XRSession und einem WebGLRenderingContext bzw. WebGL2RenderingContext. Über dieses Objekt bekommst du GPU-seitige Ressourcen, die WebXR für diesen Kontext bereitstellt, also Texturen und Layer, in die direkt gerendert werden kann.
Du brauchst ein XRWebGLBinding vor allem in diesen Fällen:
- WebXR Layers API:
createProjectionLayer(),createQuadLayer(),createCylinderLayer(),createEquirectLayer(),createCubeLayer()sowiegetViewSubImage()/getSubImage(), um die passende Farb- und Tiefentextur pro Frame zu bekommen. - Tiefenerkennung auf der GPU mit
getDepthInformation(view)(Feature"depth-sensing"). - Zugriff auf das Kamerabild mit
getCameraImage(camera)(Feature"camera-access") in AR-Sitzungen.
Für das einfache Rendern reicht meistens der ältere XRWebGLLayer. XRWebGLBinding ist die modernere und flexiblere Alternative: Mehrere Layer lassen sich kombinieren, und der Compositor kann z. B. Text auf Quad-Layern schärfer darstellen. Wichtig: Der WebGL-Kontext muss XR-kompatibel sein. Das erreichst du mit { xrCompatible: true } beim Erzeugen des Kontexts oder durch Aufruf von gl.makeXRCompatible().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $session Pflicht | XRSession | Die WebXR-Sitzung, an die der Kontext gebunden werden soll. Sie darf noch nicht beendet sein. | |
| $context Pflicht | WebGLRenderingContext | WebGL2RenderingContext | Der WebGL-Kontext, mit dem gerendert wird. Er muss XR-kompatibel sein (xrCompatible: true oder makeXRCompatible()) und darf nicht verloren sein. Für viele Layer-Funktionen, etwa Texture Arrays, ist WebGL2 nötig. |
Rückgabewert
XRWebGLBinding-Objekt, das Sitzung und WebGL-Kontext miteinander verbindet.Beispiele
Binding für eine immersive VR-Sitzung erzeugen
const startXR = async () => {
if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
console.log('immersive-vr wird nicht unterstützt');
return;
}
const session = await navigator.xr.requestSession('immersive-vr', {
optionalFeatures: ['layers']
});
const canvas = document.createElement('canvas');
// Kontext direkt XR-kompatibel anlegen
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const binding = new XRWebGLBinding(session, gl);
console.log(binding instanceof XRWebGLBinding);
return { session, gl, binding };
};
// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#enter-vr').addEventListener('click', startXR);
Projection Layer anlegen und pro Frame rendern (WebXR Layers)
const runWithLayers = async () => {
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['layers']
});
const gl = document.createElement('canvas').getContext('webgl2');
await gl.makeXRCompatible();
const binding = new XRWebGLBinding(session, gl);
const layer = binding.createProjectionLayer({
textureType: 'texture',
depthFormat: gl.DEPTH_COMPONENT24
});
session.updateRenderState({ layers: [layer] });
const refSpace = await session.requestReferenceSpace('local');
const fb = gl.createFramebuffer();
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
for (const view of pose.views) {
const sub = binding.getViewSubImage(layer, view);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D, sub.colorTexture, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.TEXTURE_2D, sub.depthStencilTexture, 0);
const { x, y, width, height } = sub.viewport;
gl.viewport(x, y, width, height);
gl.clearColor(0.1, 0.2, 0.3, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// ... Szene für diese Ansicht zeichnen
}
};
session.requestAnimationFrame(onFrame);
};
Kamerabild in einer AR-Sitzung als WebGL-Textur holen
const startAR = async () => {
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['camera-access']
});
const gl = document.createElement('canvas').getContext('webgl2', { xrCompatible: true });
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
const binding = new XRWebGLBinding(session, gl);
const refSpace = await session.requestReferenceSpace('local');
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
const pose = frame.getViewerPose(refSpace);
if (!pose) return;
for (const view of pose.views) {
if (view.camera) {
const cameraTexture = binding.getCameraImage(view.camera);
// cameraTexture ist eine WebGLTexture, nur in diesem Frame gültig
console.log(view.camera.width, view.camera.height);
}
}
};
session.requestAnimationFrame(onFrame);
};