Willkommen im immersiven Web

Das immersive Web ist eine virtuelle Welt, die über den Browser gehostet wird. Das gesamte Virtual-Reality-Erlebnis erschien im Browser oder über VR-fähige Headsets.

Joe Medley
Joe Medley

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

Auch wenn wir zur Beschreibung immersiver Erlebnisse zwei Begriffe verwenden, sollten sie als ein Spektrum von vollständiger Realität bis zu einer vollständig immersiven VR-Umgebung mit verschiedenen AR-Ebenen betrachtet werden.

Beispiele für immersive Erfahrungen:

  • Immersive 360°-Videos
  • Traditionelle 2D-Videos (oder 3D-Videos) in einer eindrucksvollen Umgebung
  • Datenvisualisierung
  • Haushaltswaren
  • Kunst
  • Etwas Cooles, an das noch niemand gedacht hat

Wie komme ich dorthin?

Das immersive Web ist jetzt seit fast einem Jahr in embryonischer Form verfügbar. Dazu wurde die WebVR 1.1 API verwendet, die seit Chrome 62 im Rahmen eines Ursprungstests verfügbar ist. Diese API wird auch von Firefox und Edge sowie einem Polyfill für Safari unterstützt.

Aber es ist 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 aus WebVR 1.1 gelernt, aber im Laufe der Zeit wurde deutlich, dass einige wesentliche Änderungen erforderlich waren, um die Arten von Anwendungen zu unterstützen, die Entwickler erstellen möchten. Die vollständige Liste der gewonnenen Erkenntnisse ist zu lang, um hier aufzugehen, 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 häufige Anwendungsfälle wie ein magisches Fenster als Nebeneffekt und nicht als beabsichtigte Funktion. Das Magische Fenster ist eine Technik zur Anzeige immersiver Inhalte ohne Headset. Dabei rendert die App eine einzelne Ansicht basierend auf dem Ausrichtungssensor des Geräts.

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

Die WebXR Device API wurde unter Berücksichtigung dieser erweiterten Anwendungsfälle entwickelt und benannt und bietet eine bessere Lösung. Implementatoren von WebVR haben sich verpflichtet, zur WebXR Device API zu migrieren.

Was ist die WebXR Device API?

Wie die WebVR-Spezifikation vorher ist auch die WebXR Device API ein Produkt der Immersive Web Community Group, zu der Beitragende von Google, Microsoft, Mozilla und anderen gehören. Das „X“ in XR ist als algebraische Variable gedacht, die für alles im Spektrum immersiver Erlebnisse steht. Sie ist im zuvor genannten Ursprungstest sowie über einen polyfill verfügbar.

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

Mehr über diese neue API als in einem Artikel wie diesem zu finden. Ich möchte Ihnen ausreichend Informationen geben, damit Sie die WebXR-Beispiele auswerten können. Weitere Informationen finden Sie sowohl in der ursprünglichen Erläuterung als auch in unserem Erstnutzer-Leitfaden für immersive Web. Im Verlauf des Ursprungstests erweitere ich Letzteres. Sie können Probleme melden oder Pull-Anfragen senden.

In diesem Artikel werden das Starten, Beenden und Ausführen einer XR-Sitzung sowie einige Grundlagen zur Verarbeitung von Eingaben erläutert.

Ich gehe nicht darauf ein, wie AR-/VR-Inhalte auf den Bildschirm gezeichnet werden. Die WebXR Device API bietet keine Bildrenderingfunktionen. Das liegt ganz bei Ihnen. Das Zeichnen erfolgt mithilfe von WebGL APIs. Das ist nur möglich, wenn du wirklich ehrgeizig bist. Wir empfehlen jedoch die Verwendung eines Frameworks. Für die immersiven Webbeispiele wird ein speziell für die Demos erstelltes Beispiel Cottontail verwendet. Three.js unterstützt WebXR seit Mai. Ich habe noch nichts über A-Frame gehört.

App starten und ausführen

Der grundlegende Prozess sieht so aus:

  1. Fordern Sie ein XR-Gerät an.
  2. Fordern Sie eine XR-Sitzung an, sofern verfügbar. Wenn der Nutzer sein Smartphone in ein Headset einsetzen soll, spricht man von einer immersiven Sitzung, für die eine Nutzergeste erforderlich ist.
  3. Führen Sie in dieser Sitzung eine Renderingschleife aus, die 60 Bildframes pro Sekunde liefert. Zeichnen Sie in jedem Frame entsprechende Inhalte auf dem Bildschirm.
  4. Führen Sie die Renderingschleife aus, bis der Nutzer die Wiedergabe beendet.
  5. Beenden Sie die XR-Sitzung.

Schauen wir uns das etwas genauer an und fügen Code hinzu. Auf dem, was ich Ihnen gleich zeige, können Sie keine App ausführen. Aber auch hier geht es darum, einen Eindruck davon zu vermitteln.

XR-Gerät anfordern

Hier erkennen Sie den Standardcode zur Funktionserkennung. Sie könnten dies in eine Funktion mit dem Namen checkForXR() verpacken.

Wenn du keine immersive Sitzung verwendest, kannst du die Werbung für die Funktion und eine Nutzergeste überspringen und direkt eine Sitzung anfordern. Eine immersive Sitzung erfordert ein Headset. Bei einer Sitzung werden die Inhalte einfach auf dem Bildschirm des Geräts angezeigt. An Virtual Reality oder Augmented Reality denken die meisten an die erstere. 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

Da wir nun unser Gerät und die Geste für den Nutzer haben, ist es Zeit für eine Sitzung. Zum Erstellen einer Sitzung benötigt der Browser ein Canvas, auf dem er gezeichnet werden 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
})

Renderingschleife ausführen

Der Code für diesen Schritt entwirft etwas. Um es zu entwirren, werde ich Ihnen gleich ein paar Wörter werfen. Wenn Sie einen Blick auf den endgültigen Code werfen möchten, überspringen Sie einen kurzen Blick und kehren Sie dann zur vollständigen Erklärung zurück. Es gibt einiges, das Sie sich vielleicht nicht ableiten lassen.

Der grundlegende Prozess für eine Rendering-Schleife sieht so aus:

  1. Fordern Sie einen Animationsframe an.
  2. Abfrage der Position des Geräts.
  3. Zeichnen Sie Inhalte entsprechend seiner Position auf dem Gerät.
  4. Erledigen Sie die an den Eingabegeräten erforderlichen Arbeiten.
  5. Wiederholen Sie diesen Vorgang 60 Mal pro Sekunde, bis der Nutzer die App verlassen möchte.

Präsentationsframe anfordern

Das Wort „Frame“ hat im Web XR-Kontext mehrere Bedeutungen. Der erste ist der Referenzrahmen, der definiert, von wo aus 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 ändert 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 für das 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 Sie weiter verabreden kann, gebe ich Ihnen noch ein paar Code. 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, müssen Sie wissen, worauf das Anzeigegerät zeigt, und Sie benötigen Zugriff auf den Bildschirm. Im Allgemeinen wird die Position und Ausrichtung eines Objekts in AR/VR als Pose bezeichnet. Sowohl Betrachter als auch Eingabegeräte haben eine Pose. (Eingabegeräte werden später behandelt.) Sowohl die Positionen des Betrachters als auch des Eingabegeräts sind als 4 × 4-Matrix definiert, die in einer Float32Array in der Spaltenhauptreihenfolge gespeichert ist. Um die Position des Zuschauers zu ermitteln, rufen Sie XRFrame.getDevicePose() für das aktuelle Animationsframe-Objekt auf. Testen Sie immer, um zu sehen, ob Sie wieder in Pose zurückstehen. Wenn etwas schiefgelaufen ist, wollen Sie nicht auf dem Bildschirm zeichnen.

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

Aufrufe

Nachdem du deine Pose überprüft hast, ist es an der Zeit, etwas zu zeichnen. Das Objekt, zu dem 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 nicht-komplexen Sitzung befinden, hat das Array eine Ansicht. Wenn Sie sich in einer immersiven Sitzung befinden, hat das Array zwei, eines für jedes Auge.

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

Dies ist ein wichtiger Unterschied zwischen WebXR und anderen immersiven Systemen. Auch wenn es sinnlos erscheint, durch eine Ansicht zu iterieren, können Sie so einen einzigen Rendering-Pfad für eine Vielzahl von Geräten haben.

Die gesamte Renderingschleife

Wenn ich das alles zusammenfasse, erhalte ich den Code unten. Ich habe einen Platzhalter für die Eingabegeräte gelassen, auf den ich später noch eingehen 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. 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 gut verhält, das Endereignis überwachen und beim Eintreten die Sitzungs- und Rendererobjekte verwerfen. Eine einmal 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 App möchte ich Ihnen einen Vorstellung davon geben, wie Sie mit Objekten in AR oder VR interagieren.

Die WebXR Device API verfolgt bei Nutzereingaben einen Point-and-Click-Ansatz. Bei diesem Ansatz verfügt jede Eingabequelle über einen definierten Zeigerstrahl, der angibt, wohin ein Eingabegerät zeigt, und über Ereignisse, die anzeigen, wann etwas ausgewählt wurde. Ihre App zeichnet den Zeigerstrahl und zeigt an, wohin er zeigt. Wenn der Nutzer auf das Eingabegerät klickt, werden die Ereignisse select, selectStart und selectEnd ausgelöst. Ihre App erkennt, was angeklickt wurde, und reagiert entsprechend.

Das Eingabegerät und der Zeigerstrahl

Für die Nutzer ist der Zeigerstrahl nur eine schwache Linie zwischen dem Controller und dem Objekt, auf das sie zeigen. Ihre App muss es jedoch zeichnen. Dabei wird die Position des Eingabegeräts ermittelt und eine Linie von seinem Standort zu einem Objekt im AR/VR-Bereich gezogen. Dieser Vorgang 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 reduzierte Version des Beispiels für das Eingabe-Tracking aus der Gruppe der Immersive Web Community. Wie beim Frame-Rendering liegt die Zeichnung des Zeigestrahls und des Geräts ganz bei Ihnen. Wie bereits erwähnt, muss dieser Code als Teil der Renderingschleife ausgeführt werden.

Elemente im virtuellen Raum auswählen

In AR/VR reicht es nicht aus, einfach nur auf Dinge zu zeigen. Für etwas Nützliches brauchen Nutzende die Möglichkeit, Dinge auszuwählen. Die WebXR Device API bietet drei Ereignisse für die Reaktion auf Nutzerinteraktionen: select, selectStart und selectEnd. Es gibt eine kleine Eigendynamik, die ich nicht erwartet hatte: Sie erfahren nur, dass ein Eingabegerät angeklickt wurde. Sie sagen nicht aus, auf welches Element in der Umgebung geklickt wurde. Event-Handler werden dem XRSession-Objekt hinzugefügt und sollten hinzugefügt werden, 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 Eingabeauswahl, falls Sie mehr Kontext benötigen.

Um herauszufinden, worauf geklickt wurde, verwenden Sie eine Pose. (Sind Sie überrascht? Das hätte ich nicht gedacht.) Die Details sind spezifisch für Ihre App oder das von Ihnen verwendete Framework und somit über den Umfang dieses Artikels hinaus. Der Ansatz von Cottontail wird im Beispiel für die Eingabeauswahl verwendet.

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: Blick in die Zukunft

Wie bereits erwähnt, wird Augmented Reality für Chrome 69 erwartet (Canary-Version im Juni 2018). Trotzdem möchte ich Sie ermutigen, das, was wir bisher gelernt haben, auszuprobieren. Wir brauchen Feedback, um es zu verbessern. Beobachte den Fortschritt auf ChromeStatus.com für WebXR Hit Test. Sie können auch WebXR-Ankern folgen, um das Posen-Tracking zu verbessern.