Signatur
Beschreibung
createEquirectLayer() gehört zur XRMediaBinding-Schnittstelle der WebXR Layers API. Die Methode verbindet ein HTMLVideoElement direkt mit einer Kompositionsebene, die das Video als equirectangulare Projektion auf die Innenseite einer Kugel legt. So lassen sich 360°- und 180°-Videos in einer immersiven XR-Sitzung abspielen, ohne dass jeder Videoframe selbst per WebGL in eine Textur kopiert und gerendert werden muss.
Weil der XR-Compositor die Ebene direkt darstellt, sind Bildqualität und Schärfe meist besser als beim Rendern über eine Projektionsebene: Das Video wird nur einmal abgetastet, und Bildrate und Stromverbrauch profitieren davon. Das ist vor allem auf Standalone-Headsets spürbar.
Über das options-Objekt legst du den Referenzraum, die Stereo-Aufteilung des Videos (mono, stereo-left-right, stereo-top-bottom), den Kugelradius und die abgedeckten Winkelbereiche fest. Mit diesen Winkeln kannst du auch Teilkugeln abbilden, etwa bei 180°-VR-Videos. Damit die erzeugte Ebene sichtbar wird, muss sie über XRSession.updateRenderState({ layers: [...] }) in die Ebenenliste der Sitzung aufgenommen werden.
Voraussetzung ist eine immersive Sitzung, die mit dem Feature "layers" angefordert wurde (requiredFeatures oder optionalFeatures).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $video Pflicht | HTMLVideoElement | Das Videoelement, dessen Frames in der Ebene angezeigt werden. Die Wiedergabe steuerst du weiter über video.play()/pause(). |
|
| $options | object | {} | Konfigurationsobjekt (XRMediaEquirectLayerInit) mit den folgenden Eigenschaften. |
| $options.space Pflicht | XRSpace | Raum, in dem die Kugel verankert ist, typischerweise ein Referenzraum wie "local". Ohne Angabe wirft die Methode einen Fehler. |
|
| $options.layout | "mono" | "stereo" | "stereo-left-right" | "stereo-top-bottom" | "mono" | Anordnung der Bilder für linkes und rechtes Auge innerhalb des Videos. |
| $options.invertStereo | boolean | false | Vertauscht die Bilder für linkes und rechtes Auge, z. B. bei falsch gemasterten Videos. |
| $options.transform | XRRigidTransform | Identität | Position und Ausrichtung des Kugelmittelpunkts relativ zu space. |
| $options.radius | number | 0 | Kugelradius in Metern. 0 bedeutet unendlich groß, die Kugel wirkt also wie eine Umgebung ohne Parallaxe. |
| $options.centralHorizontalAngle | number | 6.28318 (2π) | Horizontal abgedeckter Winkel in Radiant. Math.PI ergibt z. B. eine 180°-Halbkugel. |
| $options.upperVerticalAngle | number | π/2 | Oberer vertikaler Grenzwinkel in Radiant. |
| $options.lowerVerticalAngle | number | -π/2 | Unterer vertikaler Grenzwinkel in Radiant. |
Rückgabewert
XREquirectLayer-Ebene. Ihre Eigenschaften (z. B. radius, transform, centralHorizontalAngle) kannst du auch nach dem Erzeugen noch ändern.Beispiele
360°-Video in einer immersiven Sitzung abspielen
const video = document.createElement('video');
video.src = '/media/strand-360.mp4';
video.crossOrigin = 'anonymous';
video.loop = true;
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['layers']
});
const refSpace = await session.requestReferenceSpace('local');
const mediaBinding = new XRMediaBinding(session);
const equirect = mediaBinding.createEquirectLayer(video, {
space: refSpace,
layout: 'mono'
});
session.updateRenderState({ layers: [equirect] });
await video.play();
console.log('Radius:', equirect.radius);
};
document.querySelector('#vr-start').addEventListener('click', startXR);
180°-Stereo-Video (Side-by-Side) als Halbkugel
const createVR180Layer = (session, refSpace, video) => {
const binding = new XRMediaBinding(session);
return binding.createEquirectLayer(video, {
space: refSpace,
layout: 'stereo-left-right',
centralHorizontalAngle: Math.PI, // 180° horizontal
upperVerticalAngle: Math.PI / 2,
lowerVerticalAngle: -Math.PI / 2,
radius: 20
});
};
const layer = createVR180Layer(session, refSpace, video);
session.updateRenderState({ layers: [layer] });
Equirect-Ebene mit WebGL-Projektionsebene kombinieren
const gl = canvas.getContext('webgl2', { xrCompatible: true });
const glBinding = new XRWebGLBinding(session, gl);
const projLayer = glBinding.createProjectionLayer();
const equirect = new XRMediaBinding(session).createEquirectLayer(video, {
space: refSpace,
transform: new XRRigidTransform({ x: 0, y: 1.6, z: 0 })
});
// Reihenfolge = Zeichenreihenfolge: Video hinten, 3D-UI davor
session.updateRenderState({ layers: [equirect, projLayer] });
// Wichtig · Fallstricke
- Browser-Unterstützung: Die WebXR Layers API ist experimentell und wird derzeit im Wesentlichen vom Meta Quest Browser unterstützt. Prüfe die Unterstützung vorher mit
'XRMediaBinding' in windowund fordere"layers"am besten alsoptionalFeaturesan, damit du eine Ausweichlösung anbieten kannst. - Ist die Sitzung bereits beendet oder das Feature
"layers"nicht aktiviert, wirft die Methode einenInvalidStateError. Ein ungültigeslayoutwie"default"führt zu einem Fehler. - Die Ebene wird erst angezeigt, wenn sie in
updateRenderState({ layers })eingetragen ist. Die Reihenfolge im Array bestimmt, welche Ebene über welcher liegt. - Videos von fremden Ursprüngen brauchen korrekte CORS-Header und
crossOrigin. Wegen der Autoplay-Richtlinien der Browser mussvideo.play()meist durch eine Nutzeraktion ausgelöst werden. - Die Winkel werden in Radiant angegeben, nicht in Grad. Ein
radiusvon0bedeutet eine unendlich große Kugel. - Stimmt
layoutnicht mit dem tatsächlichen Videoformat überein, sieht man doppelte oder verzerrte Bilder. Prüfe daher, wie das Video gemastert ist.