Spherical Image Capture in VR

# はじめに

この記事は [Unreal Engine 4 (UE4) Advent Calendar 2016 ](http://qiita.com/advent-calendar/2016/ue4) 17日目の記事です。

UE4を用いて全天球画像を撮影する方法について、いくつか紹介します。また、そのうちの一つの方法でVR内でリアルタイムに全天球キャプチャを活用する方法とファイルへの保存についてをまとめます。

## デモ動画

**Theta in VR Play Movie**
[![Theta in VR Play Movie](http://img.youtube.com/vi/Pkh3ZekwoCs/0.jpg)](http://www.youtube.com/watch?v=Pkh3ZekwoCs)
https://youtu.be/Pkh3ZekwoCs

VR内で全天球画像を活用したデモです。ポイントはVR内でリアルタイムに活用できている点です。また、VR内で撮影した全天球画像をファイルに保存して別のサービスに投稿することも可能です。([投稿例はこちら] (https://theta360.com/s/mQsQAZoIJGe6mayYx5FI1peNQ) )

※ この動画は [ここで解説されている方法](https://www.youtube.com/watch?v=IHBOjoEt_Yk) で、HTC Viveでもプレイ画面をフルスクリーン表示にしてキャプチャしました。

# 全天球画像の撮影方法

いくつかの撮影方法がありますが、それぞれに制約があります。簡単に各方法を紹介します。

## Nvidia Ansel Photography Plugin

Ansel は NVIDIA の提供するゲームキャプチャツールです。撮影方式やフィルター、解像度などをシンプルなインターフェースで指定して利用することが出来ます。

UE4.14からプラグイン対応もしており、簡単にゲームに組み込むことが出来ます。美麗なグラフィクスのゲームの画像をユーザーが好きなように撮れるのは大きな価値があると思います。

しかし、現在のところVR内では活用できないこと、キャプチャの体験がゲームの体験とは切り離された体験になるために利用シーンを選びます。

利用手順についてはこちらを参照ください: https://docs.unrealengine.com/latest/INT/Engine/Plugins/Ansel/Testing/

## Stereo Panoramic Movie Capture

GDC 2016 のデモで行われた、リアルタイムに表情をキャプチャしたデモムービーは衝撃的でした。 https://www.unrealengine.com/ja/blog/gdc-2016-a-glimpse-at-the-real-time-future

上記デモムービーの[ステレオスコピック 360 度キャプチャー版](https://www.youtube.com/watch?v=1RKOb33tpD4)も公開されており、このムービーの作成に Stereo Panoramic Movie Capture が使用されています。

最低限の利用手順としては Plugin を有効にして、ExecuteConsoleCommand等で SP.OutputDir などのパラメタを設定して、SP.PanoramicScreenshot を実行します。

この記事で利用方法や技術の概要について解説されています。https://www.unrealengine.com/ja/blog/capturing-stereoscopic-360-screenshots-videos-movies-unreal-engine-4

VRでも利用でき、高品質な静止画や動画を撮ることが出来ますが、ある程度の長い時間(設定にも依りますが、1分程度など) 処理が停止してしまうため、VR体験の中で活用するのは厳しいです。また、利用時の注意点として Instanced Stereo を無効にしている必要があります。下記のエラーが出る場合には、Project Settings > Rendering で VR > Instanced Stereoを Off にする必要があります。

> log stereopanorama error panoramic capture not supported with instanced stereo rendering enabled

※ Unreal Engine 4.11から、各メッシュを左右両画面にまとめて描いてドローコールを半減させる最適化機能が入っており、この機能が有効だと、Plugin が動作しません。

## Scene Capture Component

ヒストリアさんがブログで紹介している [360°動画の作り方](http://historia.co.jp/archives/4653) で使用しているのがこのコンポーネントです。ブログでは SceneCaptureComponentCube 設定後にMatinee/Sequencer経由で連番静止画を出力し、動画に仕上げています。

このブログで解説されているように、一度平面に描画したものを撮影しなおしたり、マテリアルでカスタムノードを設定するなど、ある程度複雑な手順が必要になりますが、解像度をある程度に抑えておけば、VR空間内でリアルタイムに利用するのに耐えるものにすることができます。

また、出力をシーケンサーのカメラではなく CinematicCamera などを経由して ExportRenderTarget を行うことで、静止画単体の出力をVR体験に組み込むこともできます。（ファイル形式については後述します）

今回のデモでは、この方式で実装を行いました。

# サンプル実装と使い方

github に実装サンプルを置きました。（VRTemplateに組み込んだ例も追加しました）
https://github.com/sandinist/SphericalCaptureUE4

githubにも書きましたが、サンプルの使用方法について簡単に説明します。

1. Content/SphericalCapture を 自プロジェクトの Content 以下にコピーしてください。

2. 撮影したい位置のオブジェクトに SceneCaptureComponentCube を追加して、下記の設定を行ってください
  * Texture Target に CubeRenderTarget を追加
  * Capture Every Frame を Off
  * Capture on Movement を Off
  * Auto Activate を Off

3. BluePrint で下例のように呼び出しを行ってください。
![saveHDR](https://raw.githubusercontent.com/sandinist/SphericalCaptureUE4/master/Images/Call.png)

例ではVRTemplateを元にして、MotionControllerPawn のカメラに追加しています。トリガーのボタンは適当です。

BP上部でCapture の更新を行います。上部を実行するだけで CubeRenderTarget_Mat が更新されるので、ゲーム内で使うだけでしたら上部のみでOKです。VRTemplateで適当なキューブのマテリアルに設定すると、こんな感じで更新されます。

![sc2.gif](https://qiita-image-store.s3.amazonaws.com/0/2798/d04a89df-d242-8765-59e1-20b81b237236.gif)

BP下部を実行すると、図の例だと実行ファイルの3つ上のディレクトリにファイルを保存します。Editorから実行している場合はデフォルトでは "C:\Program Files (x86)\Epic Games\4.14" 配下です。ファイルの形式は .hdr です。ファイル出力時にサンプル実装の画像サイズ(2048x1024)で一瞬固まるので、保存はユーザーアクションを起点にするのが良いと思います。（テクスチャの更新だけなら、支障をきたさないレベルです）

4.保存したファイルを編集する

.hdr のファイルはWindowsですと、XnViewなどで開けます。ヒストリアさんのブログにあったようにポストプロセスなどが効いていない状態になるので暗い状態で出力されます。XnViewではツールバー>画像>修正>明るさ/コントラスト… を選んでガンマを2~2.5くらいにすると元の画像に近い形になると思います。

![出力例](https://qiita-image-store.s3.amazonaws.com/0/2798/7d784bf9-71c2-3de2-deff-cfc22b2b82a9.jpeg)


# まとめ

全天球画像をVR内でキャプチャしてリアルタイムにゲーム内で使えること、キャプチャした画像をローカルに保存できることを示しました。

実装の解説までしたかったのですが、かなり長くなるので今回はサンプルとその使い方の解説とさせていただきました。Oculus Rift CV1, HTC Vive どちらでも動作を確認しています。

明日は @katze_7514 さんの「たぶん、BPの何か」です。