Entwickeln

WebXR Layers

WebXR Layers erweitern die von der Meta Horizon-Plattform bereitgestellte Timewarp-Funktion. In Web-Erlebnissen bieten diese Layers folgende Vorteile:
  1. Bessere Performance
  2. Höhere Renderingqualität für Bilder und Texte
  3. Einfache Anzeige von immersiven Videos
Die Vorteile von WebXR Layers werden in verschiedenen Beispielen demonstriert. Du findest diese Beispiele unter WebXR-Beispiele auf GitHub.

Bessere Performance

WebXR gibt normalerweise vor, dass du beim Rendern die Bildwiederholrate des Geräts verwenden musst. Mit Layers reicht es aus, gerenderte Inhalte zu übermitteln, wenn der Layer aktualisiert wird. Wenn du beispielsweise eine statische Skybox hast, kannst du sie einmal rendern, und das Betriebssystem übernimmt den Rest. Damit ist mehr Kapazität für das Rendering der dynamischen Teile deines Erlebnisses frei.

Qualitativ hochwertige Bilder

Mit WebXR Layers kannst du direkt in den abschließenden Buffer rendern und dadurch doppeltes Abtasten und Verzerrungen vermeiden.
Fuzzy WebXR Screenshot In WebXR
Sharp WebXR Layer Screenshot Im WebXR-Äquirekt-Layer

Einfachere Videowiedergabe

Mit WebXR Media Layers kannst du Videos viel einfacher wiedergeben als mit Frameworks von Drittanbietern. Du kannst etwa wie hier gezeigt eine immersive Session mit einem Media Layer einrichten:
… // Create an immersive session with layers support.
let xrMediaFactory = new XRMediaBinding(session);
let video = document.createElement('video');
video.src = '...'; // url to your video

let layer = xrMediaFactory.createCylinderLayer(video,
{space: refSpace, layout: "stereo-top-bottom"});
session.updateRenderState({ layers: [ layer ] });
Der Browser übernimmt die Größenanpassung des Layers und stellt ihn möglichst optimal dar, um dir ein möglichst hochwertiges Video mit minimaler Systembelastung zu bieten.
Diese Funktion unterstützt alle Videos, inklusive Cross-Origin- oder Streamingvideos. Das WebXR-Videobeispiel auf GitHub demonstriert, wie einfach du hochwertige Videos abspielen kannst.

Emulation für andere Browser

WebXR Layers werden nicht in allen Browsern unterstützt. Um die Entwicklung auf unterschiedlichen Browsern und Geräten zu ermöglichen, unterstützt das im Immersive Web GitHub gehostete WebXR Layers-Polyfill die Emulation von WebXR Layers. Dieses Framework emuliert die Implementierung nativer Layers. In der Dokumentation auf der GitHub-Seite erfährst du, wie du diese Lösung in dein Erlebnis integrieren kannst.

WebXR Layers –Technische Übersicht

Was sind WebXR Layers?

In herkömmlichen WebXR-Erlebnissen wird die gesamte Szene von JavaScript mit der Bildwiederholrate des Geräts in einen Framebuffer (auch als „Eye-Render-Buffer“ bekannt) gerendert. Dieser Framebuffer wird anschließend an den System-Compositor übermittelt, der ihn mit Timewarp für den*die Nutzer*in darstellt. Timewarp berücksichtigt die winzigen Abweichungen der Kopfposition, seitdem der Browser die Szene gerendert hat.
In der Praxis übermittelt der Browser dem JavaScript-Code die erwartete Kopfposition des Headsets zum Ende des Einzelbilds und rendert die Szene anschließend. Wenn sich die Kopfposition des*der Nutzer*in unerwartet ändert, kann diese Position zu Beginn des Renderings stark von der erwarteten Position abweichen. Timewarp gleicht diese Abweichung aus und sorgt für ein qualitativ hochwertiges und komfortables VR-Erlebnis. Timewarp ist außerdem hilfreich, wenn der Browser beim Rendern zurückfällt, indem neue Einzelbilder erfunden werden. Auf diese Weise wird das Erlebnis etwas flüssiger gestaltet, aber der*die Nutzer*in bemerkt dennoch, dass die Szene nicht flüssig abläuft.
WebXR Technical Diagram
In einer Szene mit einer Skybox, einem Video und deinen interaktiven Inhalten rendert WebXR jedes einzelne Pixel für jedes Einzelbild mit WebGL. Auf diese Weise wird jedes Pixel im Video und der Skybox vom Browser abgetastet, um den Eye-Render-Buffer zu erstellen. Anschließend wird der Eye-Render-Buffer an den Compositor übermittelt, der Timewarp anwendet und eine Linsenanpassung vornimmt. Dabei werden die Pixel im Video und der Skybox zweimal abgetastet und leicht unscharf dargestellt, insbesondere bei hochauflösenden Video- oder Skybox-Inhalten.
Mit WebXR Layers zeichnest du deine Skybox oder dein Video auf eine Struktur, die separat vom Eye-Render-Buffer verarbeitet wird. Diese Struktur wird anschließend direkt vom Compositor verarbeitet.
In unserem vorherigen Beispiel lädst du eine Cubemap einmal zu Beginn der Szene hoch, und ab diesem Moment übernimmt der Compositor das Zeichnen der Skybox. Damit wird die Qualität der Skybox verbessert, und der Browser hat mehr freie Kapazität für die interaktiven Vordergrundinhalte. Dein Video kannst du ebenfalls einem Media Layer und einem Videoelement zuordnen. Anschließend übernimmt das System das Rendering mit der passenden Bildwiederholrate.
WebXR Layer Technical Diagram
Mit Layers stellt der System-Compositor deinen Eye-Render-Buffer wie bisher mit Timewarp dar, aber deine Skybox und dein Video werden ebenfalls direkt gerendert und mit Timewarp bearbeitet. Der Compositor kann die Skybox und das Video direkt abtasten, wodurch sich die Qualität verbessert, weil jedes Pixel nur einmal abgetastet und damit die GPU entlastet wird. Layers basieren auf den Meta Quest Timewarp Layers und die API bildet die OpenXR Composition Layers ab. Unter Immersive Web Layers Explainer (Erklärung zu immersiven Web Layers) auf GitHub findest du eine ausführliche Erklärung der WebXR Layers API.

Was sind WebXR Media Layers?

WebXR Media Layers verwenden WebGL, um Inhalte in gewöhnlichen WebXR Layers darzustellen. Diese Layers bieten hervorragende Anpassungs- und Kontrollmöglichkeiten, sind jedoch komplex einzurichten, erfordern gute Kenntnisse über Shader und andere komplexe Logik.
Um ein Video anzuzeigen, ist es oft einfacher, ein Media Layer mit der gewünschten Größe und Position zu erstellen und einem standardmäßigen <video>-Element zuzuordnen. Daraufhin wird der Videoinhalt in diesem Layer angezeigt. Für die Wiedergabe kannst du die üblichen Methoden im Videoelement verwenden. Ein Beispiel findest du im WebXR Media Layer-Beispiel auf GitHub.

Bildqualität

Eine Demonstration der Verbesserung der Bildqualität findest du im Cube Layer-Beispiel auf GitHub. Wenn du eine immersive Umgebung verwendest, siehst du ein immersives 360°-Foto. Zu Anfang wird das Foto mit gewöhnlichem WebXR dargestellt, aber wenn du den Trigger ziehst, wechselt die Anzeige zu Layers. Beachte, wie viel schärfer das Bild mit Layers dargestellt wird.
Oben im Abschnitt Qualitativ hochwertige Bilder findest du Screenshots der im Beispiel demonstrierten Unterschiede.
Die Version, die Layers verwendet, ist schärfer und weniger verzerrt, insbesondere am oberen und unteren Rand der Szene. Dies liegt daran, dass das Bild nur einmal abgetastet wird. Außerdem kann der Compositor das Bild besser neu projizieren, da er weiß, dass es sich um ein Äquirekt handelt.

Unterschiede in der GPU-Auslastung

Du kannst die Verbesserung der GPU-Auslastung mit ovrgpuprofiler messen.
Führe zunächst „ovrgpuprofiler -e“ aus, um den ausführlichen Profilerstellungsmodus zu aktivieren. Anschließend kannst du mit „ovrgpuprofiler -t“ eine Ablaufverfolgung ausführen. (Nach der Ausführung mit „-e“ musst du unter Umständen den Browser mit dem Befehl „adb shell am force-stop com.oculus.browser“ neu starten.)
Für das gewöhnliche WebXR-Erlebnis liefert das Tool mit der Option -t die folgende Ausgabe:
... | 3.14 ms | 75 stages : Binning : 0.085ms Render : 1.623ms StoreColor : 0.362ms Blit : 0.002ms Preempt : 0.819ms
... | 3.15 ms | 75 stages : Binning : 0.084ms Render : 1.618ms StoreColor : 0.363ms Blit : 0.003ms Preempt : 0.819ms
... | 3.21 ms | 75 stages : Binning : 0.085ms Render : 1.663ms StoreColor : 0.364ms Blit : 0.003ms Preempt : 0.837ms
Pro Einzelbild fallen etwa 3,15 Millisekunden an Renderzeit an.
Für das Erlebnis mit WebXR Layers liefert das Tool mit der Option -t die folgende Ausgabe:
... | 0.72 ms | 74 stages : Binning : 0.072ms Render : 0.266ms StoreColor : 0.215ms Blit : 0.002ms
... | 0.72 ms | 74 stages : Binning : 0.072ms Render : 0.263ms StoreColor : 0.219ms Blit : 0.003ms
... | 0.72 ms | 74 stages : Binning : 0.073ms Render : 0.265ms StoreColor : 0.221ms Blit : 0.003ms
  • „Render“ ist deutlich schneller, weil nur die Controller dargestellt werden.
  • “StoreColor“ ist ebenfalls schneller, da ein Großteil der Szene leer ist und die entsprechenden Kacheln nicht kopiert werden müssen.
  • „preempt“ existiert nicht. Die Szene wird so schnell gerendert, dass kein Event des System-Compositors zwischengeschoben wurde.
Das „overgpuprofiler“-Tool unterstützt viele weitere Kennzahlen, die im ovrgpuprofiler-Leitfaden beschrieben werden.
GPU-Gesamtauslastung in den beiden Modi: gewöhnliches WebXR: GPU % Bus Busy : 50.210 WebXR Layers: GPU % Bus Busy : 23.904
Dasselbe Erlebnis wird also mit einer höheren Qualität und mit der Hälfte der GPU-Auslastung ausgeführt.