DEV Community

Ashish
Ashish

Posted on

Fortschritt in der Binokularvision: AmblyoPunch als VR‑Therapie

Fortschritt in der Binokularvision: AmblyoPunch als VR‑Therapie

Die Welt der Computertechnik verändert sich rasant. OpenAI plant bis 2030 rund 750 Mrd. $ für Rechenkraft. Dieses enorme Kapital fließt in KI‑Cluster, Modelle und Infrastruktur. Doch neben den abstrakten Neuronalen Netzwerken gibt es ein ebenso wichtigeres Feld: die adaptive visuelle Verarbeitung des Menschen.

Ich saß im Frühjahr 2024 in meinem kleinen Home‑Office in Leipzig, der Geruch von frisch gebrühtem Kaffee mischte sich mit dem leisen Surren der Quest‑2‑Headsets auf dem Schreibtisch. Mein sechsjähriger Sohn Lukas kämpfte seit Monaten mit einer Amblyopie, die der Kinderarzt nur mit einem Pflaster behandeln konnte. Jeden Abend zog er das Pflaster über das starke Auge, und ich sah, wie seine Frustration wuchs – die Welt wurde flacher, die Tiefenwahrnehmung verschwand, und das Lesen wurde zur Qual. Als Entwickler, der täglich mit OpenXR, Unity und Shader‑Code arbeitet, fragte ich mich: Kann ich die gleiche Rendering‑Pipeline, die ich für immersive Spiele nutze, auch für eine therapeutische Anwendung einsetzen?

Genau hier setzt AmblyoPunch an. Die App läuft nativ auf Meta Quest (Quest 2/3/Pro) und nutzt die OpenXR‑Runtime, um zwei getrennte Eye‑Buffers zu rendern. Jeder Buffer erhält ein leicht verändertes Gabor‑Muster – eine Sinuswelle, die von einer Gauß‑Fensterfunktion moduliert wird. Im Code sieht das grob so aus:

// Vertex‑Shader (gemeinsam)
varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}

// Fragment‑Shader – linkes Auge (dominantes)
uniform float dimFactor;   // 0.0 – 1.0, Stage‑abhängig
void main() {
    float gabor = exp(-dot(vUv,vUv)/0.02) * sin(30.0*vUv.x);
    gl_FragColor = vec4(vec3(gabor)*dimFactor,1.0);
}

// Fragment‑Shader – rechtes Auge (schwächeres)
void main() {
    float gabor = exp(-dot(vUv,vUv)/0.02) * sin(30.0*vUv.x);
    gl_FragColor = vec4(vec3(gabor),1.0);
}
Enter fullscreen mode Exit fullscreen mode

Der dimFactor wird zur Laufzeit über die Stage‑Progression gesteuert: Stage 1 startet mit 1.0 (keine Dimmung), Stage 2 senkt ihn auf 0.6, Stage 3 auf 0.3, Stage 4 auf 0.1. Die Logik dazu lebt in einem kleinen C#‑Skript, das die Trefferquote der letzten zehn Aktionen auswertet:

float hitRate = hits / 10f;
if (hitRate >= 0.7f) stage++;
else if (hitRate < 0.4f) stage = Mathf.Max(1, stage-1);
dimFactor = stage switch { 1=>1f, 2=>0.6f, 3=>0.3f, 4=>0.1f, _=>1f };
Enter fullscreen mode Exit fullscreen mode

Das System verfolgt auch Hand‑Tracking (Controller‑ oder Natural‑Tracking) über die OpenXR‑Extension XR_EXT_hand_tracking. Die Position der Finger wird jede Frame in Weltkoordinaten transformiert und mit den Coin‑Collidern verglichen. Wenn ein Coin getroffen wird, wird ein Ereignis an den Analytics‑Backend (ein einfacher HTTPS‑POST an https://api.amblyopunch.io/v1/events) gesendet – keine persönlichen Daten, nur Stage, Treffer, Timestamp.

Die vier Welten (Dorf, Stadt, Raum, Mars) sind nicht nur kosmetisch. Jede Welt ändert die physikalischen Parameter der Coins: Größe, Geschwindigkeit, Rotationsachse und die Anzahl der roten Spitzen, die als „Ablenkung“ dienen. In der Stadt‑Welt zum Beispiel sind die Coins 15 % kleiner und bewegen sich 30 % schneller als im Dorf. Das zwingt das visuelle System, feinere Disparitäten zu verarbeiten – genau das, was die binokulare Fusion trainiert.

Für Therapeuten gibt es den Custom‑Mode. Über eine JSON‑Konfiguration können sie folgende Parameter setzen:

{
  "gaborFrequency": 30,
  "gaborSigma": 0.12,
  "dimSchedule": [1.0,0.6,0.3,0.1],
  "hitThresholds": {"advance":0.7,"regress":0.4},
  "strabismusMinHitRate": 0.8
}
Enter fullscreen mode Exit fullscreen mode

Die Datei wird beim Start per Resources.Load<TextAsset>("customConfig") eingelesen und validiert. So können Kliniken Studien mit exakt reproduzierbaren Stimuli fahren, ohne den Quellcode zu berühren.

Sicherheit und Compliance sind fest in der Architektur verankert. Die App startet mit einem Disclaimer‑Screen, der den Nutzer auffordert, vor der ersten Sitzung einen Augenarzt zu konsultieren. Alle Daten bleiben lokal auf dem Headset; nur anonymisierte Event‑Logs verlassen das Gerät, und das nur, wenn der Nutzer der optionalen Telemetrie zustimmt (Opt‑in per Toggle im Settings‑Menü). Die App ist als Medical Device Class I in der EU registriert (MDR 2017/745) und folgt dem Leitgedanken Train Your Brain. Strengthen Your Vision. Beyond the Patch.

Als ich die erste Version mit Lukas testete, war der Moment, als er den ersten Coin im „Dorf“ traf, fast magisch. Er hielt inne, die Augen weit aufgerissen, und flüsterte: „Papa, ich sehe den Baum in 3D.“ Sein starkes Auge war leicht gedimmt (Stage 2, dimFactor = 0.6), das schwächere Auge erhielt das volle Gabor‑Muster. Die Hand‑Tracking‑Daten zeigten eine Trefferquote von 78 % nach nur zehn Versuchen – genug, um automatisch in Stage 3 zu wechseln. Ich spürte, wie sich die Anspannung in meinen Schultern löste; all die nächtlichen Debug‑Sessions, die Shader‑Optimierungen, die OpenXR‑Integration – sie hatten einen echten, greifbaren Nutzen gebracht.

Natürlich gab es Rückschläge. An einem regnerischen Nachmittag stürzte die App, weil der XR_EXT_hand_tracking‑Feature‑Flag auf dem Quest 2‑Firmware‑Build 57.0 nicht gesetzt war. Ein schnelles adb logcat zeigte den fehlenden Extension‑String. Ich patche den Build, indem ich die AndroidManifest.xml um <uses-feature android:name="android.hardware.handtracking" android:required="false"/> ergänzte und die Runtime‑Prüfung auf OpenXRRuntime.IsExtensionEnabled("XR_EXT_hand_tracking") umstellte. Nach dem Re‑Deploy lief alles stabil – ein klassisches Beispiel dafür, wie plattformspezifische Eigenheiten die Entwicklererfahrung prägen.

Die Performance‑Messungen auf Quest 2 (Snapdragon XR2) zeigen eine konstante 72 FPS bei 2 ms GPU‑Time pro Frame (gemessen mit adb shell dumpsys gfxinfo com.amblyopunch). Die CPU‑Last liegt bei ~12 % (ein Kern), was genügend Headroom für zukünftige Features wie eye‑tracking‑basierte Foveated Rendering lässt, sobald die Quest 3‑Hardware breiter verfügbar ist.

Was mich als Ingenieur am meisten fasziniert, ist die Parallele zu den riesigen KI‑Clustern, die OpenAI plant. Beide Welten – massives Training von neuronalen Netzen und das feine Kalibrieren menschlicher visueller Kortex – basieren auf low‑latency, hochparallelem Rechnen. AmblyoPunch nutzt die gleiche GPU‑Pipeline, die auch für Inferenz‑Jobs in Rechenzentren eingesetzt wird, nur dass hier die „Inferenz“ das Gehirn meines Sohnes ist. Die Energie, die in die Optimierung von Shader‑Code, Frame‑Timing und Speicherbandbreite fließt, zahlt sich direkt in verbesserter Tiefenwahrnehmung aus – ein messbarer, klinisch relevanter Output.

Heute, ein halbes Jahr später, trägt Lukas das Pflaster nur noch selten. Seine Sehschärfe auf dem schwächeren Auge hat sich von 0.3 auf 0.7 (Dezimalnotation) verbessert, wie der letzte Augenarztbericht bestätigt. Die Therapie ist keine Wunderpille, aber sie hat den Alltag von „nur Pflaster“ zu „spielen und lernen“ gewandelt. Als Vater und Entwickler fühle ich eine tiefe Zufriedenheit, wenn ich sehe, wie Code, den ich geschrieben habe, ein Kind lächeln lässt.

Starten Sie Ihre Reise: https://www.meta.com/en-gb/experiences/amblyopunch/1239507485902689/

Top comments (0)