Software Notes — MetaPuppet

世界観と
ゲームの実装

受信した映像・マスクと、Questの手指トラッキングから、参加者を実際に操作する体験をUnity側でどう組み立てているかの記録。

Author清水(ソフトウェア実装担当)
Prologue Scope Note

まえがき

MetaPuppetのUnity側には、普通のVRゲームにはない出力が1つある。ゲーム内の判定結果が、モーターに巻かれたワイヤーを通って、参加者の腕を物理的に引く。画面の中で完結しないのである。

そうなると、設計のあらゆる場所で同じ問いに突き当たる。映像、マスク、姿勢推定、手指トラッキング、音楽。毎フレーム届くこれらの情報のうち、どれを信じて人の体を動かすのか。PC側から届く推定結果は情報量が多いが、遅れることも壊れることもある。Questの手指トラッキングは関節数こそ少ないが、目の前の体を直接測っている。Unity側では、判定とワイヤーはQuestの実測と音楽の時計だけを見る、映像と姿勢推定は表示にしか使わない、と決めた。この振り分けが各章で繰り返し出てくる。

Chapter 01 Stage Direction

体験の進行と音楽の同期

体験は、参加者から見て3つの段階を順番に通る。最初は一人称視点で、自分の手の位置に浮かぶ的だけを見ながらリズムに合わせて手を動かす段階。次に三人称視点に切り替わり、自分の分身である3Dの人形が、同じリズムに合わせて手を動かしているのが見える段階。最後に、その人形が本人の実写映像(PC側のRVMマスキングによる切り抜き映像)に置き換わる段階。3つとも、判定のロジックや的の配置は同じで、見せ方だけが変わる。

一度教えた操作の意味を、後から書き換えていく進行である。この構造はゲームに先行例がある。BioShock(2007)の「Would you kindly?」は、目標を与えられれば実行するというFPSの慣習を何時間も使わせたあとで、その従順なプレイ自体を物語上の操縦として読み替えさせた。The Stanley Parable(2013)は、ナレーターの指示に従うことも逆らうことも含めて、ゲームから指示されるということ自体を素材にしたゲームで、指示に従って体を動かし続ける本作の参加者の状態を考えるとき、いちばん近くにあった。本作で参加者が覚えるのは「音に合わせて手を上げ下げする」という操作だけだが、同じ操作の対象が的、人形、自分の実写と進むにつれ、やっていたことが人形の操作で、最終的には自分自身の身体の操作だったと読み替えられていく。三人称段階で自分の分身を外から眺める作りは、OneShotやUndertaleがプレイヤーとプレイヤーキャラクターを別の存在として扱った設計に連なる。

The Stanley Parable — Launch Trailer(出典: YouTube, stanleyparable)

この3段階の切り替えタイミングは、Unityの通常のフレーム時間(Time.time)ではなく、オーディオの再生時計(AudioSettings.dspTime)[1]を基準に計算している。フレーム時間は描画の重さで簡単にずれるが、音楽の再生時計はハードウェアの音声出力に同期しているため、これを基準にしないと、判定の的と実際に鳴っている音がずれてしまう。一人称段階を32拍、暗転(既定5秒)を挟んで三人称の人形段階を32拍、少し長めの暗転(既定12秒)を挟んで実写段階を96拍(60BPMで96秒)という尺で組んでいる。

PC側から届く実写映像・マスクのストリームが、実写段階の途中で途切れた場合は、判定を止めずに三人称の人形表示へ自動的に戻す作りになっている。見た目の演出が壊れても、参加者が今まさに動かしている手の判定自体は止めない、という優先順位である。

楽曲を、ゲームの拍に合わせて切り出す

会場で流れる音楽は、現在の実装では6つの区間(導入・一人称・人形・実写・結果・終了)に分かれた1本の譜面として組んであり、体験が段階を進めるたびに、映像の切り替わりに合わせて次の区間へ手渡していく。楽曲そのものはSuno AIで制作した3曲で、Kangding Rayの楽曲と『NieR:Automata』のサウンドを参考にしながら生成と選別を繰り返して作った。導入には静かな1曲、一人称から結果までは同じ1曲の別々の箇所、終了には別の短い1曲を当てている。ゲーム側の判定は60BPMで動いているので、本編の曲は原曲の132BPMからピッチを変えずに120BPMへ時間伸縮し、ゲームの1拍が音楽の2拍に1回きっちり重なるようにした。切り出した各区間は小節の頭から始まり、末尾は先頭へ継ぎ目なく戻るループとして畳んである。区間ごとの音色(EQ)や、後半に向けて低域と残響が増していく変化も、Unityの中で毎回計算するのではなく、この切り出し工程であらかじめ音声ファイルに焼き込んでいる。

区間と区間のつなぎ方は、単純な音量のクロスフェードではなく、DJのミキシングで使うEQスワップを真似ている。まず、去っていく側の曲を帯域の狭い遠い音にして、少しだけ息継ぎの間を置く。次に、去る側から低音を先に抜き、来る側は高音だけで入ってきて下へ広がる。低音が二重に鳴る瞬間を作らないためである。交差点では両方をわずかに沈める。終了の区間だけは意図的に解決させず、細く・遠く・少し不安定なまま消えるようにしてある。

ミッドサイドの合唱と、部屋鳴り

切り出し工程で焼き込んでいる処理のうち、いちばん手をかけたのが一人称の区間の合唱の扱いである。原曲には持続する合唱のような帯域(700〜6000Hz)があり、これをそのまま鳴らすと音楽の真上に乗って主張しすぎる。そこでこの帯域だけを取り出し、原音側ではその帯域を中央で7dB下げて場所を空ける。取り出した帯域からは、音程を数セントずつずらした3つの複製(−9・+7・+14セント)を数ミリ秒ずつ遅らせて左右交互に置いた「広げた」層と、1オクターブ上の薄いきらめきを作り、区間の進行とともに4秒から8秒へ伸びていく長い残響へ投げる。この残響をMid(中央)とSide(左右差)に分解し、Sideには100%、Midには30%だけ戻す。周囲の音は2.5dB沈める。こうすると合唱は音楽の上に重なるのではなく、頭の周りで鳴る。

before — 区間EQのみ
after — 合唱帯域をSide側の残響へ
一人称区間の同じ14秒。切り出しツールで、合唱の処理だけを入れずに書き出したものと入れて書き出したもの。ヘッドホンで聴くと、後者は合唱が中央から外れて左右の外側で鳴る

残響は2層に分かれている。1層目は切り出し工程で焼き込む残響で、人形と実写の区間では、進行とともに低域と残響の量(送り量5%から25〜40%へ)と残響の長さが伸びていく変化を音声ファイルに書き込んでいる。2層目はUnityの実行時にかける残響で、こちらは段階ごとの「部屋」を決める。人形の段階は小さな部屋で、残響は短く(1.4秒)、高域を少し落として少し遠くに置く。本人の実写が現れてからは、段階の進行に合わせて部屋がホールへ育っていき、残響は1.5秒から4.5秒へ、送り量も−25dBから−9dBへ連続的に上がる。命中音も同じ部屋の中で鳴る。区間の手渡しでは、去る側の曲を残響の奥へ押し込みながら乾いた音を5dB下げ、実写段階への手渡しだけは、来る側の曲を先に残響だけで聴かせてから本体を入れる。何かが来る気配を先に置くためである。

dry — 残響なし
room — 人形の段階(残響1.4秒)
hall — 実写段階の終盤(残響4.5秒)
人形区間の冒頭12秒に、段階ごとの部屋の設定値を切り出しツール側の残響で当てたもの。実機ではこの変化がUnityの残響フィルターで連続的に起きる

音を、頭の中から舞台の上へ移す

音の置き場所も段階に連動させている。一人称の間、音楽は普通のステレオで頭の中にある。人形段階に入ると、音楽と命中音は人形が立っている舞台の方角へ置き直され、頭を回してもその方向に留まる。距離と部屋鳴りも場面ごとに変えていて、人形の段階では少し遠く小さな部屋で、実写段階では近く、そしてホールが段階の進行とともに広がっていく。命中音も、実写段階では画面の中の本人の体の位置から鳴る。

この定位は、空間音響のプラグインを使わず、音声スレッド上の信号処理だけで作っている。左右の音量差、両耳に届く時間差、遠い側の耳のこもり、頭の後ろに回ったときの鈍り、という4つを組み合わせると、ヘッドホンでも音が頭の周りを回って聞こえる。ただし回転は状態ではなく仕草として扱い、使うのは3つの瞬間だけに絞った。人形へ操作が移る手渡しで1周、本人の実写が現れる場面でゆっくり1周、そして終盤のホログラム崩壊では、崩れ具合に応じて回転が加速する。それ以外の時間は普通のステレオのままである。

不安の処理

音楽の「調子の悪さ」も、参加者が何を見ているかに同期させている。2種類の劣化を音楽に挟めるようにした。1つはテープの回転むらのようなゆっくりした音程の揺れで、暗転から人形へ操作が移る瞬間に一度跳ね上がってから減衰し、人形が自分を写している間はじわじわ増え、本人の実写が現れる場面でピークに達し、実写で遊んでいる間に落ち着いていく。もう1つはローファイな信号崩壊で、サンプルレートを落とし、新しい値へ追いつききれない吃りを入れ、量子化の階調を減らす。これは終盤のホログラム崩壊のためのもので、実写段階の残り十数秒で映像の崩壊と同じ進行度で立ち上がり、結果表示では引き戻すが、完全にきれいな音には戻さない。音源の位置そのものも崩壊の度合いに応じて震えるようにしてある。

仕上げた音の通し試聴(約4分)。導入45秒・一人称32秒・人形37秒・実写108秒・結果6秒・終了12秒という本番の尺で、6つの区間をUnityと同じ順序と長さのフェーダーでつないだもの
  1. Unityのオーディオシステムが内部で持っている、音声再生専用の高精度な時計。AudioSource.PlayScheduled()と組み合わせて使うと、「何フレーム目に鳴らすか」ではなく「その時刻ちょうどに鳴らす」という、フレームレートに左右されない予約ができる。ゲーム全体の時間管理に使うTime.timeとは別の時計である。
Chapter 02 Rhythm Judgment

手の高さで叩くリズムゲーム

リズムゲーム部分の基本構造(譜面データからノーツを生成し、時刻で判定する作り)は、Qiitaの解説記事「音ゲーを創る[基本実装編]」と「Unityで音ゲーを作ろう(ノーツ・譜面編)」を参照して組んだ。譜面を外部データとして持ち、判定と表示を分ける構成はこれらの通りで、本作で違うのは入力がボタンではなく手の高さであること、そして判定の先にワイヤー機構がつながっていることである。

判定の仕組み自体は、一人称・三人称・実写のどの段階でも共通している。参加者は左右の手をQuestのハンドトラッキングで追跡されていて、譜面(あらかじめ決めておいた、拍・左右の手・高さのリストのようなもの)で指定された時刻・手・高さの位置に、手が一定の範囲内で入っていれば「成功」になる。的への接近は、開始と終わりで速度がゼロになる緩急のついた曲線(minimum jerk[1])で動かしており、機械的な等速移動より、人の手の動きに近い自然な加減速に見えるようにしている。

操作の対応付けを体に覚えさせてから、その意味を変える設計は、Brothers: A Tale of Two Sons(2013)が参考になった。左右のスティックを兄と弟それぞれに割り当て、両手で2人を同時に動かす操作をプレイヤーの体に学習させたうえで、物語の進行によって片方の入力が持つ意味を変えてしまうゲームである。本作でも、開始前の較正(両手を静止させ、その高さを基準に的を置く)が決めているのはボタン配置の類ではなく、「この高さに手を上げる」という動作と判定との対応付けで、動作自体は最後まで変わらないまま、その先に付いているものが段階ごとに的から人形、人形から自分の映像へ差し替わっていく。

Brothers: A Tale of Two Sons のスクリーンショット。兄と弟が並んで進む場面
Brothers: A Tale of Two Sons(出典: Steam ストアページ)

譜面は、高さ2段ぶん(20cm)を一気に飛ぶ移動に最低4拍、隣の段への移動に最低2拍の間隔を空ける設計にしている。後述する物理ワイヤー駆動の機構が、それより速くは腕を動かせないためである。

  1. 物体が動き始める瞬間と止まる瞬間、どちらも速度・加速度がゼロになるように設計された動きの曲線。人間の腕の動きの観察からよく使われる近似で、等速直線運動よりも自然な「滑らかに加速し、滑らかに止まる」動きに見える。
Chapter 03 Silhouette as Collider

マスクそのものを当たり判定にする

実写段階では、切り抜かれた本人の映像に当たり判定を付ける必要がある。3Dの人形ならコライダーを付ければ済むが、実写の本人は1枚の映像で、輪郭は毎フレーム変わる。そこで物理エンジンは使わず、判定したい点が映像の画面上でどこに写るかを計算し、その位置のマスク画像(PC側の記録で扱った、RVMが出力する人物シルエット)の画素を読んで、人物の内側かどうかを見るモジュールを書いた。

カメラで抜いたシルエットをそのまま当たり判定に使う作りは、メディアアートに前例が多い。Myron KruegerのVideoplace(1970年代)では、カメラに写った観客の輪郭が画面の中の図形を押したりつかんだりするし、Camille UtterbackとRomy AchituvのText Rain(1999)では、落ちてくる文字が観客のシルエットの上に積もる。どちらも体の形をポリゴンに起こさず、映像の画素をそのまま判定に使っていて、本作の判定もこれと同じ作りである。

Videoplaceの体験風景。スクリーンに映った観客のシルエットがグラフィックと重なっている
Myron Krueger, Videoplace(出典: Ars Electronica Blog "Throwback: Videoplace")

ステレオ映像なので、左目用・右目用それぞれのマスクで同じ点を独立にサンプリングし、両目が同時に「人物あり」と判定して初めて命中とする。これは、片目のマスクだけがノイズで誤反応した場合に、誤判定をそのまま採用してしまわないためのガードである。判定点1つにつき、中心と、その周囲8点のリング状のサンプル点も見て、一定割合(既定50%)以上が命中していれば「衝突」とする設計になっており、マスクの輪郭付近のギザギザした境界で判定が一瞬だけ点滅するような誤反応を抑えている。

Chapter 04 Pose Fusion

Questの手を基準に、映像由来の姿勢を合わせ込む

三人称の人形段階では、参加者の全身の姿勢(肩・肘・腰・膝など)を、PC側の姿勢推定(RTMPose、または予備経路としてのMediaPipe)から受け取って人形に反映している。映像から推定した手の位置と、Questが実測した手の位置は微妙に食い違うので、どちらを使うかを部位ごとに決めてある。ゲームの判定と、後述するワイヤー駆動には常にQuestの実測を使い、映像由来の姿勢は胴体・肘・膝・足の表示を補うためだけに使う。

この2つの座標系(映像由来の骨格と、Questの実測位置)を1つにまとめる処理では、両手の位置と、両手の中点から頭までの向きという3点から、映像側とQuest側それぞれで直交した基準の軸を作り、そこから回転・拡大縮小・平行移動をまとめて求めている。求めた変換を映像側の骨格全体にかけたうえで、頭と両手についてはさらにQuestの実測位置へ強く寄せる。人形の腕や脚の曲げ方自体は、関節を2つ持つ簡易的な逆運動学(IK)[1]で解いており、肘や膝が逆方向に折れてしまわないよう、伸びきる直前で角度を頭打ちにする制限も入れている。

IK調整前の人形。両腕が体の前で交差し、肘があり得ない方向に折れ曲がっている
IKの調整がうまくいく前のスクリーンショット。肘の曲げ方向の制限が効いておらず、両腕が体の前で交差して関節が破綻している。

肘の曲げ方向を決め直す

この破綻は、その後の作り直しで解消している。現在の腕は、肩・肘・手首の2ボーンを解析的に一発で解くソルバに置き換えたうえで、破綻の本当の原因だった「肘がどちらへ張り出すか」を毎フレーム決める部分を作り込んだ。基準になるのは、座って前へ手を伸ばしたときの自然な肘の置き場所(胴体の少し外側・少し下・少し前)で、そこへ姿勢推定が実際に検出した本人の肘の位置を、検出の信頼度に応じて最大85%まで混ぜ込む。つまり人形の肘は、幾何学の帳尻合わせで適当な方向へ折れるのではなく、できる範囲で本人の肘の張り方を写す。

ただしカメラ由来の肘の位置はノイズで暴れるので、3つのガードを挟んでいる。第一に、肘が胴体を突き抜けて内側へ折れ込む方向の成分だけを取り除く。前後や上下の動きはそのまま通すので、本人が肘を上げれば人形の肘も上がる。第二に、腕がほぼ伸びきった状態を経由しない限り、曲げ方向が反対側へ一気に裏返ることを禁止する。冒頭の写真のような交差は、主にこの裏返りが引き起こしていた。第三に、決めた方向は時間方向に平滑化し、フレームごとにぱたぱたと切り替わらないようにする。このほか、手のひらの目標は常に肩より最低10cm前へ押し出し(座った体験で体の後ろへ手を伸ばす場面はない)、腕の伸びも完全に伸びきる手前で頭打ちにしている。

作り直した後の人形。両腕が体の前で自然に曲がり、左右のリングの位置に手が収まっている
作り直した後の同じ人形。肘が胴体の外側へ張り出し、両腕が交差せずにリングへ届いている

腕の位置とリングの同期

リズムゲームの目標として現れる光るリングも、この座標合わせの延長にある。リングの位置は空間に固定の座標として置いているのではなく、体験開始時のキャリブレーションから決まる。開始時にQuestのHMDの向きから水平回転だけを取り出した座標系を固定し、そのとき両手のひらがあった位置を、そのまま左右それぞれの「中段」のリングの位置にする。上下の段はそこから10cm刻みで積む。つまり譜面が指定しているのは「どちらの腕を・どの段まで」だけで、実際にリングが現れる場所は、参加者本人の腕がその瞬間に自然に届く位置から逆算されている。腕の長さや座高が違っても、リングが遠すぎて届かないということが起きない。

判定も、この作りに合わせて高さだけを見る。リングの水平・奥行き座標はキャリブレーション時のまま動かさないので、参加者がやることは腕の上げ下げに限定され、手のひらの高さと目標の高さの差が許容範囲に入っていれば命中になる。リングは手が近づくほど明るくなり、目標を照らすスポットライトの強度もこの距離に連動して変わるので、正解の高さは色と明るさで探れる。

三人称の人形段階では、同じリングを人形側の腕の位置に写して表示する。人形は参加者のほうを向いて座っているため、鏡と同じ提示にしてある。参加者の物理的な左手のリングは画面上でも左側に出るよう、対応する人形のボーンは解剖学的には逆の腕になる。リングの位置は毎フレーム更新するが、移動は補間せず一瞬で切り替える。滑らかに滑らせると、リングが自分の意思で動く物体に見えてしまい、腕との対応が切れて見えるからで、瞬間移動の唐突さは、リングが次の目標として点灯するときのフェードで隠している。

実写段階の体験画面。参加者の背中側の映像の左右に、黄色と赤色の光るリングが浮かんでいる
実写段階のリング。左手側が黄、右手側が赤。リングはキャリブレーション時に本人の手のひらがあった位置を基準に現れる。
  1. Inverse Kinematics(逆運動学)。「肩と手首をこの位置にしたいとき、間の肘は何度に曲げればよいか」を、手先の目標位置から逆算して求める計算。関節が2つ(肘・膝など)だけの単純な鎖であれば、三角形の辺の長さの関係から解析的に一発で解ける。
Chapter 05 Physical Actuation

判定結果を、実際に腕を引くワイヤーへ送る

ここまでの判定はすべて画面の中で完結する話だが、MetaPuppetにはもう一段、物理的な出力がある。左右の手首・肘に対応する4本のワイヤーを、モーターで巻き取る機構が実機として存在し、ゲーム内の衝突判定の結果に応じて、各ワイヤーの張力をUDP経由で毎秒最大60回、マイコン(ESP32)へ送っている。参加者が画面の中の的を外すと、その情報が実際に腕を引く力に変換される。

ゲームの側でこの部分に一番近いのはINSIDE(2016)である。あのゲームには、装置を被せた人間を外から歩かせる仕掛けがゲームメカニクスとして登場し、それを操作しているのは、アバターを外から操作しているプレイヤー自身である。画面の中で人を操る装置と、画面の外のコントローラーが同じ働きをしている。本作はこの関係を物理の側へ延長した。ゲームの判定結果が、画面の効果で終わらず、ワイヤーを通ってプレイヤーの体まで戻ってくる。

INSIDEのキービジュアル。暗い森を歩く少年のシルエット
INSIDE(出典: Steam ストアページ)

計算機の出力を機構で実際の人体まで届けた先行作もある。Marcel·lí Antúnez RocaのEpizoo(1994)では、観客のタッチパネル操作が空気圧の機構を介して作家本人の体を動かす。StelarcのPing BodyとFractal Flesh(1995〜96)では、ネットワーク越しのデータや遠隔地の観客の操作が、電気刺激として作家の筋肉を動かした。真鍋大度のElectric Stimulus to Face(2008)では、音の信号が電気刺激として本人の顔面筋を動かす。いずれも計算機からアクチュエータを経て人体に至る系だが、動かされる体と、動かす入力を出した体は別である。本作では、参加者がゲームに入力した身体運動が、判定を経てワイヤーの張力になり、入力したのと同じ体に戻る。この閉じた輪が「自分自身を、自分自身で操作する」というタイトルの中身である。

Stelarc, Ping Body — Technical Documentation(出典: YouTube, V2_ Lab for the Unstable Media)

物理的に人を操作する装置である以上、安全側の設計にも相応の手当てが要る。装置の起動時には「操作対象が誰も装着していない状態」であることを確認する試験を行い、参加者が両手の親指と人差し指をつまんだ状態を5秒間続けるジェスチャー、またはキーボードのEscapeキーで、いつでも緊急停止できるようにしてある(誤って一瞬つまんだだけでは発動せず、意図して続けたときだけ発動する長さにしてある)。

Chapter 06 Art Direction / Shaders

朽ちた舞台とシェーダー

舞台の見た目について、最初に決めたのは「派手にしない」ことだった。主役は参加者自身の体なので、舞台側は暗くして、動くものを彫像の揺れと光の首振り程度まで減らしている。

空と舞台

空はグラデーションのドームで、地平線が暗い灰、天頂がほとんど黒に近い紫。雲のむらは量を7%程度まで絞って、ごくゆっくり流している。舞台の床や構造物は黒・アイボリー・黄土・赤・青灰の配色で、これはバウハウスの舞台美術から取った。Oskar Schlemmerのトリアディック・バレエ(1922)は、衣装で人間を幾何学的な人形に見立てて踊らせた舞台で、参加者を人形として扱う本作が同じ学校の色を借りるのは筋が通っていると考えた。マテリアルは画像テクスチャを一切使わず、座標から計算で作るノイズ[1]だけで、石の汚れ、表面の粗さのむら、角の摩耗を出している。テクスチャを読まない作りは、Quest単体動作のメモリと帯域の節約を兼ねる。

トリアディック・バレエの舞台写真。幾何学的な衣装のダンサーたち(1923年8月16日)
Oskar Schlemmer, The Triadic Ballet, 1923(出典: schlemmer.org)

この配色とマテリアルは一度で決まったわけではない。制作途中の段階では、バウハウス由来の配色をほぼそのまま置いていて、彩度が高く、石の素材感もまだなかった。そこから計算ノイズで汚れと摩耗を足し、照明を落として彩度を絞り込んでいった。

制作途中の舞台。黄土色の幾何学的な構造物が原色に近い彩度で並んでいる
制作途中の舞台。配色を置いただけの段階で、彩度が高く、マテリアルもフラットなまま。
調整が進んだ後の舞台。石のような汚れとむらのある構造物が暗い照明の中に立つ
調整が進んだ後の同じ舞台。ノイズによる石の汚れと摩耗を加え、照明を落として彩度を絞っている。

背景には彫像(サモトラケのニケやラオコーンなど、パブリックドメインのスキャンモデル)を置いている。動かない人体の造形が立っている舞台のイメージは、ドラッグオンドラグーンの最後の歌の場面に現れる巨大な石像から来ている。

ドラッグオンドラグーン「最後の歌」(ニコニコ動画)

この石像の引用は、正面の舞台だけで終わらない。参加者の背後には、体験中ずっと巨大な頭部の像(プット、天使の子供の像)を置いてある。正面を向いている間は視界に入らないが、振り返れば体験中いつでもそこにいて、参加者を見下ろしている。「あなたを動かしていたのは、本当にあなた自身だったでしょうか」という最後の問いの背後にも、最初からそこにいた大きなものが立っている。

参加者の背後に置かれた巨大な白い頭部像。手前に黒い角柱が浮かび、終了時の文言が重なっている
参加者の背後に置かれた巨大なプット(天使の子供)の頭部。体験中ずっと背後にいて、最後の文言もこの像を背景に現れる

彫像の選び方

舞台に置く彫像は、有名だから選んだわけではなく、それぞれが「体を外から動かされる」という本作の構造のどこかに重なるものを選んでいる。

いちばん直接的なのがラオコーン像である。神罰として送られた蛇に巻き付かれ、体の自由を奪われながらなお抗う人間の構図で、作品そのものが「外からの力で身体を拘束される人物」を表している。指のピンチで自分の腕をワイヤーに引かれる本作の参加者と、置かれている状況が同じである。舞台の中でもっとも大きく、参加者からよく見える位置に据えている。

舞台に置かれたラオコーン像。蛇に巻き付かれた人体が、黒い角柱の間で抗っている
舞台上のラオコーン像。蛇に体を拘束されながら抗う構図が、腕を外から引かれる参加者と重なる

サモトラケのニケは、頭部と両腕を失ったまま、風を受けて前へ踏み出す動きだけが残っている像で、顔も意思も見えないのに体の動きははっきり読める。カメラで切り抜かれ、表情より先に姿勢だけがVRへ届く本作の参加者の姿に近い。アポロン・ベルヴェデーレは、長いあいだ「理想の身体」の基準として引用されてきた像で、参加者の分身である木の人形が、まさにその型に嵌められた匿名の身体であることと対になる。

そして背後のプット(天使の子供)の頭部は、西洋絵画や彫刻で人間の営みを頭上から眺め、ときに矢や糸で人を動かす存在として描かれてきたモチーフである。体験のあいだずっと背後から参加者を見下ろしているこの像に、参加者を動かしていた「見えざる何か」の役を負わせている。

スキャンされた人体が白い像として空間に立つ光景では、RhizomatiksのPerfume Disco-Graphy 25年の軌跡と奇跡(2024)も参照している。ボリュメトリックに記録されたPerfumeの3人が、彫像のような白い姿で過去のパフォーマンスを再演し続ける展示で、静止した石像と生身の体の中間にあるその存在感は、本作の彫像と人形の見せ方に近い。

Perfume Disco-Graphy展の展示風景。白いボリュメトリックスキャンのPerfumeの3人が踊っている
Rhizomatiks, Perfume Disco-Graphy 25年の軌跡と奇跡, 2024(出典: rhizomatiks.com)

彫像は完全には静止させず、振幅4cm・周期50秒で横に揺らしている。見つめないと気づかない速さである。回転も選択肢にはあったが、重い石像がその場で回るのは滑稽に見えるのでやめて、横揺れと上下動だけにした。ライトには十数秒周期で首を振る動きを付けている。

PCVRでは、この光にURP用のボリューメトリックフォグ(CristianQiu氏)を合わせている。空間を薄い霧で満たし、ライトの光がその霧に散乱する量をレイマーチング(視線に沿って少しずつ進みながら霧の濃さを積算していく描画法)で計算するので、光の筋が画面効果ではなく空間の中の体積として立つ。VRだと頭を動かして光の筋を横から覗き込めるため、平面的なグロー効果との差がはっきり出る。煙で満たした部屋の映写光を、触れられそうな立体として見せたAnthony McCallのLine Describing a Cone(1973)の見え方を、リアルタイムの霧でやっている。フォグの濃度は後述する演出強度の数値と連動していて、実写段階に近づくほど濃くなる。Quest単体動作ではこのフォグは重すぎて焚けず、安い近似に差し替えている(第7章)。

Line Describing a Coneの展示風景。煙の中に円錐状の映写光が立体として浮かぶ
Anthony McCall, Line Describing a Cone, 1973(出典: Whitney Museum of American Art)

人形が本人に変わる瞬間のシェーダー

この体験でいちばん演出的に重要なのは、三人称の人形が、本人の実写映像に置き換わる瞬間である。ここは専用のシェーダーを書いた。仕組みは1枚のしきい値マップに集約されている。人形の表面を既定48×48の格子に切り、格子ごとに乱数で固有の値を持たせ、その上にInterleaved Gradient Noise[2]というより細かい規則的なノイズを混ぜて、画素ごとに0から1の値を1つ決める。進行度がその値を超えた画素から、人形の色の代わりに本人の映像が表示される。値の低い画素から先に切り替わるので、序盤はまばらな点の群れ、終盤は面になり、写真の現像に近い見え方になる。しきい値の判定幅は0.04と狭くしてあって、境界がなめらかに溶けずに、粒のまま進む。

細部も2つ足してある。格子の乱数は時間でわずかに揺らしていて、進行が止まっている間も粒がちらちらと入れ替わり続ける。切り替わりつつある境界の帯には薄い青白色をわずかに足していて、いま現像が進んでいる場所だけが少し明るく見える。表示される本人の映像は、PC側のVR表示シェーダーと同じ経路で届くYUVのステレオ映像とRVMマスクで、左右の目で別々のテクスチャを読み、マスクの外側の画素はそもそも現れない。人形の上に「現像」されるのは、切り抜かれた本人だけである。

現像の序盤。人形の両手の部分だけに粒状の実写が現れ始めている 現像の中盤。人形の上半身が格子状の粒に置き換わり、実写と人形が混ざっている 現像の終盤。人形が本人の実写映像にほぼ置き換わり、両手でリングを叩いている
人形が本人に変わる瞬間。両手から粒状に現像が始まり、格子ごとの粒が面になって、本人の実写に置き換わる

照明とポストエフェクトの段階連動

演出の強度は、体験が一人称・人形・実写のどの段階まで進んだかに応じて上がる1つの数値で持っていて、Bloom(光のにじみ)、色調、ビネット(画面周辺の暗さ)、フォグの濃度、舞台照明は毎フレームこの数値から決まる。拍に同期した明滅もこの上に乗る。序盤は沈んだ画で始まり、実写段階で照明ごとピークに達する。個々のエフェクトのタイムラインを手で並べる管理をしたくなかったので、こうした。

実写映像を表示するシェーダーの品質

本人の実写を出す「Stereo Dual Unlit」シェーダーは、左右の目ごとに独立した映像を受け取り、今まさに描画中の目に対応する組を選んで表示する。ここに、後から一連の品質の手直しを入れた。まず色の扱いを正した。届く映像は放送規格(BT.709のビデオレンジ)のYUVで、これを画面向けの非線形なRGBに変換したままUnityの線形色空間へ流し込むと、色が沈み、マスクとの合成でも縁に濁りが出る。輝度・色差の展開をリニアなテクスチャ上で行い、非線形の符号化をほどいてからシーンに返し、マスクによる合成もストレートアルファとして一度だけ掛かるように経路を整理した。あわせて、映像が黄色く転ぶ原因になっていた古い色味の乗算をやめ、明るさを保ったまま中立な色に置き換えている。

輪郭の品質は、追加のテクスチャや描画パスを増やさずに上げている。輝度を中心と上下左右の4点で読み、その差分から軽い先鋭化を掛ける。映像の端やトリム、歪み補正の境界で1画素単位の硬い切れ目が出る問題は、画面上の微分から幅を決めた滑らかな傾斜で置き換え、解像度に依存しない。マスクは既定でしきい値0.55・柔らかさ0.06で切り、不確かな縁だけをわずかに退ける。8ビット出力の階調割れには半LSBぶんのディザを乗せているが、映像が存在しない画素にまで乗るとゴミになるので、有効な画素にだけ掛かるよう門を付けた。露出は、カメラの輝度が既に手元にあるのを利用して、舞台の明るさを超えるハイライトだけを圧縮し、暗い服やシルエットのコントラストは残す。実写段階の最後の3分の1では、本人の像が人形と同じ粗い素材感を少しずつ引き継いでいき、終盤のシェーダー変化を周囲の世界ではなく体の側に置いている。

調整前の実写表示。人物全体が黄緑に転び、輪郭がにじんで光の縁が出ている 調整後の実写表示。色が中立になり、輪郭が締まって舞台に馴染んでいる
調整前(左)と調整後(右)。左は色が黄緑に転び、輪郭がにじんで光の縁が出ている。右は色が中立になり、縁が締まって舞台の光に馴染んでいる

鏡像の扱いにも一つ工夫がある。本人を鏡のように向かい合わせて見せるとき、単に横方向を反転すると立体視の奥行きが裏返る。そこで横反転は必ず左右の目の入れ替えと対にして、奥行きを保ったまま鏡像にしている。最後のノートで手の対応が入れ替わる場面では、像を中央の細い帯へ一度圧縮し、細くなっている間に鏡像の状態を交換して再び広げる。画面全体でぱっと切り替わるのではなく、細い帯の中で入れ替わるので目立たない。

終わりのホログラム崩壊

実写段階の終盤には、本人の像がホログラムのように崩れていく演出を入れている。同じシェーダーに追加した段で、平常時から常に少しだけ「生きている」状態にしてある。細い走査線、インターレースのちらつき、薄い横方向の残像、行ごとのごく小さな揺れ。そこに、たまに短い発作が乗る。何行かの帯が横にちぎれ、まばらなブロックが1マスぶん飛び、色がずれる。発作はゆっくりした包絡で門を掛けてあるので、ほとんどの時間は画は澄んでいる。崩壊の強さは実写段階の残り秒数から0〜1で決まり、最初の数秒はほとんど気づかない程度から、最後は密なちぎれとコマ落ち、画面全体の縦滑り、数フレームの黒落ちまで進む。終盤は輝度を段階化して、映像というより壊れたデータに見えるようにしている。

この演出で気を配ったのは立体視である。ノイズの入力を画面座標にすると、左右の目で別のノイズが出て像が融合せずにぎらつく。そこで乱数の入力はすべて映像面上の座標と時間だけにして、両目に同じ乱れが映像面の奥行きに現れるようにした。乱数も三角関数を使わない整数ハッシュにして、GPUが違っても同じ模様が出て、精度でずれていかないようにしている。ちぎれた帯の縁は約1割の幅で滑らかにつないで、アナログの同期ずれのように像が連続して見えるようにし、境界の行にはヘッドセットでも読める明るい継ぎ目を入れた。さらに、直前数十フレームぶんの輝度とマスクの履歴を保持し、8〜30フレーム遅れた本人の体を今の像の後ろに描く残像も加えている。遅れ幅は固定せず、ゆっくり変化させている。この崩壊は音側の信号崩壊と同じ進行度で駆動され、映像が壊れるほど音も壊れ、音の位置も回転しながら震える。

  1. 画像を使わず、座標を入力とした計算だけで濃淡のむらを作る手法(バリューノイズ)。同じ座標なら常に同じ値が返るため、模様がちらつかず、テクスチャ画像の読み込みも不要になる。
  2. 画面座標だけを入力にした計算で求まる、規則的だが目立つ縞の出にくいノイズ。テクスチャを読まずに1行で書けるため、ディザ(点の密度で濃淡を表す手法)用として広く使われている。
Chapter 07 XR / Rendering

XR側の設定と、会場での負荷対策

この章の設定の大半は、2つの心配から来ている。1つは、会場で体験を止めないこと。本作のフル構成はPCとQuestをつないだPCVRで、人物マスキングも実写段階もPC側のGPUに依存している。会場でPC側に問題が出たときに体験ごと止まってしまわないよう、Quest単体でも動く構成を別に用意してある。もう1つは、そのQuest単体構成をモバイルGPUで毎秒72フレームに収めること。VRではフレーム落ちがそのまま酔いにつながるうえ、本作は音楽に合わせて体を動かしてもらう体験なので、絵がつかえると判定の数字より先に体感が崩れる。

映像とマスクを、GPUから降ろさずに使う

PC側から届く映像とマスクを、Unity側でどう受け取っているかにも触れておく。処理の本体は通信インフラの記録の第5章に書いたとおりで、デコードされた左右2枚の映像(NV12)はGPU上のDirect3D 11テクスチャのまま前処理を受け、CUDAと相互運用するバッファを通ってRVMの推論に入り、出てきたマスクもGPU上でぼかしと時間方向の平滑化を受けたあと、テクスチャとしてそのままUnityへ渡る。この経路では、映像もマスクも一度もCPUのメモリに戻らない。Unity側の実写表示シェーダーは、左右の目それぞれについて輝度と色差の面とマスクの面を直接読むだけで、映像をUnityのテクスチャへコピーし直す工程を持たない。

この作りがUnity側の設計に効いているのは、実写段階の「軽さ」である。本人の像を描くコストは、シェーダーが数枚の面を読む分だけで、映像の解像度が上がっても描画側の負担は変わらない。マスクを当たり判定に使う処理(第3章)も、姿勢推定が届かないときにQuestの手で動き続ける作り(第4章)も、映像とマスクが「毎フレームGPUに置かれているテクスチャ」であることを前提にしている。姿勢推定の結果だけは関節位置の小さなパケットとしてCPUに届き、人形の骨格へ渡る。大きなデータはGPUに留め、小さなデータだけをCPUで扱う、という分け方である。

XR周りはOpenXR[1]を土台に、Metaの提供する拡張機能、手指トラッキング用のパッケージ、XR Interaction Toolkitを組み合わせて構成している。ステレオ描画は、PC側の記録の第6章で触れたシングルパス・インスタンシング(1回の描画命令で両目分を描く方式)を、Android・PC双方の描画設定で使っている。VRは同じ場面を左右の目で2回描くので、この描画命令の重複をつぶすのが負荷対策の出発点になる。

映像の合成はComposition Layers[2]を使う案もあったが、結局使わず、通常の板ポリゴンとシェーダーで行っている。

Quest単体動作では、フォベーテッドレンダリング[3]を有効にし、レンダースケールも0.8に落としている。参加者の視線はゲーム中ほぼ的と自分の手に集中するので、視界の周辺の解像度を落としても気づかれにくい、という読みである。削って一番惜しかったのはフォグで、第6章の光の筋はボリューメトリックフォグがあってこそなのだが、Questで毎フレーム焚くには重すぎた。単体動作では計算の安い指数関数フォグと、数を32個までに絞ったパーティクルで近い見た目を作っている。

PC接続時(PCVR)のコマ落ちは事情が違って、原因がRVMの推論なのかUnityの描画なのかで対処が変わる。推論が重いなら解像度設定を下げ、描画が重いならエフェクトを削る。切り分けのため、推論時間と描画負荷は別々に計測できるようにしてある。

Quest単体動作の代償は、体験の最終段階である。PC側のRVM推論が無いので実写段階には進めず、三人称の人形段階までで構成が止まる。会場で確実に動く構成を優先した結果として、受け入れている。

  1. VRヘッドセットのメーカーごとに異なっていたAPIを統一するための、業界標準の仕様。OpenXR対応のアプリは、対応しているヘッドセットであればメーカーを問わず動く。
  2. 通常、VRの映像はUnityが1枚の画像として毎フレーム描画してからヘッドセットに渡すが、Composition Layersは特定の平面や動画だけをOpenXRのランタイム側に直接渡し、ヘッドセット側で合成させる仕組み。負荷を下げたり、文字などをより鮮明に見せたりする用途で使われる。
  3. 人間の目は視界の中心以外の解像度低下に気づきにくいことを利用し、視線の中心から離れた領域のレンダリング解像度を意図的に落として負荷を下げる技術。
Epilogue Summary

あとがき

Unity側を書いていておもしろかったのは、譜面の設計にワイヤーの可動速度がそのまま顔を出すところだった。譜面を書く手が、モーターの巻き取り速度に縛られる。ゲームのルールと機械の都合が同じファイルに並ぶコードは、この作品を作らなければ書く機会がなかったと思う。

普通のリズムゲームなら、譜面は音楽と難易度だけを見て書けばいい。隣の段へ2拍、2段飛びに4拍という本作の間隔は、参加者の反応速度から来た数字ではなく、モーターがドラムに巻き取れる速さと、腕が急に引かれないよう加速度に上限を掛けた結果として、腕がその高さへ物理的に到達できる最短時間から逆算した数字である。ノートを一つ詰めようとすると、その先に必ず「そのとき機構は間に合うか」という問いが立つ。ゲームを面白くする作業と、人の腕を安全に動かす作業が、同じ譜面データの上で綱引きをしていた。

同じことは判定の側にもあった。手の高さだけを見る単純な判定に落ち着いたのは、遊びやすさのためだけではない。判定が水平方向の位置まで問うと、ワイヤーが腕を引く方向と参加者が腕を動かしたい方向が食い違う場面が生まれ、機構と本人が体の主導権を奪い合うことになる。上下だけにすれば、ワイヤーが引く方向と譜面が求める方向は常に一致する。ルールを削ったのは、機械と体を喧嘩させないためだった。

この作品を作る前は、ゲームのコードと機械のコードは別の層にあるものだと思っていた。ゲームは判定を出し、機械はそれを受け取って動く、という一方通行の関係である。実際に書いてみると、機械の都合は判定の設計にも、譜面の書き方にも、音楽の切り出し方にまで遡ってきた。参加者の体を実際に動かすということは、参加者の体のほうが設計のいちばん上流にいるということだった。この上流に立つのが自分の体ではなく参加者の体だという点が、この作品を作っていていちばん緊張したところであり、いちばんおもしろかったところでもある。

MetaPuppet — Unity Implementation Notes
MetaPuppet