Virtual Reality – jetzt im Web

Hier sind ein paar Grundlagen, mit denen du dich auf die verschiedenen immersiven Erlebnisse vorbereiten kannst: Virtual Reality, Augmented Reality und alles dazwischen.

Joe Medley
Joe Medley

Mit Chrome 79 bietet das Web beeindruckende Erlebnisse. Die WebXR Device API bringt Virtual Reality mit Virtual Reality und in Chrome 81 wird Augmented Reality unterstützt. Ein Update der GamePad API dehnt die erweiterte Verwendung der Steuerelemente auf VR-Geräte aus. Andere Browser werden diese Spezifikationen bald unterstützen, darunter Firefox Reality, Oculus Browser, Edge und Helio-Browser von Magic Leap.

Mit diesem Artikel beginnt eine Reihe zum Thema „Immersive Web“. In diesem Teil wird das Einrichten einer einfachen WebXR-Anwendung sowie das Starten und Beenden einer XR-Sitzung beschrieben. In späteren Artikeln werden die Frameschleife (das Arbeitstier der WebXR-Erfahrung), die Besonderheiten der Augmented Reality und die WebXR Hit Test API behandelt, mit der Oberflächen in einer AR-Sitzung erkannt werden. Sofern nicht anders angegeben, gilt alles, was in diesem und den nachfolgenden Artikeln behandelt wird, sowohl für AR als auch für VR.

Was ist das immersive Web?

Obwohl wir immersive Erlebnisse mit zwei Begriffen beschreiben – Augmented Reality und Virtual Reality –, betrachten wir sie in einem Spektrum von vollständiger Realität bis hin zu vollständig virtuell, wobei die verschiedenen Ebenen eintauchen. Das „X“ in XR soll dieses Denken widerspiegeln, indem es eine Art algebraische Variable ist, die für alles im Spektrum immersiver Erlebnisse steht.

Ein Diagramm, das das Spektrum der visuellen Erlebnisse von der realen bis zum immersiven Wahrnehmung veranschaulicht.
Die Bandbreite immersiver Erlebnisse

Beispiele für immersive Erfahrungen:

  • Spiele
  • 360°-Videos
  • Traditionelle 2D-Videos (oder 3D-Videos) in einer eindrucksvollen Umgebung
  • Hauskauf
  • Produkte in deinem Zuhause vor dem Kauf ansehen
  • Immersive Kunst
  • Etwas Cooles, an das noch niemand gedacht hat

Konzepte und Nutzung

Ich werde Ihnen einige Grundlagen zur Verwendung der WebXR Device API erklären. Wenn Sie ausführlichere Informationen benötigen, sehen Sie sich die WebXR-Beispiele der Immersive Web Working Group oder die zunehmenden 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 einfachen Beispiel der Immersive Web Working Group (Demo, Quelle), wurde jedoch der Einfachheit halber überarbeitet.

Im Rahmen der Erstellung 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 fokussiert sein, bevor sensible Daten vom Betrachter angefordert werden können. Webseiten oder Apps müssen über HTTPS bereitgestellt werden. Die API selbst schützt von Sensoren und Kameras erhaltene Informationen, die sie für das Funktionieren benötigt.

Sitzung anfordern

Zum Aufrufen einer XR-Sitzung ist eine Nutzergeste erforderlich. Dazu testen Sie mit der Funktionserkennung XRSystem (über navigator.xr) und rufen XRSystem.isSessionSupported() auf. In den Chrome-Versionen 79 und 80 hieß das XRSystem-Objekt XR.

Im folgenden Beispiel habe ich angegeben, dass ich eine Virtual-Reality-Sitzung mit dem Sitzungstyp 'immersive-vr' möchte. Die anderen Sitzungstypen sind 'immersive-ar' und 'inline'. Eine Inline-Sitzung dient der Präsentation von Inhalten in HTML und wird hauptsächlich für Teaser-Inhalte verwendet. Das Beispiel Immersive AR Session veranschaulicht dies. Ich erkläre das in einem späteren Artikel.

Sobald ich weiß, dass Virtual-Reality-Sitzungen unterstützt werden, aktiviere ich eine Schaltfläche, mit der ich eine Nutzergeste übernehmen 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. Er wird von navigator nach xr in eine XRSession-Instanz verschoben. In frühen Versionen der API musste ein Skript ein Gerät anfordern, bevor eine Sitzung angefordert wurde. Jetzt wird das Gerät implizit übernommen.

Sitzung eingeben

Nachdem ich eine Sitzung erhalten habe, muss ich sie starten und eingeben. Aber zuerst muss ich ein paar Dinge einrichten. Eine Sitzung benötigt einen onend-Event-Handler, damit die App oder Webseite zurückgesetzt werden kann, wenn der Nutzer die Sitzung beendet.

Außerdem benötige ich ein <canvas>-Element, um meine Szene zu zeichnen. Es muss ein XR-kompatibler WebGLRenderingContext oder WebGL2RenderingContext sein. Alle Zeichnungen werden mit ihnen oder einem WebGL-basierten Framework wie Three.js ausgeführt.

Jetzt, da ich einen Ort habe, an dem ich zeichnen kann, brauche ich eine Inhaltsquelle, um darauf zu zeichnen. Dafür erstelle ich eine Instanz von XRWebGLLayer. Ich verknüpfe es mit dem Canvas, indem ich XRSession.updateRenderState() aufrufe.

In einer Sitzung brauche ich eine Möglichkeit, um zu ermitteln, wo sich die Dinge in der Virtual Reality befinden. Ich brauche einen Referenzraum. Bei einem 'local-floor'-Referenzraum befindet sich der Ursprung in der Nähe des Viewer, wobei die Y-Achse auf Bodenhöhe den Wert 0 hat und sich daher nicht bewegen soll. Es gibt andere Arten von Referenzbereichen, aber das ist ein komplexeres Thema, als ich hier aufzählen kann. Ich speichere den Referenzraum 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 ein Referenzraum abgerufen habe, rufe ich XRSession.requestAnimationFrame() auf. Dies ist der Beginn der Präsentation virtueller Inhalte in der Frame-Schleife.

Frameschleife ausführen

Die Frameschleife ist eine vom User-Agent gesteuerte Endlosschleife, in der Inhalte wiederholt auf den Bildschirm gezeichnet werden. Inhalte werden in einzelnen Blöcken gezeichnet, die als Frames bezeichnet werden. Die Abfolge von Frames erzeugt den Eindruck einer Bewegung. Bei VR-Anwendungen können die Bilder pro Sekunde zwischen 60 und 144 Bildern betragen. AR für Android läuft mit 30 Bildern pro Sekunde. Ihr Code sollte nicht von einer bestimmten Frame-Rate ausgehen.

Der grundlegende Prozess für die Frameschleife sieht so aus:

  1. Rufen Sie einfach XRSession.requestAnimationFrame() an. Der User-Agent ruft als Antwort die von dir definierte XRFrameRequestCallback auf.
  2. Führen Sie innerhalb der Callback-Funktion folgende Schritte aus:
    1. Rufen Sie XRSession.requestAnimationFrame() noch einmal an.
    2. Stell dir die Pose des Zuschauers vor.
    3. Übergeben Sie ('bind') den WebGLFramebuffer von XRWebGLLayer an WebGLRenderingContext.
    4. Iterieren Sie über jedes XRView-Objekt, wobei Sie seine XRViewport aus dem XRWebGLLayer abrufen und an das WebGLRenderingContext übergeben.
    5. Zeichnen Sie etwas im Framebuffer.

Im weiteren Verlauf dieses Artikels werden Schritt 1 und Teil von Schritt 2 beschrieben, nämlich das Einrichten und Aufrufen von XRFrameRequestCallback. Die übrigen Elemente von Schritt 2 werden in Teil II behandelt.

Das XRFrameRequestCallback

Die XRFrameRequestCallback wird von Ihnen definiert. Es werden zwei Parameter verwendet: eine DOMHighResTimeStamp- und eine XRFrame-Instanz. Das XRFrame-Objekt stellt die Informationen bereit, die zum Rendern eines einzelnen Frames in der Anzeige erforderlich sind. Das Argument DOMHighResTimeStamp ist für die zukünftige Verwendung vorgesehen.

Bevor ich etwas anderes mache, fordere ich den nächsten Animationsframe an. Wie bereits erwähnt, wird die Zeitdauer von Frames vom User-Agent auf der Grundlage der zugrunde liegenden Hardware bestimmt. Wenn zuerst der nächste Frame angefordert wird, wird die Frameschleife fortgesetzt, wenn während des Callbacks ein Fehler ausgegeben wird.

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

Jetzt ist es an der Zeit, etwas für die Zuschauer zu zeichnen. Das ist eine Diskussion für Teil II. Bevor wir dorthin gehen, möchte ich Ihnen zeigen, wie man eine Übung beendet.

Sitzung beenden

Eine immersive Sitzung kann aus verschiedenen Gründen beendet werden, z. B. mit Ihrem eigenen Code durch einen Aufruf von XRSession.end(). Andere Ursachen können beispielsweise die Trennung des Headsets oder die Steuerung durch eine andere Anwendung sein. Aus diesem Grund sollte eine Anwendung, die sich einwandfrei verhält, das Ereignis end überwachen. Verwerfen Sie in diesem Fall die Sitzung und die zugehörigen Renderingobjekte. Eine beendete immersive Sitzung kann nicht fortgesetzt werden. Damit ich wieder in den immersiven Modus versetzt werden kann, muss die App eine neue Sitzung starten.

Aus dem Abschnitt Eine Sitzung aufrufen erfahren Sie, dass ich während der Einrichtung einen onend-Event-Handler hinzugefügt habe.

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

Stellen Sie im Event-Handler den Status der App wieder her, bevor der Nutzer eine Sitzung betreten hat.

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

Fazit

Ich habe nicht alles erklärt, was Sie zum Schreiben einer Web XR- oder AR-Anwendung brauchen. Hoffentlich haben Sie genug, um den Code selbst zu verstehen und zu experimentieren. Im nächsten Artikel erkläre ich die Frame-Schleife, in der Inhalte auf den Bildschirm gezogen werden.

Foto von JESHOOTS.COM bei Unsplash