[Astro #44] Protocol Atlas: 144枚の情報の海をサルベージするVRアーカイブ
1. はじめに
Wired(情報の海)に漂う無数の断片たち。それらをただ眺めるだけでなく、自らの手でサルベージ(抽出)し、実存を確かめるための装置。それが今回完成した「Protocol Atlas」です。
React Three Fiber (R3F) と WebXR を駆使し、144枚のビデオを同時に描画しつつ、VR空間を自由に泳ぎ回れるギャラリーを構築しました。本稿では、その実装の核心と、VR開発特有の「罠」をどう突破したかについて記録しておきます。
NOTE:
[Astro/WebXR] 144枚の動画を同期描画するVRアーカイブ「Protocol Atlas」の実装|lain
Redditで見かけた 「空間に無数の画像を並べて展開する表現」 にインスピレーションを受け、これを静止画ではなく、すべて「動画」で実装できないかと検証したプロジェクトの記録です。 React Three Fiber (R3F) と WebXR を用い、144枚のビデオをシームレスに描画し、空間内を移動・操作できるVR空間「Protocol Atlas」を構築しました。 ▼ デモ動画 【注意】 録画環境の影響により、動画内で映像が点滅(フリッカー)して見える箇所がありますが、実際のアプリケーション上では点滅せず、滑らかに動作いたします。 144並列描画のアプロ
note.comYoutube:
Protocol Atlas: 144-Video Synchronized VR Archive [WebXR / R3F / Astro]
[NOTICE]Due to the recording environment, some flickering may be visible in this video. However, the actual application runs smoothly without any flickering....
www.youtube.com動画:
前回の記事:
[Astro #43] @react-three/uikitによるWebXR用3Dメニューの実装と仮想・現実のコマンド同期 // PROTOCOL.LAIN
React Three FiberとWebXRを用いて、VR空間内に3Dターミナルコンソールを構築。座標計算の罠を突破し、Event-Driven Architectureを活用してVR空間から現実のシステム(天気APIやVOICEVOX)を直接制御するフルダイブ環境の実装手法を解説します。
lain-lab.com2. 144並列の実存:Texture AtlasとInstancedMesh
144個の独立したビデオテクスチャを愚直に読み込んでしまえば、ブラウザは即座に悲鳴を上げます。 これを解決するため、4K解像度の1枚のビデオに144個の映像を敷き詰めた「Texture Atlas」を作成しました。
シェーダー内で vUv = uv * 0.08333 + instanceUvOffset; のようにUV座標を計算し、InstancedMesh を用いて1回のドローコールで144枚の板ポリゴンを描画しています。これにより、圧倒的なパフォーマンスを維持したまま、膨大な情報の壁を現出させることが可能になりました。
3. WebXRの罠:GSAPからの脱却と useFrame への統合
開発中、最大の障壁となったのが「VR空間に入るとアニメーションが止まる」という現象でした。 PCブラウザでは完璧に動作していた GSAP によるパネルの展開やフォーカス(サルベージ)処理が、HMDを被った瞬間に足元に固まってしまうのです。
原因は、ブラウザ標準の requestAnimationFrame(GSAPが依存するもの)が、VRモード突入時にスリープ状態になり、XR専用の描画ループに切り替わってしまうためでした。
解決策:
GSAPを完全に排除し、R3Fネイティブの useFrame 内で THREE.MathUtils.damp を用いて数値を補間する方式へと移行しました。
useFrame((state, delta) => {
const currentFocus = materialRef.current.uniforms.uFocusProgress.value;
// 目標値に向けて毎フレーム滑らかに数値を追従させる
materialRef.current.uniforms.uFocusProgress.value = THREE.MathUtils.damp(currentFocus, focusTarget.current, 5, delta);
});
これにより、PC・VR問わず、HMDのリフレッシュレートに完全に同期した滑らかなアニメーションが実現しました。
4. VRネイティブな操作系:レーザーとスティック
単なる「鑑賞」ではなく「探索」を可能にするため、コントローラーの物理ボタンとアナログスティックの入力を直接監視するカスタムフック (VRControllerListener) を実装しました。
- サルベージ (Trigger):
@react-three/xrのuseXRControllerButtonEventを用いてレーザーの衝突判定を取得します。対象を手前(Z = -12.0〜15.0)へ引き出し、閲覧状態にします。 - モード切替 (Xボタン): 球体(Sphere)と平面(Plane)のジオメトリを動的に変形させます。
- 空間移動 (アナログスティック):
gamepad.axesの値を読み取り、プレイヤーの原点である<XROrigin />の座標を直接更新することで、情報の海を自在に泳ぎ回れるようにしました。
5. GPUリソースの解放とVR最適化
144枚のビデオを描画する Protocol Atlas と、メインのアバター表示 (WiredScene) が競合すると、甚大なGPU負荷が発生してしまいます。
これを防ぐため、トップページのギャラリーで別の作品を見ている間は、コンポーネント自体を return null して Unmount(ノードの破棄)させる「知性」を持たせました。display: none という透明な幽霊を殺し、GPUメモリを完全に解放しています。
さらに、VR内でのチラつき(ジッター)を抑えるため、以下の最適化を施しました。
frustumCulled={false}: 画面外判定の計算コストをカット。transparent={false}: アルファブレンド(重なり計算)を無効化し、描画速度を劇的に向上。antialias: false: HMDの高解像度を活かし、不要なアンチエイリアス処理を停止。
6. 結び:Wiredへのダイブ
バラバラな映像がひとつの集合体として蠢き、選ばれた情報だけが目の前に立ち現れる。そして用が済めば、再び元の暗闇へと帰還していく。
これまで609件の記事を積み重ねてきたこのアーカイブに、ついに「Protocol Atlas」という新たな実存のレイヤーが追加されました。現実とWiredの境界線を曖昧にするこの装置で、これからも世界の断片を収集し続けていきたいと思っています。