Bienvenue dans le Web immersif

Le Web immersif désigne des expériences dans le monde virtuel hébergées par le navigateur. L'ensemble de ces expériences de réalité virtuelle sont mis en avant dans le navigateur ou dans les casques compatibles de réalité virtuelle.

Joe Medley
Joe Medley

Le Web immersif désigne des expériences dans le monde virtuel hébergées par le navigateur. Cela couvre l'intégralité des expériences de réalité virtuelle (RV) affichées dans le navigateur ou dans les casques compatibles de réalité virtuelle tels que les casques Daydream, Oculus Rift, Samsung Gear VR, HTC Vive et Windows en réalité virtuelle, ainsi que les expériences de réalité augmentée développées pour les appareils mobiles compatibles avec la RA.

Bien que nous utilisions deux termes pour décrire les expériences immersives, elles doivent être considérées comme un spectre allant de la réalité complète à un environnement RV complètement immersif, avec différents niveaux de RA entre les deux.

Voici quelques exemples d'expériences immersives:

  • Vidéos immersives à 360°
  • Vidéos 2D (ou 3D) traditionnelles présentées dans un environnement immersif
  • Visualisations des données
  • Shopping à dom
  • Art
  • Quelque chose de cool à quoi personne n'a encore pensé

Comment on y va ?

Le Web immersif est disponible depuis près d'un an sous forme embryonnaire. Pour ce faire, vous avez utilisé l'API WebVR 1.1, qui est disponible en phase d'évaluation depuis Chrome 62. Cette API est également compatible avec Firefox et Edge, ainsi qu'un polyfill pour Safari.

Mais il est temps de passer à autre chose.

La phase d'évaluation a pris fin le 24 juillet 2018 et la spécification a été remplacée par l'API WebXR Device et une nouvelle phase d'évaluation.

Qu'est devenu WebVR 1.1 ?

Nous avons beaucoup appris de WebVR 1.1, mais au fil du temps, il est devenu évident que des modifications majeures étaient nécessaires pour prendre en charge les types d'applications que les développeurs souhaitent créer. La liste complète des leçons apprises est trop longue pour être abordée ici. Elle inclut des problèmes tels que l'association explicite de l'API au thread JavaScript principal, un trop grand nombre de possibilités pour les développeurs de configurer des configurations manifestement incorrectes, ainsi que des utilisations courantes telles que le fait que la fenêtre magique est un effet secondaire plutôt qu'une fonctionnalité intentionnelle. (La fenêtre magique est une technique d'affichage de contenu immersif sans casque, dans laquelle l'application affiche une seule vue en fonction du capteur d'orientation de l'appareil.)

Cette nouvelle interface facilite les implémentations et offre de grandes améliorations des performances. Au même moment, la RA et d'autres cas d'utilisation étaient apparus, et il est devenu important que l'API soit extensible pour les prendre en charge à l'avenir.

L'API WebXR Device a été conçue et nommée en tenant compte de ces cas d'utilisation étendus et offre une meilleure option. Les implémentations de WebVR se sont engagés à migrer vers l'API WebXR Device.

Qu'est-ce que l'API WebXR Device ?

Comme la spécification WebVR précédente, l'API WebXR Device est un produit du Immersive Web Community Group, qui réunit des contributeurs de Google, Microsoft, Mozilla, etc. Le "X" dans XR est destiné à être une sorte de variable algébrique qui correspond à tout élément du spectre des expériences immersives. Il est disponible dans la phase d'évaluation mentionnée précédemment ainsi que via un polyfill.

Lorsque cet article a été publié pour la première fois pendant la période bêta de Chrome 67, seules les fonctionnalités de RV étaient activées. La réalité augmentée est arrivée dans Chrome 69. Pour en savoir plus, consultez l'article Réalité augmentée pour le Web.

Un article comme celui-ci va en apprendre davantage sur cette nouvelle API. Je veux vous donner suffisamment de détails pour commencer à comprendre les exemples WebXR. Pour en savoir plus, consultez l'explication d'origine et notre Guide immersif destiné aux utilisateurs de la première heure sur le Web. Je vais développer ces dernières à mesure que la phase d'évaluation avance. N'hésitez pas à signaler les problèmes que vous rencontrez ou à envoyer des demandes d'extraction.

Dans cet article, je vais vous parler du démarrage, de l'arrêt et de l'exécution d'une session XR, ainsi que de quelques notions de base sur le traitement des entrées.

Je ne vais pas vous expliquer comment dessiner des contenus RA/RV à l'écran. L'API WebXR Device ne fournit pas de fonctionnalités de rendu d'image. La décision vous appartient. Le dessin est réalisé à l'aide des API WebGL. Vous pouvez le faire si vous êtes vraiment ambitieux. Nous vous recommandons toutefois d'utiliser un framework. Les exemples de sites Web immersifs en utilisent un, créé uniquement pour les démonstrations, appelé Cottontail. Three.js est compatible avec WebXR depuis mai. Je n'ai entendu parler de "A-Frame" (A-Frame).

Démarrer et exécuter une application

Le processus de base est le suivant:

  1. Demandez un appareil XR.
  2. Le cas échéant, demandez une session XR. Si vous souhaitez que l'utilisateur place son téléphone dans un casque, cela s'appelle une session immersive et nécessite un geste de l'utilisateur pour y accéder.
  3. Utilisez la session pour exécuter une boucle de rendu fournissant 60 images par seconde. Permet d'afficher le contenu approprié à l'écran dans chaque frame.
  4. Exécutez la boucle de rendu jusqu'à ce que l'utilisateur décide de quitter.
  5. Mettez fin à la session XR.

Examinons cela plus en détail et incluons du code. Vous ne pourrez pas exécuter une application à partir de ce que je vais vous montrer. Mais encore une fois, c'est juste pour vous donner un aperçu.

Demander un appareil XR

Ici, vous reconnaîtrez le code de détection de fonctionnalité standard. Vous pouvez l'encapsuler dans une fonction appelée checkForXR().

Si vous n'utilisez pas de session immersive, vous pouvez passer directement à demander une session sans faire la publicité de la fonctionnalité et obtenir un geste de l'utilisateur. Les sessions immersives nécessitent un casque. Une session non immersive affiche simplement du contenu sur l'écran de l'appareil. La première est ce à quoi la plupart des gens pensent lorsque vous faites référence à la réalité virtuelle ou à la réalité augmentée. Cette dernière est parfois appelée "fenêtre magique".

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.");
}

Demander une session XR

Maintenant que nous avons notre appareil et notre geste utilisateur, il est temps d'obtenir une session. Pour créer une session, le navigateur a besoin d'un canevas sur lequel dessiner.

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
})

Exécuter la boucle de rendu

Le code de cette étape nécessite un peu de démêlage. Pour la démêler, je suis sur le point de vous jeter un tas de mots. Si vous voulez avoir un aperçu du code final, avancez rapidement pour un aperçu rapide, puis revenez pour une explication complète. Il y a beaucoup de choses que vous ne pourrez peut-être pas déduire.

Le processus de base d'une boucle de rendu est le suivant:

  1. Demander un frame d'animation.
  2. Permet de rechercher la position de l'appareil.
  3. Permet de dessiner du contenu à la position de l'appareil en fonction de sa position.
  4. Effectuez les tâches nécessaires pour les périphériques d'entrée.
  5. Répétez l'opération 60 fois par seconde jusqu'à ce que l'utilisateur décide de quitter.

Demander un cadre de présentation

Le mot "frame" a plusieurs significations dans un contexte Web XR. Le premier est le cadre de référence, qui définit l'endroit à partir duquel l'origine du système de coordonnées est calculée et ce qu'il advient de cette origine lorsque l'appareil se déplace. (La vue reste-t-elle la même lorsque l'utilisateur se déplace ou change-t-elle comme dans la réalité ?)

Le deuxième type de cadre est le cadre de présentation, représenté par un objet XRFrame. Cet objet contient les informations nécessaires pour afficher une seule image d'une scène de RA/RV sur l'appareil. C'est un peu déroutant, car un cadre de présentation est récupéré en appelant requestAnimationFrame(). Il est ainsi compatible avec window.requestAnimationFrame().

Avant de vous donner plus de détails, je vais vous proposer du code. L'exemple ci-dessous montre comment la boucle de rendu est démarrée et gérée. Notez la double utilisation du cadre de mots. Notez l'appel récursif à requestAnimationFrame(). Cette fonction sera appelée 60 fois par seconde.

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);
    }
});

Postures

Avant de dessiner quoi que ce soit à l'écran, vous devez savoir où pointe l'appareil d'affichage et vous devez avoir accès à l'écran. En général, la position et l'orientation d'un objet en RA/RV sont appelées "pose". Les lecteurs et les périphériques d'entrée ont une posture. (Je parlerai des périphériques d'entrée plus tard.) Les poses du lecteur et du périphérique d'entrée sont définies comme une matrice 4:4 stockée dans un Float32Array dans l'ordre principal des colonnes. Pour obtenir la pose du spectateur, appelez XRFrame.getDevicePose() sur l'objet frame d'animation actuel. Faites toujours un test pour voir si vous avez repris la pose. Si quelque chose s'est mal passé, vous ne voulez pas dessiner à l'écran.

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

Vues

Après avoir vérifié la posture, il est temps de dessiner quelque chose. L'objet dans lequel vous dessinez s'appelle une vue (XRView). C'est là que le type de session devient important. Les vues sont extraites de l'objet XRFrame sous forme de tableau. Lors d'une session non immersive, le tableau comporte une vue. Si vous êtes dans une session immersive, le tableau en comporte deux, un pour chaque œil.

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

Il s'agit d'une différence importante entre WebXR et les autres systèmes immersifs. Bien qu'il puisse sembler inutile d'effectuer une itération sur une seule vue, cela vous permet d'avoir un seul chemin de rendu pour divers appareils.

Toute la boucle de rendu

Si j'assemble tout cela, je obtiendrai le code ci-dessous. j'ai laissé un espace réservé pour les périphériques d'entrée, que je couvrirai dans une section ultérieure.

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);
    }
}

Mettre fin à la session XR

Une session XR peut se terminer pour plusieurs raisons, y compris se terminer par votre propre code via un appel à XRSession.end(). D'autres causes peuvent être à l'origine de la déconnexion du casque ou d'une autre application qui en prend le contrôle. C'est pourquoi une application bien conçue doit surveiller l'événement de fin et, lorsqu'il se produit, supprimer les objets de session et de moteur de rendu. Une fois terminée, une session XR ne peut pas être réactivée.

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);
}

Comment fonctionne l'interaction ?

Comme pour la durée de vie de l'application, je vais juste vous donner un aperçu de l'interaction avec des objets en RA ou en RV.

L'API WebXR Device adopte une approche de type "pointer-cliquer" pour l'entrée utilisateur. Avec cette approche, chaque source d'entrée dispose d'un rayon de pointeur défini pour indiquer où pointe un périphérique d'entrée, et d'événements pour indiquer quand quelque chose a été sélectionné. Votre application trace le pointeur et indique où il pointe. Lorsque l'utilisateur clique sur le périphérique d'entrée, des événements sont déclenchés, plus précisément select, selectStart et selectEnd. Votre application détermine ce qui a enregistré un clic et répond de manière appropriée.

Le périphérique d'entrée et le rayon de pointeur

Pour les utilisateurs, le rayon de pointeur n'est qu'une faible ligne entre le contrôleur et l'élément vers lequel il pointe. mais votre application doit le dessiner. Cela signifie obtenir la position du périphérique d'entrée et tracer une ligne entre son emplacement et un objet dans l'espace RA/RV. Ce processus se présente à peu près comme suit:

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.
    }
}

Il s'agit d'une version simplifiée de l'exemple de suivi des entrées de l'Immersive Web Community Group. Comme pour le rendu des images, vous pouvez dessiner le rayon du pointeur. C'est à vous de choisir l'appareil. Comme indiqué précédemment, ce code doit être exécuté dans la boucle de rendu.

Sélection d'éléments dans un espace virtuel

Il n'est pas très utile de signaler simplement des choses en RA/RV. Pour faire quoi que ce soit d'utile, les utilisateurs doivent avoir la possibilité de sélectionner des choses. L'API WebXR Device fournit trois événements permettant de répondre aux interactions utilisateur: select, selectStart et selectEnd. Ils ont une bizarrerie à laquelle je ne m'attendais pas: ils vous disent seulement qu'un périphérique d'entrée a été cliqué. Ils ne vous indiquent pas quel élément de l'environnement a été cliqué. Les gestionnaires d'événements sont ajoutés à l'objet XRSession et doivent être ajoutés dès qu'il est disponible.

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);
});

Ce code est basé sur un exemple de sélection des entrées, au cas où vous souhaiteriez plus de contexte.

Pour savoir sur quoi l'utilisateur a cliqué, utilisez une posture. (Êtes-vous surpris ? Je ne pensais pas.) Ces détails sont spécifiques à votre application ou au framework que vous utilisez et dépassent donc le cadre de cet article. L'approche de Cottontail se trouve dans l'exemple de sélection des entrées.

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

Conclusion: regarder l'avenir

Comme je l'ai dit précédemment, la réalité augmentée est attendue dans Chrome 69 (Canary à partir de juin 2018). Néanmoins, je vous encourage à essayer ce que nous avons jusqu'ici. Nous avons besoin de vos commentaires pour l'améliorer. Suivez sa progression en consultant le site ChromeStatus.com pour obtenir le Test d'appel WebXR. Vous pouvez également suivre WebXR Anchors qui améliorera le suivi des postures.