超歌舞伎に登場する初音ミクさんの美麗な舞を高品質なままMicrosoft HoloLensで鑑賞する技術

DCEXPOでの展示の様子

TL;DR(とても長いのでまとめ)

HoloLensの3D計算能力は限られているので、美麗なミクさんを美麗なまま鑑賞するために細々とした工夫をしたよ、という話。

ドワンゴ×HoloLens

ドワンゴでAR/VR/イベント演出システムなどの開発を担当している先端演出技術開発セクションの岩城(MIRO)です。

ドワンゴではHoloLensを使ったライブ体験を提供するための技術開発を継続的に行っています。2017年4月にはN高等学校の入学式において、75台のHoloLensを同期沖縄の本校にいる校長先生を六本木ニコファーレに出現させ、式に遠隔でご参加いただくといった試みも実施しました。

N高入学式の様子1
N高入学式の様子2

これらのHoloLens関連技術は先日「Innovative Technologies+」に採択され、日本科学未来館で技術展示をさせていただきました。実はこの展示では(校長先生の式辞ではなく)「超歌舞伎 花街詞合鏡(くるわことばあわせかがみ) 」に登場した初音ミクさん(※初音太夫)の舞をごらんいただくことにしたのですが、この「ミクさんをHoloLensで出す」という裏側には結構いろいろな工夫をしていました。 本記事では、この「超歌舞伎に登場した初音ミクさんの美麗な舞」を「HoloLensでなるべく高品質に」鑑賞するためにあらたに盛り込んだ工夫について解説します。

Microsoft HoloLensのもつパフォーマンス

HoloLensはPCなどを使った他の「VR」ヘッドセットなどと違い、HoloLensそれ自身が単体で動作する単体のコンピュータです。HoloLens自身にセンサ・プロセッサ・バッテリー・ディスプレイがすべて含まれており、自身で自分の位置をつねに追跡し、自分の位置から見えるべき仮想空間の物体を計算・現実世界に重ね合わせて表示します。 これは言い換えるとすべての(表示に必要な)計算能力はHoloLens上にあるチップを使わなければならないということであり、つまりは強力なCPUやGPUを使って力業で品質を上げるという手段が使えないということでもあります。

HoloLensの能力の真骨頂はそれがもつセンサと、センサに高度に結合された恐るべき精度のトラッキング(位置追跡)、そしてトラッキングから超低遅延で表示に反映するシステム、さらにはそれを統合したOSであって、3Dの表示能力自体は正直いまひとつなのが現実。3Dまわりのレンダリング能力は数世代前の携帯電話程度と思っていただければしっくりくるでしょう。それで秒60フレームのレンダリングを死守しなければならない、といえば大変さが少しイメージできるでしょうか。

たとえばこちらの記事ではダンスモーションのキャラクタを表示するのに2000ポリゴンまで削減したモデルで秒30フレームという結果が出ています。 また、リアルタイムに動かすためのキャラクターモデルであるUnityちゃん約1万6000ポリゴン。だいたい相場感としてはこのあたりが表示上の限界といったところでしょうか。

超歌舞伎ミクさんを出したい、とは言ったものの…

さて、そんなHoloLensで超歌舞伎のミクさんを見たい…!と思うのですが…

超歌舞伎ミクさんBefore

こちらのモデル、実は約17万ポリゴン、約4000個のボーンがあります。もともとリアルタイムに動かすことを想定しているモデルなので極端なハイポリゴンではないのですが、それでも約17万ポリゴン! さらにはボーン(※CGモデルを動かすための軸となる「骨」のこと)の数は通常のキャラクターモデルと数の桁が違います。これはミクさんが着ている着物を繊細に動かすためのもの。細やかな着物の布の動きをこれで再現しているわけなのです。 そういったデータも含めると…パワフルなGPUを持つパソコンならともかく、HoloLensで出すのはかなりの無理ゲー感があります…。

とはいえまずはできるところから。 まずポリゴン数はもっと減らせるんじゃないか…というわけで、CGデザイナーさんにお願いしてみます。

「このミクさんHoloLensで出したいのでポリゴン数減らしてほしいんですけど…」 「無理ですねー」 「ギャー!!

聞けば繊細な布の動きを再現するためにかなりのポリゴン数を割いており、ここは単純にポリゴンを減らしてしまうとシミュレーションが破綻し突き抜けてしまったり荒れたりしてしまうとのこと。ポリゴンを減らしたあとに再度全フレーム細かくチェックして手で修正していけばなんとかなるけれども、かなり時間も工数もかかる…。

仕方ないので着物部分のポリゴン数削減はすっぱりあきらめて、それ以外の部分で頑張っていただきました。ミクさんの髪飾りなど細かいところも細部まで作り込んでいたので、そのあたりのポリゴンを削って(※見た目はほとんど変わらない)着物部分は手を触れず。

超歌舞伎ミクさんAfter

結果… 約7.7万ポリゴン(約6万頂点)に減りました! やったね!

でも「2万ポリゴンでもカツカツ」なHoloLens。まだまだ工夫しなければ歌舞伎ミクさんはきれいに出ません。さあがんばろう。 ※ここからかなり専門的な話になります※

STEP1: スキニング計算をやめる(モーションの事前焼き込み)

次に膨大なスキニング計算をばっさり削ります。キャラクタの実在感を高めるための手法としてよく 「見ている人を認識して自然に反応する」ことが良いと言われています。が、今回はやろうとしているのが「歌舞伎の演目の再現」。生の「超歌舞伎」舞台では歌舞伎役者さんの間を読んで動かす必要があるためリアルタイムに動くこともありますが、今回は舞台の出演者たるミクさんが観客の動きに直接的に反応しなくとも特に不自然ではありません。(今回に限り)動きはリアルタイムに計算するのでなく、もう先に決めてしまいましょう

というわけで、4000本のボーンによる複雑な動きはすべて事前計算、計算済の情報をすべての頂点・すべてのフレームぶんデータとして持っておくことにします。アニメーションは2分33秒ですから、6万頂点×4650フレーム(秒30フレーム換算)でおおよそ8.8GB。HoloLensの端末ストレージには充分おさまります。 このようにフレームごとに全頂点ぶんのデータを焼き込む形式としては「Alembic」というファイル形式が知られています。元のアニメーションをAlembicに出力し、そのデータをマスターとしてHoloLensに持ち込むことにします。

STEP2: ファイルI/O・頂点ストリームの最適化

これで膨大なスキニング計算は要らなくなったわけですが、かわりに登場するのが膨大な頂点位置データ。事前に確認したところHoloLensの内部ストレージはそこまで遅くはなかったので充分速度としては読み切れるのですが、再生が引っかかると興ざめです。なので、ファイルのキャッシングも含めた頂点ストリーム読み出し部分を自力で作ります。

もともとAlembic形式はAlembic ImporterというUnity向けのプラグインが提供されているのですが、Alembicそのままでは使い勝手が悪かったこともありいったんオレオレフォーマットに変換したあとでDocuments領域に独自形式のデータを持っています。

Index, UVは全フレーム共通なので各フレームには持たず、Position, Normalだけがアニメーションし、そのPosition・Normalもfloatではなく固定小数(-2.0fから2.0fの範囲をUInt16.Maxで分割)にして持つなど細かくファイルサイズが小さくなる工夫をしています。このデータがでかかったりアプリケーション埋め込みになったりすると各HoloLens端末へのデプロイがとても大変なので地味にだいじなのです(当初8.8GBが最終的には2.5GBくらいになりました)。

当初は頂点情報の圧縮も検討したのですが、圧縮率を高めてファイルサイズを減らすよりもここはHoloLensでのCPU時間のほうが貴重!という結論になったのでした。

STEP3: レンダリングの最適化

レンダリングもがっつり最適化。

  • メインの光源は仮想点光源x2(自前のシェーダで照明ごとにパスを分けず、まとめて処理します。BRDFは物理ベースです。)
  • 環境光も追加(ドワンゴが実施しているARライブで使用する「リアルタイムの照明反映」システム用魚眼センサからの情報(の一部)にあたります。今回はセンサを置かなかったので固定の情報を使いましたが、リアルタイムでも流し込めます。照明のレンジは一応、HDRです。)
  • 一部、Metallic-Smoothnessマップ対応(着物の箔押し部分が一番目を引く部分なので、ここは欠かせない!)
  • 一部、AmbientOcclusionマップ対応。(Hololensでのリアルタイムシャドウは厳しいので、事前に焼き込むAOは結構大事だと思います。影大事。でも、暗くしすぎるとHololensでは薄くなるので注意。)
  • Linear⇔sRGB変換はシェーダ内で行い、Linear色空間で計算しています。(Unity上の色空間の設定でLinearを選ぶと、Hololensの画面が真っ暗になったため、設定上はGammaを選択せざるを得ませんでした。)

STEP4: 細かい実装の最適化

ここまで出来てくると、あとは完全に「細かい最適化」が大事になってきます。プロファイラとにらめっこしながら、CPU・GPUともにボトルネックになっているところを次々と潰していく感じですね。 まずCPUは処理スレッドをきちんとわけて、メインスレッドのブロックが発生しないようにします。基本。

  • IOスレッド(バイト列切り出し)。リクエストされたフレームに応じてシークする。10フレームほど先読みする。1フレーム16ms以内に終わる必要あり
  • デコードスレッド(バイト列からVector3の配列への変換)。IOスレッドの出力を即座に変換する。1フレーム16ms以内に終わる必要あり
  • Monitor.WaitとMonitor.Pulseでエンキューされるまで待機するキューを作成して複数スレッドを連携させている(N校のGearVRのJpegDecoderのところでも使った)
  • GCが発生しないようにスレッド間の受け渡しに使うバッファを使いまわして循環させる
  • byte[]からVector3[]への展開にGCHandle.Alloc(dataArray, GCHandleType.Pinned)からIntPtrを得てMarshal.Copy(byte[], IntPtr)している(memcpy的)
  • 毎フレーム実行するMesh.vertices, normalsへの代入は意外と速い

また、アニメーションのフレームは30fpsで持っていますが、これを内部で補間し60fpsで再生しています。Position, Normalのトポロジが不変であることを活かして各頂点を補間しています。 この補間はC#上でLerpなどで素直に実装すると非常に重い(new Vector3やVector3.Lerpが重い)ので、補間するだけのネイティブDLLを作り呼び出しています。やはり一番速度が欲しいところはネイティブで。

STEP5: レンダリング解像度を動的に下げる

ここまでの最適化で、 レンダリングは(歌舞伎ミクさんが全身見えるくらい離れた位置からならば)60fpsを維持できる ようになりました。 そう、「歌舞伎ミクさんが全身見えるくらい離れた位置からならば」。HoloLens最後のボトルネックは「ピクセルフィルレート」。歌舞伎ミクさんに近づいていくと(=ミクさんの表示面積が大きくなると)描画が追いつかずフレームレートがどうしても下がってしまうのです。

これは最終的にこうしました

  • HoloLensではCGの画面占有率が上がるとFillRateが厳しい。ミクさんに近づくと動的にXR.renderViewportScaleを下げることでフレームレートを維持する

ミクさんに近づくにつれて動的にレンダリング解像度が下がるようにしました。これは段階的に(離散的に)変わるのではなく、徐々に変化します。最も近づいたときにはrenderViewportScale=0.4くらい、つまり768x432くらいのレンダリング解像度に下がります。が、これミクさんがアップになるにつれ解像度が下がることになるため意識して見ていてもほとんどわからないです。

これでどこから見てもレンダリングもアニメーションも60fps実現!やった!!!

STEP6: 舞台セットの工夫

ソフトウェア側ではやることはやりきったので、あとは「それをどう見せるか」にも工夫!これをやるかどうかで「実在感」の印象はだいぶ違います。

  • 舞台セット自体をきちんと空間演出することで雰囲気をつくる。今回は屏風柄の背景や舞台などをきちんとセットとして作りました
  • 照明をコントロールし連動。いままでドワンゴで実施するARライブは「照明状態をセンサで取得しCGで再現」というアプローチが多かったのですが、今回は照明の明滅をコントロールし、同じ情報をCG側で再現することで実在する照明とHoloLens上のミクさんの照明環境をあわせました。
  • カメラ映像にはより高品質なレンダリング。HoloLens上のミクさんはがんばったとはいえやはりサブセット。その様子を(通りがかりの人にも)見ていただく外部モニターには全力でレンダリングしたミクさんを表示しました。

結果として…

超歌舞伎ミクさん(HoloLens実機録画)
  • 元は17万ポリゴン、リダクション済で7.7万ポリゴンの着物姿のミクさんアニメーションが
  • 舞台照明と連動したライティングを活かしつつ
  • HoloLens実機上で

アニメーション60fps、レンダリング60fpsが安定して出て、舞台演出も込みでHoloLensならではの実在感が楽しめるようになりました。各種演出や外部ARシステム・プロジェクタ投影との同期、アンカー管理・システムのヘルスチェック、また安定化平面のハンドリングなど、今回解説した「ミクさんを表示するための技術」以外のHoloLensの基本的な取り扱いに関してはDAHLESという仕組みの上にこのレンダリングを乗せることで別途おさえています。

「HoloLensだからこんなもん」で諦めずにきちんと工夫すれば意外とちゃんとした絵が出せるんだ!というのがおわかりいただけたでしょうか。

このミクさんに会いたい!

年末年始(2017年12月27日(水)〜2018年1月4日(木))、池袋西武本店7階催事場で開催される「歌舞伎の世界展」の一角で本技術を体験いただけます。デジタルコンテンツEXPOでの展示からさらにチューニングが進んでいますので、もしご興味がありましたらぜひどうぞ。