Start · Sprachen · JavaScript · Referenz · XRMediaBinding.createCylinderLayer()

XRMediaBinding.createCylinderLayer()

Methode

Erzeugt einen <code>XRCylinderLayer</code>, der ein <code>HTMLVideoElement</code> auf einer gekrümmten, zylinderförmigen Fläche in der XR-Szene darstellt.

seit JavaScript Experimentell: WebXR Layers API (Chromium-basiert, Kategorie: webapi

Signatur

XRMediaBinding.prototype.createCylinderLayer(video, options)

Beschreibung

Die Methode createCylinderLayer() einer XRMediaBinding-Instanz erzeugt eine Medien-Schicht in Form eines Zylinderausschnitts. Der Inhalt eines <video>-Elements wird dabei direkt vom Compositor des XR-Geräts auf die gekrümmte Fläche gezeichnet. Sie müssen die Videobilder also nicht selbst in einer WebGL-Renderschleife als Textur hochladen.

Zylinder-Schichten eignen sich besonders für Kino- und Panorama-Leinwände, die den Nutzer halb umschließen. Bei gleicher Breite verzerren sie am Rand weniger als eine flache Quad-Schicht. Weil der Compositor direkt zeichnet, sind Text und Video meist schärfer und der Energieverbrauch ist geringer als beim Rendern über eine Projektionsschicht.

Die Form wird über radius, centralAngle (Bogenwinkel im Bogenmaß) und aspectRatio bestimmt, die Lage über space und transform. Mit layout lassen sich auch Stereo-Videos (nebeneinander oder übereinander) korrekt auf beide Augen verteilen. Die erzeugte Schicht wird erst sichtbar, wenn Sie sie über XRSession.updateRenderState({ layers: [...] }) in die Schichtliste der Sitzung aufnehmen.

Voraussetzung ist eine immersive Sitzung, die mit dem Feature "layers" angefordert wurde. Die Sitzung wird beim Konstruktor new XRMediaBinding(session) übergeben.

Parameter

Name Typ Default Beschreibung
$video Pflicht HTMLVideoElement Das Videoelement, dessen Bilder auf der Schicht angezeigt werden.
$options Pflicht Object Konfigurationsobjekt mit den folgenden Eigenschaften.
$options.space Pflicht XRSpace Referenzraum, in dem die Schicht positioniert wird, z. B. aus session.requestReferenceSpace("local").
$options.layout "mono" | "stereo-left-right" | "stereo-top-bottom" "mono" Aufteilung des Videobilds auf die Augen. Bei Stereo-Layouts erhält jedes Auge die passende Hälfte des Bilds.
$options.invertStereo boolean false Vertauscht bei Stereo-Layouts linke und rechte Bildhälfte.
$options.transform XRRigidTransform Identitätstransformation Position und Ausrichtung des Zylindermittelpunkts relativ zu space.
$options.radius number 2.0 Radius des Zylinders in Metern, also der Abstand der Leinwand vom Mittelpunkt.
$options.centralAngle number 0.78539 (π/4) Horizontaler Bogenwinkel des sichtbaren Zylinderausschnitts im Bogenmaß.
$options.aspectRatio number Seitenverhältnis des Videos Verhältnis von Breite zu Höhe der Schicht. Ohne Angabe wird es aus videoWidth/videoHeight bzw. dem Layout abgeleitet.

Rückgabewert

Typ
XRCylinderLayer
Beschreibung
Eine neue Zylinder-Schicht, deren Inhalt vom Compositor laufend aus dem Video aktualisiert wird. Die Werte radius, centralAngle, aspectRatio und transform lassen sich später noch ändern.

Beispiele

Video als gekrümmte Kinoleinwand anzeigen

const startCinema = async () => {
  const video = document.querySelector('#film');
  const session = await navigator.xr.requestSession('immersive-vr', {
    requiredFeatures: ['layers']
  });
  const refSpace = await session.requestReferenceSpace('local');

  const mediaBinding = new XRMediaBinding(session);
  const cylinderLayer = mediaBinding.createCylinderLayer(video, {
    space: refSpace,
    radius: 3,                     // 3 m entfernt
    centralAngle: Math.PI / 2,     // 90° Bogen
    transform: new XRRigidTransform({ x: 0, y: 1.6, z: 0 })
  });

  session.updateRenderState({ layers: [cylinderLayer] });
  await video.play();
};

document.querySelector('#start').addEventListener('click', startCinema);

Stereo-Video (nebeneinander) mit Projektionsschicht kombinieren

const setupStereoScreen = async (session, gl, video) => {
  const refSpace = await session.requestReferenceSpace('local-floor');
  const glBinding = new XRWebGLBinding(session, gl);
  const projectionLayer = glBinding.createProjectionLayer();

  const mediaBinding = new XRMediaBinding(session);
  const screen = mediaBinding.createCylinderLayer(video, {
    space: refSpace,
    layout: 'stereo-left-right',
    radius: 4,
    centralAngle: Math.PI / 3,
    transform: new XRRigidTransform({ x: 0, y: 1.5, z: -1 })
  });

  // Reihenfolge: hintere Schichten zuerst
  session.updateRenderState({ layers: [projectionLayer, screen] });
  return screen;
};

Leinwand zur Laufzeit vergrößern und Feature-Erkennung

if (!('XRMediaBinding' in window)) {
  console.warn('WebXR-Medienschichten werden nicht unterstützt.');
}

// screen ist ein zuvor erzeugter XRCylinderLayer
const widenScreen = (screen) => {
  screen.centralAngle = Math.min(screen.centralAngle * 1.25, Math.PI);
  console.log(`Neuer Bogen: ${(screen.centralAngle * 180 / Math.PI).toFixed(0)}°`);
};
Neuer Bogen: 113°

// Wichtig · Fallstricke

  • Experimentell: Die WebXR Layers API wird bisher nur von einigen Chromium-basierten Browsern unterstützt, vor allem vom Meta Quest Browser. Firefox und Safari unterstützen sie nicht. Prüfen Sie deshalb immer vorab mit 'XRMediaBinding' in window.
  • Die Sitzung muss mit requiredFeatures oder optionalFeatures: ['layers'] angefordert werden. Wurde "layers" nicht aktiviert oder ist die Sitzung bereits beendet, wirft die Methode eine InvalidStateError-DOMException.
  • Die Schicht wird erst nach session.updateRenderState({ layers }) sichtbar. In der Schichtliste stehen hintere Schichten zuerst.
  • Das Video muss selbst abgespielt werden (video.play()). Wegen der Autoplay-Richtlinien sollte der Aufruf in einer Nutzerinteraktion erfolgen. Videos von fremden Ursprüngen benötigen CORS (crossorigin-Attribut).
  • centralAngle wird im Bogenmaß angegeben, nicht in Grad. Sehr große Winkel nahe 2π erzeugen einen fast geschlossenen Ring.
  • Kennt der Browser die Videoabmessungen noch nicht (vor loadedmetadata), kann das automatisch abgeleitete aspectRatio falsch sein. Geben Sie es im Zweifel ausdrücklich an.