Willkommen im immersiven Web

Das immersive Web ist eine virtuelle Welt, die über den Browser gehostet wird. Diese gesamte Virtual-Reality-Erfahrung wurde im Browser oder in VR-fähigen Headsets angezeigt.

Joe Medley
Joe Medley

Das immersive Web ist eine virtuelle Welt, die über den Browser gehostet wird. Das gilt für vollständige Virtual-Reality-Inhalte (VR), die im Browser oder in VR-fähigen Headsets wie Google Daydream, Oculus Rift, Samsung Gear VR, HTC Vive und Windows Mixed Reality angezeigt werden, sowie für Augmented-Reality-Inhalte, die für AR-fähige Mobilgeräte entwickelt wurden.

Obwohl wir zwei Begriffe zur Beschreibung immersiver Erlebnisse verwenden, sollten sie als ein Spektrum von der vollständigen Realität bis zu einer vollständig immersiven VR-Umgebung betrachtet werden, die verschiedene AR-Ebenen dazwischen umfasst.

Beispiele für immersive Inhalte:

  • Immersive 360°-Videos
  • Herkömmliche 2D- (oder 3D-)Videos in einer immersiven Umgebung
  • Datenvisualisierung
  • Onlineshopping
  • Kunst
  • Etwas Cooles, an das noch niemand gedacht hat

Wie komme ich dorthin?

Das immersive Web ist seit fast einem Jahr in einer rudimentären Form verfügbar. Dazu wurde die WebVR 1.1 API verwendet, die seit Chrome 62 in einem Ursprungstest verfügbar ist. Diese API wird auch von Firefox und Edge sowie einem Polyfill für Safari unterstützt.

Aber es ist an der Zeit, weiterzumachen.

Der Ursprungstest endete am 24. Juli 2018 und die Spezifikation wurde durch die WebXR Device API und einen neuen Ursprungstest ersetzt.

Was ist mit WebVR 1.1 passiert?

Wir haben viel über WebVR 1.1 gelernt, aber mit der Zeit wurde deutlich, dass einige größere Änderungen erforderlich waren, um die Arten von Anwendungen zu unterstützen, die Entwickler erstellen möchten. Die vollständige Liste der Erkenntnisse ist zu lang, um sie hier zu erwähnen. Sie umfasst jedoch Probleme wie die explizite Verknüpfung der API mit dem Haupt-JavaScript-Thread, zu viele Möglichkeiten für Entwickler, offensichtlich falsche Konfigurationen einzurichten, und gängige Verwendungen wie das magische Fenster, das eher eine Nebenwirkung als eine beabsichtigte Funktion ist. (Magic Window ist eine Methode, mit der sich immersive Inhalte ohne Headset ansehen lassen. Dabei rendert die App eine einzelne Ansicht basierend auf dem Orientierungssensor des Geräts.)

Das neue Design ermöglicht einfachere Implementierungen und große Leistungsverbesserungen. Gleichzeitig kamen AR und andere Anwendungsfälle auf und es wurde wichtig, dass die API erweiterbar ist, um diese in Zukunft zu unterstützen.

Die WebXR Device API wurde unter Berücksichtigung dieser erweiterten Anwendungsfälle entwickelt und benannt und bietet einen besseren Weg in die Zukunft. Implementierungen von WebVR haben sich verpflichtet, zur WebXR Device API zu migrieren.

Was ist die WebXR Device API?

Wie die WebVR-Spezifikation zuvor ist die WebXR Device API ein Produkt der Immersive Web Community Group, zu der unter anderem Entwickler von Google, Microsoft und Mozilla gehören. Das „X“ in XR ist eine Art algebraische Variable, die für alles im Spektrum der immersiven Erlebnisse steht. Sie ist im bereits erwähnten Ursprungstest sowie über eine Polyfill-Lösung verfügbar.

Als dieser Artikel ursprünglich während der Betaphase von Chrome 67 veröffentlicht wurde, waren nur VR-Funktionen aktiviert. Augmented Reality ist in Chrome 69 verfügbar. Weitere Informationen finden Sie unter Augmented Reality für das Web.

Diese neue API hat noch mehr zu bieten, als in einem Artikel wie diesem beschrieben werden kann. Ich möchte Ihnen genug Informationen geben, damit Sie die WebXR-Beispiele besser verstehen können. Weitere Informationen finden Sie sowohl in der ursprünglichen Erklärung als auch in unserem Leitfaden für Early Adopter des immersiven Webs. Im Verlauf des Ursprungstests werde ich die zweite Option erweitern. Sie können gerne Probleme melden oder Pull-Anfragen senden.

In diesem Artikel geht es um das Starten, Beenden und Ausführen einer XR-Sitzung sowie über einige Grundlagen der Verarbeitung von Eingaben.

Ich werde nicht darauf eingehen, wie AR-/VR-Inhalte auf dem Bildschirm dargestellt werden. Die WebXR Device API bietet keine Bildrenderingfunktionen. Es liegt ganz bei dir. Das Zeichnen erfolgt mit WebGL-APIs. Das ist möglich, wenn Sie wirklich ehrgeizig sind. Wir empfehlen jedoch die Verwendung eines Frameworks. Für die immersiven Webbeispiele wird eins verwendet, das speziell für die Demos mit dem Namen Cottontail erstellt wurde. Three.js unterstützt WebXR seit Mai. Ich habe nichts über A-Frame gehört.

App starten und ausführen

Der grundlegende Ablauf sieht so aus:

  1. XR-Gerät anfordern
  2. Wenn eine XR-Sitzung verfügbar ist, beantragen Sie eine solche. Wenn Sie möchten, dass der Nutzer sein Smartphone in ein Headset steckt, wird dies als immersive Sitzung bezeichnet und erfordert eine Nutzergeste, um sie zu starten.
  3. Verwenden Sie die Sitzung, um einen Rendering-Loop mit 60 Bildframes pro Sekunde auszuführen. Zeichnen Sie in jedem Frame die entsprechenden Inhalte auf den Bildschirm.
  4. Führen Sie den Rendering-Loop so lange aus, bis der Nutzer das Programm beendet.
  5. Beenden Sie die XR-Sitzung.

Sehen wir uns das genauer an und fügen etwas Code hinzu. Mit dem, was ich Ihnen gleich zeige, können Sie keine App ausführen. Aber wie gesagt, das soll nur einen Eindruck vermitteln.

XR-Gerät anfordern

Hier sehen Sie den Standardcode für die Featureerkennung. Sie könnten das in einer Funktion mit dem Namen checkForXR() einschließen.

Wenn Sie keine immersive Sitzung verwenden, können Sie die Funktion nicht bewerben und keine Nutzergeste abfragen, sondern direkt eine Sitzung anfordern. Für eine immersive Sitzung ist ein Headset erforderlich. Bei einer nicht immersiven Sitzung werden Inhalte einfach auf dem Gerätebildschirm angezeigt. An Ersteres denken die meisten Menschen, wenn sie von Virtual Reality oder Augmented Reality sprechen. Letzteres wird manchmal als „magisches Fenster“ bezeichnet.

if (navigator.xr) {
    navigator.xr.requestDevice()
    .then(xrDevice => {
    // Advertise the AR/VR functionality to get a user gesture.
    })
    .catch(err => {
    if (err.name === 'NotFoundError') {
        // No XRDevices available.
        console.error('No XR devices available:', err);
    } else {
        // An error occurred while requesting an XRDevice.
        console.error('Requesting XR device failed:', err);
    }
    })
} else{
    console.log("This browser does not support the WebXR API.");
}

XR-Sitzung anfordern

Nachdem wir unser Gerät und die Nutzergeste haben, ist es an der Zeit, eine Sitzung zu starten. Zum Erstellen einer Sitzung benötigt der Browser einen Canvas, auf dem er zeichnen kann.

xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
    // The immersive option is optional for non-immersive sessions; the value
    //   defaults to false.
    immersive: false,
    outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Use a WebGL context as a base layer.
    xrSession.baseLayer = new XRWebGLLayer(session, gl);
    // Start the render loop
})

Renderschleife ausführen

Der Code für diesen Schritt ist etwas unübersichtlich. Um das zu verdeutlichen, werde ich Ihnen gleich eine Reihe von Begriffen nennen. Wenn Sie sich den endgültigen Code ansehen möchten, springen Sie vor und kehren Sie dann zurück, um die vollständige Erklärung zu sehen. Vieles lässt sich vielleicht nicht ableiten.

Der grundlegende Ablauf eines Rendering-Loops sieht so aus:

  1. Animationsframe anfordern
  2. Position des Geräts abfragen
  3. Inhalte an der Position des Geräts zeichnen
  4. Führen Sie die für die Eingabegeräte erforderlichen Arbeiten aus.
  5. Wiederholen Sie den Vorgang 60 Mal pro Sekunde, bis sich der Nutzer entscheidet, den Vorgang zu beenden.

Präsentationsframe anfordern

Das Wort „Frame“ hat im Web XR-Kontext mehrere Bedeutungen. Der erste ist der Referenzrahmen, der definiert, wo der Ursprung des Koordinatensystems berechnet wird und was mit diesem Ursprung passiert, wenn sich das Gerät bewegt. (Bleibt die Ansicht gleich, wenn sich der Nutzer bewegt, oder verschiebt sie sich wie im echten Leben?)

Der zweite Frame-Typ ist der Präsentationsframe, der durch ein XRFrame-Objekt dargestellt wird. Dieses Objekt enthält die Informationen, die zum Rendern eines einzelnen Frames einer AR-/VR-Szene auf dem Gerät erforderlich sind. Das ist etwas verwirrend, da ein Präsentationsframe durch Aufrufen von requestAnimationFrame() abgerufen wird. Dadurch ist es mit window.requestAnimationFrame() kompatibel.

Bevor ich Ihnen noch mehr zu verdauen gebe, möchte ich Ihnen etwas Code zeigen. Das folgende Beispiel zeigt, wie die Renderingschleife gestartet und aufrechterhalten wird. Beachten Sie die doppelte Verwendung des Wortrahmens. Beachten Sie den rekursiven Aufruf von requestAnimationFrame(). Diese Funktion wird 60 Mal pro Sekunde aufgerufen.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    // Process the frame.
    xrFrame.session.requestAnimationFrame(onFrame);
    }
});

Posen

Bevor Sie etwas auf dem Bildschirm zeichnen können, müssen Sie wissen, wo das Display gerichtet ist, und Sie benötigen Zugriff auf den Bildschirm. Im Allgemeinen wird die Position und Ausrichtung eines Objekts in AR/VR als Pose bezeichnet. Sowohl Zuschauer als auch Eingabegeräte haben eine Pose. (Eingabegeräte werden später behandelt.) Sowohl Viewer- als auch Eingabegeräte-Positionen sind als 4:4-Matrix definiert, die in einer Float32Array in Spaltenhauptreihenfolge gespeichert ist. Die Haltung des Betrachters wird durch Aufrufen von XRFrame.getDevicePose() für das aktuelle Animationsframe-Objekt abgerufen. Prüfen Sie immer, ob Sie eine Pose zurückbekommen haben. Wenn etwas schiefgelaufen ist, möchten Sie nicht auf den Bildschirm zeichnen.

let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
    // Draw something to the screen.
}

Aufrufe

Nachdem wir die Pose überprüft haben, ist es Zeit, etwas zu zeichnen. Das Objekt, auf das Sie zeichnen, wird als Ansicht (XRView) bezeichnet. Hier kommt der Sitzungstyp ins Spiel. Ansichten werden aus dem XRFrame-Objekt als Array abgerufen. Wenn Sie sich in einer Sitzung ohne immersive Ansicht befinden, enthält das Array eine Ansicht. Wenn Sie sich in einer immersiven Sitzung befinden, hat das Array zwei, eine für jedes Auge.

for (let view of xrFrame.views) {
    // Draw something to the screen.
}

Das ist ein wichtiger Unterschied zwischen WebXR und anderen immersiven Systemen. Es mag sinnlos erscheinen, eine Ansicht zu durchlaufen. So haben Sie jedoch die Möglichkeit, einen einzigen Renderingpfad für eine Vielzahl von Geräten zu haben.

Die gesamte Rendering-Schleife

Wenn ich das alles zusammenfüge, erhalte ich den folgenden Code. Ich habe einen Platzhalter für die Eingabegeräte gelassen, die ich in einem späteren Abschnitt behandeln werde.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    let pose = xrFrame.getDevicePose(xrFrameOfRef);
    if (pose) {
        for (let view of xrFrame.views) {
        // Draw something to the screen.
        }
    }
    // Input device code will go here.
    frame.session.requestAnimationFrame(onFrame);
    }
}

XR-Sitzung beenden

Eine XR-Sitzung kann aus verschiedenen Gründen beendet werden, z. B. durch einen Aufruf von XRSession.end() in Ihrem eigenen 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 Endereignis überwachen und die Sitzungs- und Renderer-Objekte verwerfen, wenn es eintritt. Eine beendete XR-Sitzung kann nicht fortgesetzt werden.

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('end', onSessionEnd);
});

// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
    xrSession = null;

    // Ending the session stops executing callbacks passed to the XRSession's
    // requestAnimationFrame(). To continue rendering, use the window's
    // requestAnimationFrame() function.
    window.requestAnimationFrame(onDrawFrame);
}

Wie funktioniert die Interaktion?

Wie bei der Lebensdauer der Anwendung möchte ich Ihnen nur einen kleinen Einblick in die Interaktion mit Objekten in AR oder VR geben.

Die WebXR Device API verwendet einen „Point-and-Click“-Ansatz für die Nutzereingabe. Bei diesem Ansatz hat jede Eingabequelle einen definierten Zeigerstrahl, der angibt, worauf ein Eingabegerät zeigt, und Ereignisse, die anzeigen, wann etwas ausgewählt wurde. Ihre App zeichnet den Zeigerstrahl und zeigt an, worauf er zeigt. Wenn der Nutzer auf das Eingabegerät klickt, werden die Ereignisse ausgelöst – insbesondere select, selectStart und selectEnd. Ihre App erkennt, was angeklickt wurde, und reagiert entsprechend.

Eingabegerät und Cursorstrahl

Für Nutzer ist der Cursorstrahl nur eine schwache Linie zwischen dem Controller und dem Objekt, auf das er zeigt. Ihre App muss sie aber zeichnen. Dazu wird die Position des Eingabegeräts ermittelt und eine Linie von seiner Position zu einem Objekt im AR-/VR-Raum gezogen. Dieser Prozess sieht ungefähr so aus:

let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
    let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
    if (!inputPose) {
    continue;
    }
    if (inputPose.gripMatrix) {
    // Render a virtual version of the input device
    //   at the correct position and orientation.
    }
    if (inputPose.pointerMatrix) {
    // Draw a ray from the gripMatrix to the pointerMatrix.
    }
}

Dies ist eine stark reduzierte Version des Beispiels für das Eingabe-Tracking der Immersive Web Community Group. Wie beim Frame-Rendering liegt es auch hier in Ihrer Verantwortung, den Mausstrahl und das Gerät zu zeichnen. Wie bereits erwähnt, muss dieser Code im Rahmen des Rendering-Loops ausgeführt werden.

Elemente im virtuellen Raum auswählen

In AR/VR einfach nur auf Dinge zu zeigen, ist ziemlich nutzlos. Damit Nutzer etwas Nützliches tun können, müssen sie die Möglichkeit haben, Dinge auszuwählen. Die WebXR Device API bietet drei Ereignisse, um auf Nutzerinteraktionen zu reagieren: select, selectStart und selectEnd. Sie haben eine Eigenheit, die ich nicht erwartet hatte: Sie geben nur an, dass auf ein Eingabegerät geklickt wurde. Sie geben nicht an, auf welches Element in der Umgebung geklickt wurde. Event-Handler werden dem Objekt XRSession hinzugefügt, sobald sie verfügbar sind.

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('selectstart', onSelectStart);
    xrSession.addEventListener('selectend', onSelectEnd);
    xrSession.addEventListener('select', onSelect);
});

Dieser Code basiert auf einem Beispiel für die Auswahl von Eingaben, falls Sie mehr Kontext benötigen.

Um herauszufinden, worauf geklickt wurde, verwendest du eine Pose. (Sind Sie überrascht? Das habe ich nicht gedacht.) Die Details dazu sind spezifisch für Ihre App oder das von Ihnen verwendete Framework und gehen daher über den Rahmen dieses Artikels hinaus. Der Ansatz von Cottontail ist im Beispiel für die Eingabeauswahl zu sehen.

function onSelect(ev) {
    let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
    if (!inputPose) {
    return;
    }
    if (inputPose.pointerMatrix) {
    // Figure out what was clicked and respond.
    }
}

Fazit: Nach vorne schauen

Wie bereits erwähnt, wird Augmented Reality voraussichtlich in Chrome 69 eingeführt (in Canary irgendwann im Juni 2018). Dennoch empfehle ich Ihnen, das bisher Gelernte auszuprobieren. Wir brauchen Feedback, um es zu verbessern. Den Fortschritt können Sie auf ChromeStatus.com unter WebXR-Hit-Test verfolgen. Sie können auch WebXR-Anchors folgen, die das Positions-Tracking verbessern.