←Retour au Blog

Comment mon jeu de navigateur tourne en VR sur un Meta Quest

26 sept. 20264 min read

Mon jeu Bannermarch fonctionne dans le navigateur, et comme il est maintenant en 3D, j'ai voulu voir si je pouvais y jouer en VR. C'est possible. J'ai mis mon Meta Quest, ouvert le jeu dans le navigateur du casque et appuyé sur un bouton qui disait "Enter VR". Ensuite, je me suis retrouvé à l'intérieur de mon domaine, avec le donjon (la tour principale) sur la colline devant moi. Je n'ai rien installé. C'est la même page web que vous ouvririez sur un ordinateur portable.

Cela fonctionne grâce à deux choses. Les navigateurs disposent d'une API intégrée pour les casques VR appelée WebXR, et le jeu utilise déjà Babylon.js, un moteur 3D qui sait comment l'utiliser.

Comment le navigateur fait de la VR

WebXR permet à une page web de communiquer avec un casque VR. Le navigateur du Quest l'a, tout comme Chrome et Edge sur un ordinateur avec un casque PC VR branché. Safari sur l'iPhone ne l'a pas.

D'abord, la page demande au navigateur si la VR est disponible. Si c'est le cas, la page affiche un bouton "Enter VR". Vous devez cliquer sur quelque chose pour démarrer la VR, car les navigateurs ne permettent pas à une page de le faire d'elle-même (c'est la même règle qui empêche les vidéos de se lancer automatiquement avec le son).

Après avoir cliqué, le navigateur prend le contrôle de l'écran du casque. Plusieurs fois par seconde, il indique à la page où se trouvent votre tête et vos mains. La page dessine alors le jeu deux fois, une fois pour chaque œil, chacune depuis un point légèrement différent. Cette petite différence est ce qui donne l'impression de 3D dans le casque.

// WebXR simple, sans moteur
if (await navigator.xr?.isSessionSupported("immersive-vr")) {
  button.onclick = async () => {
    const session = await navigator.xr.requestSession("immersive-vr");
    const space = await session.requestReferenceSpace("local-floor");
    session.requestAnimationFrame(function frame(time, xrFrame) {
      const pose = xrFrame.getViewerPose(space);
      for (const view of pose.views) {
        // dessiner la scène avec view.transform et view.projectionMatrix
      }
      session.requestAnimationFrame(frame);
    });
  };
}

La partie local-floor indique au navigateur de placer le sol du jeu là où se trouve votre sol réel, de sorte que vous voyez le monde depuis votre propre hauteur.

Le navigateur s'occupe des tâches complexes, comme le suivi de votre tête et l'ajustement de l'image aux lentilles. Le jeu se contente de dessiner ce que la caméra voit.

Comment Babylon.js aide

Je n'ai pas écrit ce code moi-même. Babylon.js dispose d'une aide appelée WebXRDefaultExperience qui le fait pour vous. Elle démarre la session VR et déplace la caméra lorsque vous bougez la tête. Elle vous fournit également des pointeurs laser sur les contrôleurs et vous permet de vous téléporter. C'est à peu près toute la configuration dont j'avais besoin.

const xr = await WebXRDefaultExperience.CreateAsync(scene, {
  disableDefaultUI: true,
  floorMeshes: [ground],
  disableHandTracking: true,
  inputOptions: {
    doNotLoadControllerMeshes: true,
    disableOnlineControllerRepository: true,
  },
  teleportationOptions: { forceHandedness: "right" },
});

// plus tard, depuis le bouton Enter VR
await xr.baseExperience.enterXRAsync("immersive-vr", "local-floor");

Je n'ai pas eu à modifier le jeu lui-même. C'est le même monde 3D que vous voyez sur un ordinateur portable, avec les mêmes bâtiments, personnes et bateaux. Si vous pointez vers un bâtiment et appuyez sur la gâchette, son nom s'affiche au-dessus. Appuyez à nouveau sur la gâchette et le jeu vous fait sortir de la VR avec le menu de ce bâtiment ouvert. Gérer votre château est toujours plus facile sur un écran normal.

Les personnes sur téléphone et ordinateur portable ne téléchargent aucun code VR. Il ne se charge que sur les appareils qui peuvent l'utiliser.

Ce qui n'a pas fonctionné

Cela n'a pas fonctionné du premier coup. Les joysticks des contrôleurs ne faisaient rien au début. Babylon télécharge un fichier pour chaque contrôleur qui indique quels boutons il possède, mais les paramètres de sécurité de mon site bloquent ce téléchargement. Sans le fichier, Babylon traitait les contrôleurs comme s'ils n'avaient qu'une gâchette. J'ai résolu le problème en plaçant ces fichiers à l'intérieur du jeu pour qu'il n'ait pas besoin de les télécharger.

Lorsque j'ai ajouté la marche avec le stick gauche, le bouton "Enter VR" a disparu. La marche intégrée de Babylon ne peut pas être activée en même temps que la téléportation, donc la configuration VR a planté. J'ai écrit ma propre marche à la place, environ 30 lignes de code. Le stick gauche vous fait marcher là où vous regardez, et le stick droit vous téléporte ou vous fait tourner par étapes. J'ai omis la rotation fluide car elle rend beaucoup de gens malades.

Les couleurs étaient étranges dans le casque. Le jeu ajuste ses couleurs comme dernière étape sur la caméra normale, et cette étape ne s'exécute pas sur la caméra VR, j'ai donc dû l'appliquer d'une autre manière en VR.

Le jeu s'est également figé dès que je suis entré en VR. Pour économiser la batterie, il arrête de dessiner lorsque vous passez à un autre onglet. Le navigateur du Quest a indiqué au jeu que son onglet était masqué pendant que j'étais en VR, le jeu s'est donc arrêté. Maintenant, il continue de dessiner tant que la VR est activée.

La puce graphique du Quest est à peu près aussi puissante qu'un téléphone, et elle doit tout dessiner deux fois, elle utilise donc le réglage graphique bas du jeu. Certains téléphones indiquent également qu'ils prennent en charge la VR (pour les visionneuses en carton), j'affiche donc le bouton uniquement sur les casques et les ordinateurs.

La connexion était un problème distinct, car taper un mot de passe sur un clavier flottant est douloureux. J'ai écrit comment j'ai résolu cela dans la connexion d'un casque VR comme votre téléviseur.

Restez Informé

Recevez les derniers articles et analyses directement dans votre boîte de réception.

Aucun spam. Désinscription à tout moment.