Virtual Reality – jetzt im Web

Hier finden Sie einige Grundlagen, die Sie auf ein breites Spektrum an immersiven Erlebnissen vorbereiten: Virtual Reality, Augmented Reality und alles dazwischen.

Joe Medley
Joe Medley

Mit Chrome 79 wurde das Web noch immersiver. Die WebXR Device API ermöglicht Virtual Reality, während Augmented Reality in Chrome 81 unterstützt wird. Ein Update der GamePad API erweitert die erweiterte Verwendung der Steuerelemente auf VR. Bald werden auch andere Browser diese Spezifikationen unterstützen, darunter Firefox Reality, Oculus Browser, Edge und der Helio-Browser von Magic Leap.

Dieser Artikel ist der erste einer Reihe zum immersiven Web. Diese Ratenzahlung umfasst die Einrichtung einer einfachen WebXR-Anwendung sowie das Aufrufen und Beenden einer XR-Sitzung. In späteren Artikeln werden der Frame-Loop (das Arbeitspferd der WebXR-Umgebung), 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 erwähne, sowohl für AR als auch für VR.

Was ist das immersive Web?

Wir verwenden zwei Begriffe, um immersive Erlebnisse zu beschreiben: Augmented Reality und Virtual Reality. Viele betrachten sie jedoch als ein Spektrum von vollständiger Realität bis hin zu vollständiger Virtualität, mit verschiedenen Graden der Immersion dazwischen. Das „X“ in XR soll dieses Denken widerspiegeln und ist eine Art algebraische Variable, die für alles im Spektrum der immersiven Erlebnisse steht.

Ein Diagramm, das das Spektrum der visuellen Erfahrungen von der vollständigen Realität bis hin zur völligen Immersion veranschaulicht.
Das Spektrum der immersiven Erlebnisse

Beispiele für immersive Inhalte:

  • Spiele
  • 360°-Videos
  • Herkömmliche 2D- (oder 3D-)Videos in einer immersiven Umgebung
  • Hauskauf
  • Produkte in Ihrem Zuhause ansehen, bevor Sie sie kaufen
  • Immersive Kunst
  • Etwas Cooles, an das noch niemand gedacht hat

Konzepte und Verwendung

Ich erkläre Ihnen einige Grundlagen zur Verwendung der WebXR Device API. Wenn Sie mehr dazu erfahren möchten, sehen Sie sich die WebXR-Beispiele der Immersive Web Working Group oder die wachsenden Referenzmaterialien der MDN an. Wenn Sie mit früheren Versionen der WebXR Device API vertraut sind, sollten Sie sich alle diese Informationen ansehen. Es gab Änderungen.

Der Code in diesem Artikel basiert auf dem einfachen Beispiel der Immersive Web Working Group (Demo, Quellcode), wurde aber zugunsten von Klarheit und Einfachheit bearbeitet.

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 im Fokus sein, bevor sie sensible Daten vom Nutzer anfordern kann. Webseiten oder Apps müssen über HTTPS bereitgestellt werden. Die API selbst ist darauf ausgelegt, die von Sensoren und Kameras erfassten Informationen zu schützen, die für ihre Funktion erforderlich sind.

Sitzung anfordern

Für den Eintritt in eine XR-Sitzung ist eine Nutzergeste erforderlich. Dazu kannst du die Feature-Erkennung verwenden, um über navigator.xr nach XRSystem zu suchen und XRSystem.isSessionSupported() aufzurufen. In Chrome-Version 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 Teaserinhalte verwendet. Das Beispiel Immersive AR Session 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, mit der 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 und dann zu einer XRSession-Instanz verschoben. In früheren Versionen der API musste ein Script ein Gerät anfordern, bevor eine Sitzung angefordert werden konnte. Jetzt wird das Gerät implizit abgerufen.

Sitzung starten

Nachdem ich eine Sitzung erhalten habe, muss ich sie starten und betreten. Aber zuerst muss ich ein paar Dinge einrichten. Eine Sitzung benötigt einen onend-Ereignis-Handler, 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 meine 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, auf die ich mich beziehen kann. Dazu erstelle ich eine Instanz von XRWebGLLayer. Ich verknüpfe ihn mit dem Canvas, indem ich XRSession.updateRenderState() aufrufe.

Sobald ich in einer Sitzung bin, muss ich wissen, wo sich die Dinge in der virtuellen Realität befinden. Ich benötige einen Referenzbereich. Bei einem 'local-floor'-Referenzraum befindet sich der Ursprung in der Nähe des Betrachters, die Y-Achse hat auf Bodenhöhe den Wert 0 und soll sich nicht bewegen. Es gibt andere Arten von Referenzräumen, aber das ist ein komplexeres Thema, als ich hier eingehen kann. Ich speichere den Referenzbereich in einer Variablen, da ich ihn benötige, wenn ich auf dem Bildschirm zeichne.

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 Referenzraum erhalten habe, rufe ich XRSession.requestAnimationFrame() auf. Dies ist der Beginn der Präsentation virtueller Inhalte, die im Frame-Loop erfolgen.

Frame-Schleife ausführen

Die Frame-Schleife ist eine vom User-Agent gesteuerte Endlosschleife, bei der Inhalte wiederholt auf dem Bildschirm dargestellt werden. Inhalte werden in diskreten Blöcken gezeichnet, sogenannten Frames. Die Abfolge der Frames erzeugt die Illusion von Bewegung. Bei VR-Anwendungen können die Bilder pro Sekunde zwischen 60 und 144 liegen. AR für Android läuft mit 30 Bildern pro Sekunde. Ihr Code sollte keine bestimmte Framerate annehmen.

Der grundlegende Ablauf der Frame-Schleife ist:

  1. Rufen Sie einfach XRSession.requestAnimationFrame() an. Als Antwort ruft der User-Agent die XRFrameRequestCallback auf, die von Ihnen definiert wird.
  2. Informationen zur Callback-Funktion:
    1. Rufen Sie XRSession.requestAnimationFrame() noch einmal an.
    2. Die Körperhaltung des Betrachters
    3. Übergeben (binden, „bind“) Sie die WebGLFramebuffer von der XRWebGLLayer an die WebGLRenderingContext.
    4. Durchlaufen Sie jedes XRView-Objekt, rufen Sie dessen 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, also die Einrichtung und der Aufruf der XRFrameRequestCallback. Die verbleibenden Punkte von Schritt 2 werden in Teil II behandelt.

XRFrameRequestCallback

Die XRFrameRequestCallback wird von Ihnen definiert. Er hat zwei Parameter: eine DOMHighResTimeStamp und eine XRFrame-Instanz. Das XRFrame-Objekt stellt die Informationen bereit, 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 mache, fordere ich den nächsten Animationsframe an. Wie bereits erwähnt, wird das Timing der Frames vom User-Agent basierend auf der zugrunde liegenden Hardware bestimmt. Wenn du zuerst den nächsten Frame anforderst, wird die Frame-Schleife fortgesetzt, wenn während des Callbacks ein Fehler auftritt.

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

An dieser Stelle ist es an der Zeit, etwas für den Zuschauer zu zeichnen. Das ist ein Thema für Teil II. Aber zuerst zeige ich Ihnen, wie Sie eine Sitzung beenden.

Sitzung beenden

Eine immersive Sitzung kann aus verschiedenen Gründen enden, z. B. durch einen Aufruf von XRSession.end() in Ihrem Code. Mögliche weitere Ursachen sind eine Unterbrechung der Verbindung zum Headset oder die Übernahme der Kontrolle durch eine andere Anwendung. Aus diesem Grund sollte eine ordnungsgemäß funktionierende Anwendung das Ereignis end überwachen. Verwerfen Sie in diesem Fall die Sitzung und die zugehörigen Rendering-Objekte. Eine beendete immersive Sitzung kann nicht fortgesetzt werden. Damit ich die immersive Erfahrung wieder nutzen kann, muss meine App eine neue Sitzung starten.

Beim Aufrufen einer Sitzung habe ich bei der Einrichtung einen onend-Event-Handler hinzugefügt.

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

Stellen Sie im Ereignishandler den Zustand der App wieder her, bevor der Nutzer eine Sitzung gestartet 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 benötigen. Ich hoffe, ich konnte Ihnen genug Informationen geben, damit Sie den Code selbst verstehen und damit experimentieren können. Im nächsten Artikel erkläre ich den Frame-Loop, bei dem Inhalte auf dem Bildschirm dargestellt werden.

Foto von JESHOOTS.COM bei Unsplash