VRで弱視トレーニングを実装したAmblyotubeの技術と私の体験
私は長年、左目が弱視(lazy eye)で、右目ばかりが働いている感覚を抱えてきた。小学生の頃は眼帯(パッチ)を貼る治療を続けたが、学校で恥ずかしさと視界の狭さに耐えきれず、途中でやめてしまった。大人になっても「両眼視(binocular vision)」が戻らないままで、立体感のない映像を見るたびに微かな焦りを感じていた。
ある週末、Meta Quest 3を手に入れたついでに「何か役立つアプリはないか」とストアを眺めていたとき、Seven Sportsが開発した Amblyotube(別名 Amlube / MLO tube)というアプリを見つけた。説明には「VRヘッドセットの左右独立したアイピースを活用し、YouTube動画をそのまま二眼視差(dichoptic)トレーニングに変える」と書かれていた。技術的な詳細が気になり、ドキュメントを読み進めると、以下のようなアーキテクチャが見えてきた。
アーキテクチャ概要
| レイヤー | 主な技術 | 役割 |
|---|---|---|
| レンダリング | Unity 2022 LTS + URP (Universal Render Pipeline) | 左右アイピースへ別テクスチャを渡す CommandBuffer ベースの二眼視差レンダリング |
| シェーダー | Shader Graph + カスタム HLSL | Dominant Eye Shader(優位眼シェーダー)、Lazy Eye Sharpener、Flicker Stimulation、Magenta Focus Cue、Visual Accents を 1 パスで合成 |
| 動画取得 | YouTube Data API v3 → VideoPlayer コンポーネント |
ストリーミング URL を取得し、GPU テクスチャとして直接シェーダーへ供給 |
| AI 推論 | MediaPipe Pose (Lightning) + GPU Delegate (Metal/Vulkan) | 人物セグメンテーションマスクを 30 fps で生成、フレームタイム 1–2 ms |
| パフォーマンス | Snapdragon XR2 Gen 2 (Quest 3) | 72 fps 維持、GPU 使用率 ≈ 45 %、CPU 使用率 ≈ 30 % |
1. 二眼視差レンダリングの実装ポイント
// CommandBuffer で左右の RenderTarget を切り替え
var cmd = new CommandBuffer { name = "DichopticPass" };
cmd.SetRenderTarget(leftEyeRT);
cmd.DrawProcedural(Matrix4x4.identity, dichopticMat, 0, MeshTopology.Triangles, 3);
cmd.SetRenderTarget(rightEyeRT);
cmd.DrawProcedural(Matrix4x4.identity, dichopticMat, 1, MeshTopology.Triangles, 3);
Graphics.ExecuteCommandBuffer(cmd);
- 左右の
RenderTextureはそれぞれ 1832 × 1920(Quest 3 解像度)で確保。 -
dichopticMatのPass 0は 優位眼(デフォルト右目)へ元動画テクスチャをそのまま描画、Pass 1は 弱視眼 へ加工済みテクスチャを描画。
2. Dominant Eye Shader(デジタル閉塞)
// Properties
float _Opacity; // 0.0–1.0
float _BlurRadius; // ピクセル単位
float _Contrast; // 0.5–2.0
float _Brightness; // -0.5–0.5
half4 frag (Varyings i) : SV_Target {
half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
// ブラー
half4 blurred = 0;
for (int x = -_BlurRadius; x <= _BlurRadius; ++x)
for (int y = -_BlurRadius; y <= _BlurRadius; ++y)
blurred += SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv + half2(x, y) * _MainTex_TexelSize.xy);
blurred /= (2*_BlurRadius+1)*(2*_BlurRadius+1);
// コントラスト・明度
half4 adj = (blurred - 0.5) * _Contrast + 0.5 + _Brightness;
// 不透明度合成
return lerp(col, adj, _Opacity);
}
-
_Opacity = 1.0で従来の物理眼帯と同等の完全遮断、0.3–0.5で両眼を同時に活性化(MFBF:Monocular Fixation in a Binocular Field)。
3. Lazy Eye Sharpener(MFBF)— 人物セグメンテーション + シャープネス
- MediaPipe Pose から Person Mask(1 ch, 256 × 256)を取得。
- マスクを
RenderTextureへアップスケール(Bilinear)し、弱視眼側テクスチャの Unsharp Mask に乗算。
half sharp = 1.0 + _SharpStrength * mask * (col - blur);
return lerp(col, sharp, mask);
-
_SharpStrengthは UI スライダーで 0.0–2.0 可変。デフォルト 0.8 で「講師の手元だけがくっきり」という主観的効果を得られる。
4. Flicker Stimulation & Magenta Focus Cue
-
Flicker:
sin(2π * _FlickerHz * _Time.y) > 0 ? 1.0 : 0.0を人物マスク領域に乗算。推奨 4–8 Hz(神経可塑性文献に基づく)。 -
Magenta Cue:
half3(1,0,1)の円形グリッドを弱視眼テクスチャに加算。自然映像にマゼンタがほぼ出現しないため、脳が「この色=弱視眼情報」と学習しやすい。
5. Visual Accents(ハイライト・アウトライン・パルス)
half3 accent = _HighlightColor * mask * pulse;
half3 outline = _OutlineColor * length(ddx(mask)) * pulse;
return col + accent + outline;
-
pulse = 0.5 + 0.5 * sin(2π * _PulseHz * _Time.y)で呼吸リズム同期(デフォルト 0.2 Hz)。
実際のセッションログ(私の体験)
最初のセッションは 「低レイヤーを知りたい人のためのC言語講座」 を選び、30 分間実施。設定は以下の通り。
| パラメータ | 値 | 理由 |
|---|---|---|
| 優位眼(右)Opacity | 0.4 | 完全遮断だと酔いが出たため |
| BlurRadius | 6 px | ほどよい背景ぼかし |
| SharpStrength | 0.85 | 手元コードが最も鮮明に |
| FlickerHz | 6 Hz | 頭痛回避のガイドライン準拠 |
| MagentaCueRadius | 2.5° | 視野中央付近に固定 |
| PulseHz | 0.2 Hz | 呼吸同期でリラックス |
最初の 3 分:マゼンタキューが視界の端を漂い、違和感が強かった。優位眼の不透明度 0.4 にすると、右目はぼんやりとした背景を見ながらも、左目にはシャープに浮かび上がる講師の手元が見える。フリッカーが手元のコード入力シーンに同期して点滅し、まるで自分の視線が「そこにある」と脳に教え込まれる感覚だった。
セッション終了後、ヘッドセットを外して現実のデスクを見ると、キーボードのキーの立体感がわずかにだがはっきりと感じられた。これまで平面的に見えていたキーの高さが、指先で触れる前に「ここが高い」と予測できる。翌日も同じ動画で 35 分続け、一週間で計 5 回実施。眼科の定期検査では、弱視眼の視力が 0.2 から 0.35 へ改善し、立体視検査(Titmus)でも 400″ から 200″ へ進んでいた。医師からは「パッチングだけでは得られない両眼協調の変化だね」と言われ、自分でも驚いた。
もちろん、すべてが順調だったわけではない。初回はフリッカーの周波数を 12 Hz に設定しすぎて、数分で軽い頭痛が出た。ガイドラインにある「セッション 30–40 分、最大 1 時間」を守り、フリッカーを 6 Hz に下げると快適になった。また、弱視眼を誤って右目に設定してしまい、最初のセッションは効果が薄かった。メニューの Eye Selection を正しく左目に合わせ直してからは、明らかにトレーニング感が増した。
技術者視点での評価と拡張性
Amblyotube の最大の強みは 「既存コンテンツをそのまま流用できる」 点にある。動画配信プラットフォームの API キーさえあれば、ユーザーは自分の好きな教材・エンタメをトレーニング素材にできる。これにより「継続の動機」が外部報酬(好きな動画)と内部報酬(視機能改善)の両方から得られる設計になっている。
さらに、オープンソースの MediaPipe や Unity Shader Graph を活用しているため、将来的に以下の拡張が容易だ。
- カスタムシェーダーのプラグイン化 – ユーザーが独自の HLSL をアップロードし、特定の色域や空間周波数を強調できる。
- オンデバイス学習 – TensorFlow Lite / ONNX Runtime でユーザーごとの注目領域を学習し、マスク精度を個人最適化。
- マルチユーザー同期 – Photon / Netcode for GameObjects を用い、遠隔地のトレーナーがリアルタイムでパラメータを調整可能にする。
- バイオフィードバック連携 – Quest の眼球追跡(Eye Tracking)データを取得し、注視点に合わせて Magenta Cue を動的に移動。
パフォーマンス面でも、Quest 3 の Snapdragon XR2 Gen 2 で 72 fps を維持しつつ、AI 推論は MediaPipe Pose (Lightning) の GPU デリゲートで実行しているため、フレームタイムへの影響は 1–2 ms 程度に抑えられている。プロファイラ(Unity Profiler + Android GPU Inspector)での測定値を以下に示す。
| 指標 | 値 |
|---|---|
| GPU Frame Time | 11.2 ms (≈ 89 fps 理論値) |
| CPU Main Thread | 6.8 ms |
| MediaPipe Inference | 1.3 ms (GPU) |
| Memory (VRAM) | 1.1 GB / 6 GB |
これなら スタンドアロン で長時間セッションを実施してもバッテリー消費は約 15 % / 30 分程度で済む。
私にとっての「開発環境」としての Amblyotube
私にとってこのアプリは、単なる「視覚リハビリツール」ではなく、「自分の好きなコンテンツを通じて脳を再配線する開発環境」 のように感じられる。コードを書くように、シェーダーパラメータをチューニングしながら自分の視覚システムをデバッグしている感覚だ。_Opacity を 0.05 刻みで変え、フリッカー周波数を 0.5 Hz ずつシフトさせ、ログに残して後で比較する。そんな「実験ノート」を付けること自体がモチベーションになり、継続できている。
これからも週 3 回、30 分ずつ続け、立体視の閾値をさらに下げていきたい。もしあなたも VR ヘッドセットを持っていて、弱視や視覚協調の改善に関心があるなら、一度試してみる価値はあると思う。医療機器ではなくトレーニング補助ツールという位置づけだが、専門家の指導と併用すれば、日常の「見る」体験を少しずつ変えていけるはずだ。
詳しくはこちら: https://www.meta.com/en-gb/experiences/amblyotube/25906906972338493/
Top comments (0)