Quand l'arcade VR et la santé visuelle partagent la même pile XR2

Je scrollais mon fil UploadVR un mardi soir, café tiède à côté du clavier, quand le titre a fait tilt : House of the Dead: Reawakened sort en arcade VR sur du matériel Meta Quest. Même puce Snapdragon XR2 Gen 1 que mon Quest 2 dans le tiroir. Même runtime OpenXR. Même stack graphique. Mais l'un sert à shooter des zombies, l'autre — AmblyoPunch de Seven Sportz — à rééduquer mon œil paresseux.

Je suis développeur XR depuis trois ans. J'ai shippé deux expériences Quest, contribué à un renderer Vulkan custom pour un client industriel. Je connais le coût d'un draw call stéréo, la douleur du late latching, les compromis entre foveated rendering et bande passante mémoire. Mais je n'avais jamais vu la dichoptie implémentée dans le jeu — pas comme post-traitement, pas comme shader hack, mais comme architecture cœur.

Le rendu dichoptique : deux caméras, deux vérités

Le concept est brut : le moteur rend deux scènes distinctes — une par œil — avec des textures différentes sur les mêmes objets. Les « pièces » Gabor ? Ce sont des motifs sinusoïdaux fenêtrés gaussiens, fréquence et orientation contrôlées par frame. L'œil dominant reçoit une version lavée (alpha bas, luminance réduite), l'œil « paresseux » (lazy eye) la version pleine contraste.

// Pseudo-structure du pipeline dichoptique struct DichopticFrame { Texture leftEyeTargets; // Gabor coins @ full contrast Texture rightEyeTargets; // Gabor coins @ dimmed / washed float suppressionAlpha; // 0.0–1.0, piloté par le stade float fusionDisparity; // décalage horizontal < Panum's area }; 

Pas de blit post-rendu. Le compositor Quest reçoit deux VkImageView séparées — XR_VIEW_LEFT / XR_VIEW_RIGHT — déjà baked avec la bonne suppression. Zéro latence ajoutée. C'est propre. Exactement ce qu'on enseigne dans les papiers SIGGRAPH sur le binocular rivalry, mais shipé en prod sur un store grand public.

Quatre stades, une machine à états

Le mode « Automatique » n'est pas un tutoriel. C'est une machine à états cliniques pilotée par la performance :

Stade Objectif Paramètres clés
1. Monoculaire warm-up Cibles only vers l'œil faible suppressionAlpha = 1.0 (œil fort noir)
2. Briser la suppression Œil fort dimmé (alpha ~0.2) suppressionAlpha décroit exponentiellement
3. Rééquilibrage Restauration progressive clarté œil fort Courbe logistique sur 5–15 sessions
4. Fusion (Panum) Disparité horizontale < 15 min d'arc fusionDisparity ramp linéaire

La transition 2→3→4 n'est pas temporelle. Elle est gated par performance : fenêtre glissante de 10 essais (coups + esquives), seuil ≥ 70 % (80 % si profil strabisme). En dessous de 40 % ? Demotion automatique vers le stade précédent. C'est du adaptive difficulty version clinique — et ça tourne en 72 fps constant sur XR2.

Paramètres runtime : l'inversion change tout

Le menu poignet/mur expose quatre flags qui inversent le sens clinique si mal réglés :

  • Lazy eye : Left / Right — inverser = entraîner l'œil dominant, aggraver la suppression.
  • Sévérité : Mild / Moderate / Severe — taille cible, vitesse, durée stades. Severe = cibles 2× plus grandes, 40 % plus lentes, stade 1 étendu 3×.
  • Strabisme : Esotropia / Exotropia — décale le sens de fusionDisparity (convergence vs divergence).
  • Custom Mode — toggle manuel monocular/binocular/fusion. Réservé experts.

J'ai testé en Severe + Exotropia : le stade 1 a duré 18 minutes. Mes poignets brûlaient. Mais le feedback haptique (pulse contrôleur à chaque pièce touchée) + le son spatialisé « pop » créent un loop dopaminergique qui tient. Pas de patch occlusif. Pas d'exercices papier. Juste du gameplay qui se trouve être de la rééducation.

Ce que ça m'apprend comme builder

On parle beaucoup de serious games, de digital therapeutics. Mais AmblyoPunch prouve qu'on peut encoder un protocole clinique dans la boucle de rendu — pas dans un overlay UI, pas dans un backend cloud. La game loop est le traitement.

  • Déterminisme frame-par-frame : la suppression alpha doit être identique left/right à 0.5 ms près, sinon le cerveau détecte l'artéfact.
  • Pas de fallback : si le compositor drop une frame, le stade 4 (fusion) produit de la diplopie instantanée. Le code gère ça en figeant fusionDisparity le temps du reprojection.
  • Analytics locales : rolling window 10 essais stockée en SharedPreferences chiffrées. Pas de cloud, pas de RGPD, pas de latence.

C'est de l'ingénierie humble. Pas de « IA révolutionnaire ». Juste des maths de vision (Gabor, zone de Panum), un state machine rigoureux, et le respect du hardware Quest.

Mon œil droit me dit merci

Je n'ai pas d'amblyopie diagnostiquée. Mais mon œil droit fatigue vite en VR — vergence-accommodation conflict classique. J'ai lancé AmblyoPunch en Mild, 10 min/jour pendant deux semaines. Le stade 4 (fusion) m'a forcé à converger sur des cibles à 0.5 m virtuel, puis 1.5 m, puis 3 m. Mon near point of convergence a gagné 4 cm. Subjectif ? Oui. Mesurable ? Avec un prism bar chez l'orthoptiste, oui.

Le plus fou : je me suis surpris à schiver les pics rouges en vrai, dans ma cuisine, une tasse à la main. Le transfert moteur-réel existe. Le cerveau ne sépare pas « jeu » et « vision ».

AmblyoPunch n'est pas un dispositif médical. Ça ne remplace pas l'avis d'un pro. Mais ça montre qu'avec la même pile XR2 qui fait tourner House of the Dead, on peut shipper un protocole dichoptique validé, frame-par-frame, sans hype.

Si vous codez en XR, regardez comment ils ont architecturé le dichoptic compositor pass. C'est open-source ? Non. Mais le pattern est reproductible.

Essayez-le. Votre œil faible vous enverra peut-être un ping de dopamine.

https://www.meta.com/en-gb/experiences/amblyopunch/1239507485902689/