La réalité virtuelle arrive sur le Web

Voici quelques principes de base pour vous préparer à profiter d'un éventail d'expériences immersives: la réalité virtuelle, la réalité augmentée et bien plus encore.

Joe Medley
Joe Medley

Les expériences immersives sont disponibles sur le Web avec Chrome 79. L'API WebXR Device permet d'intégrer la réalité virtuelle à la réalité virtuelle, tandis que la réalité augmentée est disponible dans Chrome 81. Bien qu'une mise à jour de l'API GamePad étend l'utilisation avancée des commandes à la RV. D'autres navigateurs seront bientôt compatibles avec ces spécifications, comme Firefox Reality, Oculus Browser, Edge et le navigateur Helio de Magic Leap, entre autres.

Cet article commence une série sur le Web immersif. Cet épisode couvre la configuration d'une application WebXR de base, ainsi que l'entrée et la sortie d'une session XR. Les articles suivants traiteront de la boucle de frame (l'outil de travail de l'expérience WebXR), des spécificités de la réalité augmentée et de l'API Hit Test de WebXR, un moyen de détecter les surfaces dans une session de RA. Sauf indication contraire, tout ce que j'aborde dans cet article et dans les articles suivants s'applique de la même manière à la RA et à la RV.

Qu'est-ce que le Web immersif ?

Bien que nous utilisions deux termes pour décrire les expériences immersives (réalité augmentée et réalité virtuelle), nombreux sont ceux qui y voient un spectre allant de la réalité complète à complètement virtuelle, avec des degrés d'immersion entre les deux. Le "X" dans XR est destiné à refléter ce raisonnement en étant une sorte de variable algébrique qui représente tout ce qui relève du spectre des expériences immersives.

Graphique illustrant le spectre des expériences visuelles, de la réalité complète à complètement immersive.
Le spectre des expériences immersives

Voici quelques exemples d'expériences immersives:

  • Jeux
  • Vidéo à 360°
  • Vidéos 2D (ou 3D) traditionnelles présentées dans un environnement immersif
  • Achat immobilier
  • Consulter les produits de votre maison avant de les acheter
  • Art immersif
  • Quelque chose de cool à quoi personne n'a encore pensé

Concepts et utilisation

Je vais vous expliquer quelques principes de base concernant l'utilisation de l'API WebXR Device. Si vous avez besoin d'informations plus approfondies que celles fournies, consultez les exemples WebXR de l'Immersive Web Working Group ou les documents de référence de plus en plus nombreux du MDN. Si vous connaissez les premières versions de l'API WebXR Device, vous devez revoir tout ce contenu. Des changements ont été apportés.

Le code présenté dans cet article est basé sur l'exemple épuré de l'Immersive Web Working Group (demo, source), mais a été modifié par souci de clarté et de simplicité.

Une partie de la création de la spécification WebXR a consisté à étoffer les mesures de sécurité et de confidentialité afin de protéger les utilisateurs. Par conséquent, les implémentations doivent respecter certaines exigences. Une page Web ou une application doit être active et ciblée avant de pouvoir demander des informations sensibles au lecteur. Les pages Web ou les applications doivent être diffusées via HTTPS. L'API elle-même est conçue pour protéger les informations obtenues à partir des capteurs et des caméras, dont elle a besoin pour fonctionner.

Demander une session

L'entrée dans une session XR nécessite un geste de l'utilisateur. Pour cela, utilisez la détection de caractéristiques pour tester XRSystem (via navigator.xr) et appeler XRSystem.isSessionSupported(). Sachez que dans les versions 79 et 80 de Chrome, l'objet XRSystem s'appelait XR.

Dans l'exemple ci-dessous, j'ai indiqué que je voulais une session de réalité virtuelle avec le type de session 'immersive-vr'. Les autres types de sessions sont 'immersive-ar' et 'inline'. Une session intégrée permet de présenter du contenu en HTML et est principalement utilisée pour le contenu d'accroche. L'exemple de session de RA immersive illustre ce point. Je l'expliquerai dans un prochain article.

Une fois que je sais que les sessions de réalité virtuelle sont compatibles, j'active un bouton qui me permet d'acquérir un geste utilisateur.

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

Après avoir activé le bouton, j'attends un événement de clic, puis je demande une session.

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

Notez la hiérarchie des objets dans ce code. Elle passe de navigator à xr, puis à une instance XRSession. Dans les premières versions de l'API, un script devait demander un appareil avant de demander une session. L'appareil est acquis implicitement.

Saisissez une session

Une fois la session terminée, je dois la démarrer et y entrer. Mais d'abord, je dois configurer quelques éléments. Une session nécessite un gestionnaire d'événements onend pour que l'application ou la page Web puissent être réinitialisées lorsque l'utilisateur la quitte.

J'ai également besoin d'un élément <canvas> sur lequel dessiner ma scène. Il doit s'agir d'un élément WebGLRenderingContext ou WebGL2RenderingContext compatible avec XR. Tout le dessin est effectué à l'aide de ces outils ou d'un framework basé sur WebGL, tel que Three.js.

Maintenant que j'ai un endroit pour dessiner, j'ai besoin d'une source de contenu pour y dessiner. Pour cela, je crée une instance de XRWebGLLayer. Je l'associe au canevas en appelant XRSession.updateRenderState().

Une fois que j'ai une session, j'ai besoin d'un moyen de déterminer où en sont les choses dans la réalité virtuelle. J'ai besoin d'un espace de référence. Un espace de référence 'local-floor' est un espace où l'origine est située à proximité de la visionneuse, et l'axe des y est de 0 au niveau de l'étage et n'est pas censé se déplacer. Il existe d'autres types d'espaces de référence, mais c'est un sujet plus compliqué que je ne peux aborder ici. J'enregistre l'espace de référence dans une variable car j'en ai besoin lorsque je dessine à l'écran.

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

Après avoir obtenu un espace de référence, j'appelle XRSession.requestAnimationFrame(). Il s'agit du début de la présentation du contenu virtuel, qui s'effectue dans la boucle de frames.

Exécuter une boucle de frames

La boucle de frames est une boucle infinie contrôlée par un user-agent, dans laquelle le contenu est affiché à l'écran de manière répétée. Le contenu est dessiné dans des blocs discrets appelés cadres. La succession de plans crée l'illusion du mouvement. Pour les applications de RV, le nombre d'images par seconde peut être compris entre 60 et 144. La RA pour Android s'exécute à 30 images par seconde. Votre code ne doit pas supposer une fréquence d'images particulière.

Le processus de base de la boucle de frames est le suivant:

  1. Appelez XRSession.requestAnimationFrame(). En réponse, le user-agent appelle l'élément XRFrameRequestCallback, que vous avez défini.
  2. Dans votre fonction de rappel :
    1. Rappeler XRSession.requestAnimationFrame().
    2. Prenez la pose du spectateur.
    3. Transmettez ('lier') le WebGLFramebuffer de XRWebGLLayer à WebGLRenderingContext.
    4. Itérez chaque objet XRView, en récupérant son XRViewport à partir de XRWebGLLayer et en le transmettant à WebGLRenderingContext.
    5. Permet de dessiner un élément dans le framebuffer.

Le reste de cet article décrit les étapes 1 et 2, qui consistent à configurer et appeler XRFrameRequestCallback. Les points restants de l'étape 2 sont abordés dans la partie II.

XRFrameRequestCallback

C'est vous qui définissez XRFrameRequestCallback. Elle accepte deux paramètres: une instance DOMHighResTimeStamp et une instance XRFrame. L'objet XRFrame fournit les informations nécessaires pour afficher une seule image à l'écran. L'argument DOMHighResTimeStamp est destiné à être utilisé ultérieurement.

Avant de faire autre chose, je vais demander l'image d'animation suivante. Comme indiqué précédemment, la chronologie des frames est déterminée par le user-agent en fonction du matériel sous-jacent. Demander d'abord le frame suivant garantit que la boucle de frames se poursuit si quelque chose lors du rappel génère une erreur.

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

À ce stade, il est temps de dessiner quelque chose pour le spectateur. Il s'agit d'une discussion pour la partie II. Avant de commencer, laissez-moi vous montrer comment mettre fin à une session.

Mettre fin à la session

Une session immersive 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 end. Lorsque cela se produit, supprimez la session et ses objets de rendu associés. Une session immersive terminée ne peut pas être réactivée. Pour revenir à l'expérience immersive, mon application doit démarrer une nouvelle session.

Comme nous l'avons vu dans la section Enter a session (Accéder à une session), j'ai ajouté un gestionnaire d'événements onend lors de la configuration.

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

Dans le gestionnaire d'événements, restaurez l'état de l'application avant le début de la session de l'utilisateur.

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

Conclusion

Je n'ai pas tout expliqué dont vous avez besoin pour créer une application Web XR ou RA. J'espère que je vous en ai donné assez pour commencer à comprendre le code par vous-même et à tester le code. Dans l'article suivant, j'expliquerai la boucle de frames, c'est-à-dire l'endroit où le contenu est dessiné à l'écran.

Photo de JESHOOTS.COM sur Unsplash