Virtual Reality – jetzt im Web

Hier sind einige Grundlagen, die Sie auf eine Vielzahl immersiver Erlebnisse vorbereiten: Virtual Reality, Augmented Reality und alles dazwischen.

Joe Medley
Joe Medley

Mit Chrome 79 sind immersive Erlebnisse im Web möglich. Die WebXR Device API ermöglicht Virtual Reality. Unterstützung für Augmented Reality ist in Chrome 81 verfügbar. Ein Update der GamePad API erweitert die erweiterte Verwendung von Steuerelementen auf VR. Andere Browser werden diese Spezifikationen bald unterstützen, darunter Firefox Reality, Oculus Browser, Edge und der Helio-Browser von Magic Leap.

Dieser Artikel ist der erste einer Reihe über das immersive Web. In diesem Teil geht es um das Einrichten einer einfachen WebXR-Anwendung sowie das Starten und Beenden einer XR-Sitzung. In späteren Artikeln werden die Frame-Schleife (das Arbeitstier von WebXR), die Besonderheiten von Augmented Reality und die WebXR Hit Test API behandelt, mit der Oberflächen in einer AR-Sitzung erkannt werden können. Sofern nicht anders angegeben, gilt alles, was ich in diesem und den folgenden Artikeln behandle, gleichermaßen für AR und VR.

Was ist das immersive Web?

Wir verwenden zwei Begriffe, um immersive Erlebnisse zu beschreiben: Augmented Reality und Virtual Reality. Viele sehen sie jedoch als Spektrum von der vollständigen Realität bis hin zur vollständigen Virtualität, mit unterschiedlichen Immersionsgraden dazwischen. Das „X“ in XR soll diese Denkweise widerspiegeln, indem es als eine Art algebraische Variable für alles im Spektrum immersiver Erlebnisse steht.

Ein Diagramm, das das Spektrum visueller Erlebnisse von vollständiger Realität bis hin zu vollständiger Immersion veranschaulicht.
Das Spektrum immersiver Erlebnisse

Beispiele für immersive Erlebnisse:

  • Spiele
  • 360°-Videos
  • Herkömmliche 2D- oder 3D-Videos in einer immersiven Umgebung
  • Hauskauf
  • Produkte vor dem Kauf in Ihrem Zuhause ansehen
  • Immersive Kunst
  • Etwas Cooles, an das noch niemand gedacht hat

Konzepte und Nutzung

Ich erkläre Ihnen einige Grundlagen zur Verwendung der WebXR Device API. Wenn Sie mehr Informationen benötigen, als ich Ihnen zur Verfügung gestellt habe, sehen Sie sich die WebXR-Beispiele der Immersive Web Working Group oder die wachsenden Referenzmaterialien von MDN an. Wenn Sie mit frühen Versionen der WebXR Device API vertraut sind, sollten Sie sich dieses Material ansehen. Es gab Änderungen.

Der Code in diesem Artikel basiert auf dem Barebones-Beispiel der Immersive Web Working Group (Demo, Quelle), wurde aber zur besseren Verständlichkeit und Einfachheit bearbeitet.

Bei der Entwicklung der WebXR-Spezifikation wurden Sicherheits- und Datenschutzmaßnahmen zum Schutz der Nutzer ausgearbeitet. Daher müssen Implementierungen bestimmte Anforderungen erfüllen. Eine Webseite oder App muss aktiv und im Fokus sein, bevor sie sensible Informationen vom Betrachter anfordern kann. Webseiten oder Apps müssen über HTTPS bereitgestellt werden. Die API selbst wurde entwickelt, um Informationen zu schützen, die von Sensoren und Kameras stammen und die sie für ihre Funktion benötigt.

Sitzung anfordern

Für den Start einer XR-Sitzung ist eine Nutzergeste erforderlich. Verwenden Sie die Funktionserkennung, um XRSystem (über navigator.xr) zu testen, und rufen Sie XRSystem.isSessionSupported() auf. In Chrome-Version 79 und 80 hieß das XRSystem-Objekt XR.

Im Beispiel unten habe ich angegeben, dass ich eine Virtual-Reality-Sitzung mit dem Sitzungstyp 'immersive-vr' wünsche. Die anderen Sitzungstypen sind 'immersive-ar' und 'inline'. Eine Inline-Sitzung dient zur Präsentation von Inhalten in HTML und wird hauptsächlich für Teaserinhalte verwendet. Das Immersive AR Session-Beispiel veranschaulicht dies. Das erkläre ich in einem späteren Artikel.

Sobald ich weiß, dass Virtual-Reality-Sitzungen unterstützt werden, aktiviere ich eine Schaltfläche, über die ich eine Nutzergeste erfassen kann.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter VR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

Nachdem ich die Schaltfläche aktiviert habe, warte ich auf ein Klickereignis und fordere dann eine Sitzung an.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-vr')
    .then((session) => {
      xrSession = session;
      xrButton.textContent = 'Exit XR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

Beachten Sie die Objekthierarchie in diesem Code. Sie wird von navigator nach xr in eine XRSession-Instanz verschoben. In früheren Versionen der API musste ein Skript ein Gerät anfordern, bevor es eine Sitzung anfordern konnte. Das Gerät wird jetzt implizit erworben.

Sitzung eingeben

Nachdem ich eine Sitzung erhalten habe, muss ich sie starten und betreten. Aber zuerst muss ich noch ein paar Dinge einrichten. Für eine Sitzung ist ein onend-Ereignishandler erforderlich, damit die App oder Webseite zurückgesetzt werden kann, wenn der Nutzer sie verlässt.

Außerdem benötige ich ein <canvas>-Element, auf dem ich die Szene zeichnen kann. Es muss ein XR-kompatibler WebGLRenderingContext oder WebGL2RenderingContext sein. Alle Zeichnungen werden mit diesen oder einem WebGL-basierten Framework wie Three.js erstellt.

Jetzt, da ich einen Ort zum Zeichnen habe, brauche ich eine Quelle für Inhalte, auf die ich zurückgreifen kann. Dazu erstelle ich eine Instanz von XRWebGLLayer. Ich verknüpfe es mit dem Canvas, indem ich XRSession.updateRenderState() aufrufe.

Wenn ich mich in einer Sitzung befinde, muss ich wissen, wo sich die Dinge in der virtuellen Realität befinden. Ich brauche einen Referenzraum. In einem 'local-floor'-Referenzraum befindet sich der Ursprung in der Nähe des Betrachters. Die y-Achse ist auf Bodenhöhe 0 und sollte sich nicht bewegen. Es gibt weitere Arten von Referenzräumen, aber das ist ein komplexeres Thema, als ich hier behandeln kann. Ich speichere den Referenzbereich in einer Variablen, da ich ihn zum Zeichnen auf dem Bildschirm benötige.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

Nachdem ich einen Referenzbereich erhalten habe, rufe ich XRSession.requestAnimationFrame() auf. Dies ist der Beginn der Präsentation virtueller Inhalte, die im Frame-Loop erfolgt.

Frame-Schleife ausführen

Die Frame-Schleife ist eine vom User-Agent gesteuerte Endlosschleife, in der Inhalte wiederholt auf dem Bildschirm dargestellt werden. Inhalte werden in diskreten Blöcken, sogenannten Frames, dargestellt. Die Abfolge der Frames erzeugt die Illusion von Bewegung. Bei VR-Anwendungen kann die Bildrate zwischen 60 und 144 fps liegen. AR für Android wird mit 30 Bildern pro Sekunde ausgeführt. In Ihrem Code sollte keine bestimmte Framerate angenommen werden.

Der grundlegende Ablauf für die Frame-Schleife ist:

  1. Rufen Sie einfach XRSession.requestAnimationFrame() an. Als Reaktion darauf ruft der User-Agent die von Ihnen definierte XRFrameRequestCallback auf.
  2. In Ihrer Callback-Funktion:
    1. Rufen Sie XRSession.requestAnimationFrame() noch einmal an.
    2. Die Pose des Zuschauers abrufen
    3. Binden Sie die WebGLFramebuffer aus der XRWebGLLayer an die WebGLRenderingContext.
    4. Iterieren Sie über jedes XRView-Objekt, rufen Sie das zugehörige XRViewport aus dem XRWebGLLayer ab und übergeben Sie es an das WebGLRenderingContext.
    5. Etwas in den Framebuffer zeichnen.

Im weiteren Verlauf dieses Artikels werden Schritt 1 und ein Teil von Schritt 2 beschrieben: das Einrichten und Aufrufen der XRFrameRequestCallback. Die verbleibenden Elemente von Schritt 2 werden in Teil II behandelt.

Der XRFrameRequestCallback

Sie definieren den XRFrameRequestCallback. Sie hat zwei Parameter: eine DOMHighResTimeStamp- und eine XRFrame-Instanz. Das XRFrame-Objekt enthält die Informationen, die zum Rendern eines einzelnen Frames auf dem Display erforderlich sind. Das Argument DOMHighResTimeStamp ist für die zukünftige Verwendung vorgesehen.

Bevor ich etwas anderes tue, fordere ich den nächsten Animationsframe an. Wie bereits erwähnt, wird das Timing von Frames vom User-Agent auf Grundlage der zugrunde liegenden Hardware bestimmt. Wenn Sie zuerst den nächsten Frame anfordern, wird der Frame-Loop fortgesetzt, falls während des Callbacks ein Fehler auftritt.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  // Render a frame.
}

Jetzt ist es an der Zeit, etwas für den Zuschauer zu zeichnen. Das ist ein Thema für Teil II. Bevor wir dorthin gehen, zeige ich dir, wie du eine Sitzung beendest.

Sitzung beenden

Eine immersive Sitzung kann aus verschiedenen Gründen beendet werden, z. B. durch einen Aufruf von XRSession.end() in Ihrem eigenen Code. Weitere Ursachen sind, dass das Headset getrennt wurde oder eine andere Anwendung die Steuerung übernommen hat. Deshalb sollte eine gut funktionierende Anwendung das end-Ereignis überwachen. Wenn dies geschieht, verwerfen Sie die Sitzung und die zugehörigen Rendering-Objekte. Eine beendete immersive Sitzung kann nicht fortgesetzt werden. Um wieder in die immersive Umgebung zu gelangen, muss meine App eine neue Sitzung starten.

Zur Erinnerung: Beim Einrichten habe ich einen onend-Event-Handler hinzugefügt (siehe Sitzung starten).

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);
  // More setup…
}

Stellen Sie im Ereignishandler den Zustand der App vor dem Start einer Sitzung durch den Nutzer wieder her.

function onSessionEnded(event) {
  xrSession = null;
  xrButton.textContent = 'Enter VR';
}

Fazit

Ich habe nicht alles erklärt, was Sie zum Schreiben einer WebXR- oder AR-Anwendung benötigen. Ich hoffe, ich habe Ihnen genug Informationen gegeben, damit Sie den Code selbst nachvollziehen und damit experimentieren können. Im nächsten Artikel erkläre ich den Frame-Loop, in dem Inhalte auf dem Bildschirm dargestellt werden.