UnityでまともなMovieTextureを作りたい

この記事は、調べものをした途中の過程を記録する物で、成果物がある訳ではありません。

概要

Unity上での動画再生は、歴史的な経緯によりデスクトップ版ではQuickTime Playerを用いた再生を行っています。
つまり、大雑把に言うと*.movファイルをムービーテクスチャとして使用できます。
しかしQuickTime Playerはイマドキの主流であるGPUデコードには消極的で、CPUデコードを行っています(調査不足の可能性有り、何らかの最適なエンコードを行えば可能?)

その為、例えば4k2kの60FPS動画を再生すると、いまどきのCPUが1コアフル占有してコマが落ちる、と言う状況です。

多くの場合は、動画解像度を下げたり、30FPSにすることで対処出来ますが、例えばOculusRift DK2(75Hz)で全周動画を再生する、と言うシチュエーションでは、非常に困ります。

これを何とかする為の定番の方法と、現在調査中の方法をまとめます。

定番の手法

UE4+Windowsの例

Windows Media Foundationを用いた動画のGPUデコードが実装されています。

Unity+モバイル端末の例

例えばAndroidならSoCに動画のGPUデコード機能が入っており、android.mediaplayerクラスを利用することで再生が行えます。
Unity用のandroidのネイティブプラグインを書いて、このmediaplayerクラスの再生中のバッファをGLのテクスチャにバインドする。という事を行えば、Exsonys7xxx番代やSnapdragon810などで4k2kの動画がコマ落ちなくUnity上で再生出来ます。
こういった処理は、UnityのアセットであるEasyMovieTexture(30ドル)を買うと、ネイティブプラグイン部分のソースコードも同梱されているので改造し放題です。

うーん、Androidって凄い…

Unity+Windowsの例

http://www.renderheads.com/portfolio/UnityAVProWindowsMedia/ というアセットを使うことで、GPUデコード機能付きの再生が行えます。また、このアセットは外部の動画ファイルの動的読み込みにも対応しているため、Unity製の動画プレーヤーを作るような用途にも使えます。素晴らしい!

ただし、このアセットが200ドルします。うーん…お高い… そして全然Unity標準のMovieTextureと作法が異なるので、例えばAndroidWindows両対応みたいな事をする時に、結構大変そうです。

今回の提案手法

NVIDIAのCUDA実装の動画のGPUデコードを利用して、直接DX11のテクスチャバッファに動画の絵を毎フレーム書き込むネイティブプラグインを作成したいです。

これは、上記UnityAVProの機能限定(そしてNVIDIA GPU限定)版になる代わりに、再生負荷が低く出来る予感がします。

OpenCV 3.0.0rc1 のソースやサンプルを見てみると (@dandelion1124 さん 超助かりました!教えてくれてありがとうございます) BUILD_opencv_cudacodecとWITH_NVCUVIDをONにしてOpenCVをビルドして

Cudaを使った動画再生 https://github.com/Itseez/opencv/blob/master/samples/gpu/video_reader.cpp DX11テクスチャへの書き込み https://github.com/Itseez/opencv/blob/master/samples/directx/d3d11_interop.cpp を組み合わせたネイティブプラグインを作成して

Unity側で TextureのGetNativeTexturePtrをプラグインに受け渡してやる http://docs.unity3d.com/ScriptReference/Texture.GetNativeTexturePtr.html

という感じで 、望む物が出来そうな気がします。

OpenCVを使っているのは、単純に全部入りで楽そうだなあ、と思っただけなので、CUDAとDX11を生で叩いても同じ事が出来ると思います。(ウーン、UnityがOpenGLモードだと、もっと簡単な気がします。OpenCVやCudaとOpenGL仲良いですしね。でもOculusRiftのSDKはDirectX11ネイティブ対応なので、今回はDX11ですねえ)

残念ながら直近でまとまった時間が取れ無さそうなので、ここまで調べた時点で力尽きてしまいました。

しかし、UnityのMovieTextureは、大いに改善の余地がありそうなので、例えばCUDAじゃなくてOpenCLを使って汎用的な動画のGPUデコードなどが出来るアセットとかが50ドルくらいで売ってたら、人気になりそうですね。

どなたか、作りませんか!と提案してこの記事は終わります。

追記:MP4デコーダをCUDAのSDK提供のまま使って、アセット作って売るぞ!と言う場合は、一度NVIDIAの人にお伺いを立てたほうが良さそうです。うーん、知財周りは大変・・・

Gear VR向けの全周動画コンテンツの作成と宣伝

概要

Oculus VR社とSamusung社の協業によって、Gear VRと言うOculus社の品質を満たす高性能なスマホスロットインHMDシステムが発売されています。
最近は日本のキャリアでも該当機種を扱う(Galaxy s6シリーズ)為、国内での入手性も良いです。

この Gear VR向けコンテンツを、実写パノラマ動画で作っています。そのまま流すだけならmediaplayerで行けますが、選択肢で分岐したりループ制御やエフェクトがあるコンテンツを作る場合はUnity等のゲームエンジンを用いるのが良いと思います。

参考までに、このエントリでは僕が今お手伝いしているチーム(コンテンツ)のワークフローについて説明します。今後同じような事をする方の参考になれば嬉しいです。

環境

  • GoPro 6台マウント
  • Autopano Video Pro
  • VFX(After Effects,Nuke)
  • Unity5.0.0p2
  • OculusMobileSDK5.0.1
  • EasyMovieTexture 1.30

太字で書いた物はUnityアセットです。Unityではモバイル向け環境でのMovieTextureをサポートしていません。
その為にAndroid上でUnityを使って全周動画を球のメッシュに張り付けて再生する、と言うコンテンツの場合は太字で書いたEasyMovieTextureの助けを借りる必要があります。

この辺りの作成手順やソフトウェアについてはユニティの中の人の @warapuri さんが詳しいです。

www.slideshare.net

ワークフロー上の問題

チームの簡単なワークフロー図は以下の通りです。僕はUnityチームとして参加しています。 f:id:izm_11:20150502140959j:plain 今回は、Gear VR上で出来るだけ高解像度の動画素材を使いたいので 2880x1440 (30FPS)のH264(5.0 High Profile)のmp4を使う、と言う事になりました。

この解像度とプロファイルのmp4は、UnityEditor上でプレビューが出来ませんでした。また、EasyMovieTextureを使ったシーンでは、 該当アセット内のスクリプトのプラットフォーム分岐 #if UNITY_EDITIOR の中身が空っぽだったので、上図で言う赤い矢印の、UnityEditor上でのプレビュー確認が出来ません。

毎回Gear VRにビルドして転送して確認すると言う、人道的ではない開発を行う羽目になるのは嫌なので、ちょっとした工夫をして楽をします。

エディタ拡張による改善

バッチエンコードエンジン

Unityのエディタ拡張で、ffmpegのプロジェクト専用フロントエンドを作成しました。 f:id:izm_11:20150502011659j:plain こんな感じのGUIで、吐き出すのは一番UnityEditor上で負荷が低く、再インポートが速い theora(*.ogv)形式です。

EasyMovieTextureの書き換え

動画ファイルを扱うスクリプトの、空っぽだったUnityEditor上の処理を一通り書きました。
また、再生予定のファイルが例の巨大なmp4ファイルだった場合、自動的にパスを検索してエディタプレビュー用にバッチエンコードしたtheora形式の動画ファイルに動的に差し替える処理を追加しました。

この時、Movietextureを動的に読み込むために、theora形式の動画ファイルは /Assets/Resources以下に配置する必要があります。

また、HMD上でのプレビューについてはUnity 5.1以降だとVR previewが実装されるようです。
現状では拙作の OculusRiftDK2ExtendPreviewなどを併用することで、再生ボタンでDK2の見え方確認が出来ます。

neon-izm/OculusRiftDK2ExtendPreview · GitHub

f:id:izm_11:20150502231340j:plain

ビルドスクリプトの追加

/Assets/Resources以下と、/Assets/StreamingAssets以下のファイルは、Android向けに書き出すときに、基本的に全て転送されます。今回の様に大量の動画ファイルを含むプロジェクトでは、転送時間が最悪になります。
よって、こんな感じのPostProcessBuild.csをAssets/Editor以下に置きます。

using UnityEngine;
using System.Collections;
using UnityEditor;
using UnityEditor.Callbacks;


public class PostProcessBuild : MonoBehaviour {

    [PostProcessScene]
    public static void OnPostprocessScene()
    {
        if (EditorApplication.isPlayingOrWillChangePlaymode)
            return;
        
        // Move assets from Resources
        UnityEngine.Debug.Log(AssetDatabase.MoveAsset("Assets/Resources/TmpMovie", "Assets/TmpMovie"));
        AssetDatabase.Refresh();
    }

    [PostProcessBuildAttribute(1)]
    public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) {
        UnityEngine.Debug.Log(AssetDatabase.MoveAsset("Assets/TmpMovie","Assets/Resources/TmpMovie" ));
        AssetDatabase.Refresh();
    }
}
  • シーンビルド開始時に、theoraファイルが置いてあるフォルダを、別フォルダに移動する
  • ビルド中は/Assets/Resources 以下のサイズが少ないので速くビルドが完了する
  • ビルド後に、元の位置にファイルを戻す

という処理をしています。

ワークフロー改善の結果

Unityエディタ上で音やエフェクトの処理を確認した後に、Android向けに実機ビルドをする、と言う普通のゲームでは当たり前の手順が確立出来ました。
もし今回の様なコンテンツを、こういう工夫無しで作ろうと思うと結構大変だと思うので、同じようなコンテンツを作成したい方は、これらの点に留意しておくと快適だと思います。

最後に

僕がお手伝いしているチームGATE-Dは、現在OculusMobileVR Jamに参加しています。

vrjam.challengepost.com

また、MoguraVRさんに、コンテスト参加チーム紹介ページの一番上で、取り上げて頂きました。
ありがとうございます!

www.moguravr.com

5/11にコンテンツ提出締切と言うことで、チームは若干炎上していますが、鋭意頑張っております。

是非公開されたら、体験して頂けたら嬉しいです!以上宣伝でした。

Unity5PersonalでのOculusRift DK2環境構築

概要

Unity5から新たに加わったライセンス体系である、Unity5Personalライセンスは、従来のUnity4Pro相当の機能を無料で使うことが出来ます。

その為OculusRift DK2を用いたVRコンテンツも従来よりお手軽に作れるようになりました。

しかし現時点のOculusRift用SDK(以下OVRSDKと書きます)最新版であるOVRSDK0.4.4(Unity Integration)はUnity4.xとUnity5beta向けに開発されていた物で、Unity5正式版で使う時にライブラリのコードを修正する必要があります。

参考リンク:

qiita.com

このエントリでは、こういった修正をしなくても快適に動く環境を作成する手順を説明します。

環境

  • Windows8.1
  • Unity5.0.0f4 personal
  • OVRSDK0.4.4 + OvrMobileSDK0.4.3
  • OculusRuntime0.4.4

手順

  1. OculusRuntime0.4.4をインストール

  2. 通常通りUnityを起動してImportPackage→CustumPackage→OVRSDK0.4.4UnityIntegrationをインポート

  3. OvrmobileSDK0.4.3 Oculus Rift PC SDK, Samsung Gear VR Mobile SDK, Docs, Integrations | Oculus Developer Center をダウンロードして解凍→ovr_mobile_SDK0.4.3->VrUnity->UnityIntegrationのUnityIntegration.unityPackageを追加でインポート

以上です。

ProjectViewのAssets→OVR→Prefabsの中のプレハブが f:id:izm_11:20150316184333j:plain

上記画像のように、TrackingSpaceが追加されていれば、うまく上書き出来ています。

この後、LeftEyeAnchorとRightEyeAnchorのClearFlagsがSolidColorになってしまっているので、いつも通りのskyboxに変更しておきましょう

Unity5でOVRSDK0.4.4を使う場合の問題点

  1. ライブラリコードの修正が必要

  2. Monoscopic rendering(両目に同じ絵を映す)やPosition Trackingの有効無効を切り替えられない

  3. 十分なスペックのPCでもjadder(首を左右に振った時に絵がブレる)が発生する場合がある

と言う感じなので、現時点での最適なUnity5+OculusRift DK2向けの開発環境としては、このmobileSDKを併用するべきだと考えます。

テストバイナリ配布

一応Unity5でMonoscopic renderingやPosition Trackingの有効無効を確認できるバイナリを置いておきます。見え方の違いを確認したい時に使えるかもしれません。

https://copy.com/b242vKNyvIctRSXW

個人的にはMonoscopicでもPosition Trackingを有効にしていると、意外と立体に見える感じがして、楽しいです。

その他雑談

MonoscopicRenderingの良さ

Monoscopic renderingは両目に同じ絵を映すので、原理的に描画負荷を下げられます。なので例えば実写パノラマ動画を再生するようなコンテンツでは、これを使うとパフォーマンスが稼げて良いかもしれません。

また、低年齢(13歳以下)の人だと立体視の感覚が未発達なので、健康への影響を考えてOculusVR社は低年齢での使用を推奨していませんが、Monoscopic renderingであれば、そういった問題に対して別の結果が現れるかもしれません。興味深いです。

そして0.4.4以前では、Unity上でチェックボックスは有っても中身が実装されていなかったので、ようやく使えるようになって嬉しいです。

今回のネタ元

このOvrMobileSDK0.4.3を使うと良い、と言うアイディアは野生の男さん

野生の男 (@yasei_no_otoko) | Twitter

に教えてもらいました。感謝です。

Unity4.6ProでもOvrMobileSDK0.4.3を使ってPC向けビルド

@kaorun55さんが試してくださいました。

Unity4Proライセンスだけあれば、AndroidProライセンスは不要で使えます。 MonoscopicRenderingが必要であったり、最新の方が安心と言う方は検討ください。

余談

エントリ名はUnity5でもOculusしたい!と中二病でも恋がしたい!のパロディをしたかったのですが、ロゴを作っている最中に、これはもしやサムいのではないかと気付き、取り止めました。それにしてもモリサマーは可愛い…

PyCharmを使ってRaspberry Pi2上で快適リモートGPIOプログラミング

概要

せっかくRaspberry pi2も出て、モノノインターネットだとかフィジカルコンピューティングだとかユビキタス(これは死語?)も流行っているので、GPIO経由でセンサやサーボを使うプログラムを書きたいな、と思いました。
その際にPythonを使い、開発環境としてJetBrains社のPython IDEであるPyCharmを使って、普段使っているPCからリモート開発環境を作ってみました。
CUIモードのRaspberry pi2上で素のviで書くのもカッコイイとは思うのですが、入力補完等が親切な方が個人的には嬉しいです。
このエントリはその備忘録です。

多少覚えることはありますが、初心者がいきなりPythonをRaspberry pi上で書き始める、と言うのであればPyCharmは親切な環境であると思います。
他にもCPUが非力なLinuxが載る組み込み系ボード(BBB,Odroid)でも、同様に使えてIDEの恩恵を受けられるので、リモートは便利です!

続きを読む

OVRSDK0.4.4+Unityでのジャダーを防ぐビルド設定調査結果

概要

OculusRift DK2+UnityでOVRSDK0.4.4を使う時に、ビルド及び実行条件次第でジャダー(首を振った時に絵がガクガクする、凄く酔います)が起きる事がknown issueとなっています。

https://forums.oculus.com/viewtopic.php?f=37&t=18363

しかし、OVRSDK0.4.4+OculusRuntime0.4.4は現状では最もVRパフォーマンスが出る組み合わせでもあります(FPSが稼ぎやすい、遅延が短い)

よってこのエントリでは、VRコンテンツ製作者が上記環境で作る時に、どんなオプションでビルドすれば良いか、僕の調査結果を書きます。

先に結論

UnityEditorはDX9モードでもDX11モードでも良いので、BuildSettings→PlayerSettings→Other Settings→Use Direct3D11のチェックを必ず入れる事を推奨します。

f:id:izm_11:20150109005855p:plain

また、0.4.4環境では-force-d3dx9オプションは不要です。

検証環境

ソフトウェア

  • Unity4.5.5p5
  • Tuscany Demo
  • OVRSDK0.4.4
  • OculusRuntime 0.4.4

PC1(デスクトップ)

PC2(ラップトップ)

  • G-TUNE i420
  • Windows7pro(x64)
  • GeforceGTX860M+Intel HDGraphics4600(Optimusです)

制作環境

  • UnityDX11モード + DX11ビルド
  • UnityDX9モード + DX11ビルド
  • UnityDX9モード + DX9ビルド

検証手法

制作環境の3環境においてビルドしたexeを、PC1,PC2それぞれについて

  • -force-d3d9
  • -force-d3d11

オプションを付けて実行して「ジャダーの有無」「その他不具合」を目視確認。
また、いずれのPCでもTuscanyDemoが75FPS以上の速度で動くスペックです。

検証結果

緑のセルは問題なく動いた組み合わせです。赤いセルは問題があった組み合わせです。

f:id:izm_11:20150109010827p:plain

考察

  • DX9モードでビルドする意味は殆どない
  • 遥か昔はExtendModeだとUnityで作られたデモを遊ぶとき -force-d3dx9オプションを指定する必要があったが最新環境では不要。むしろ0.4.4環境ではジャダーを引き起こす可能性もある