Tutti Lab

元シリコンバレー在住のおっさん技術者、モバイルVRアプリ開発に挑戦中

どこでもドア(ポータル)をUnity NativeのVRで実現してみる

f:id:tuti107:20170319212451p:plain

VRでどこでもドア体験、ぜひやってみたい!と思うのですが、関東在住ではないので、気軽に行けそうにありません。
www.doraeiga-vr.com

そこで、Oculus Rift向けに作ってみようと思ったのですが、RenderTextureをごにょごにょして・・と色々考えたものの、どうやったらよいのかわからず、ネットで検索したところ以下の記事を発見しました。ただし、Vive用のコードで、あちこちVive専用のメソッド等が使われています。そこで、これをUnityのNative VR向けに移植してみました。
qiita.com

RenderTextureの生成

上記のサイトでは

_leftEyeRenderTexture = new RenderTexture((int)SteamVR.instance.sceneWidth, (int)SteamVR.instance.sceneHeight, 24);

として、RenderTextureを作成していますが、

_leftEyeRenderTexture = new RenderTexture((int)VRSettings.eyeTextureWidth, (int)VRSettings.eyeTextureHeight, 24);

としました。

ポータル用マテリアルへRenderTextureを設定する処理

まず、左右カメラ視差をつくるためのオフセット設定は、

var v = _cameraForPortal.transform.localPosition;
_cameraForPortal.transform.localPosition = v + new Vector3(-VrEye.stereoSeparation/2f, 0f, 0f);

としました(左目の場合)。
また、

Valve.VR.HmdMatrix44_t leftMatrix = SteamVR.instance.hmd.GetProjectionMatrix(Valve.VR.EVREye.Eye_Left, VrEye.nearClipPlane, VrEye.farClipPlane, Valve.VR.EGraphicsAPIConvention.API_DirectX);
_cameraForPortal.projectionMatrix = HMDMatrix4x4ToMatrix4x4(leftMatrix);

として、プロジェクションマトリクスの設定を行っている箇所は、

_cameraForPortal.projectionMatrix = VrEye.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);

としました(左目の場合)。

ポータル用マテリアルのシェーダー処理

左右どちらのレンダリングか、により使用するテクスチャを切り替えている以下の処理

if (unity_CameraProjection[0][2] < 0)
{
    col = tex2D(_LeftEyeTexture, sUV);
}
else {
    col = tex2D(_RightEyeTexture, sUV);
}

は、

if (unity_StereoEyeIndex == 0)

としました。
その他は、上記サイトにて記載されているソース等の通りです。実行すると、以下のような感じに動きます。
f:id:tuti107:20170319212415g:plain

UnityのNativeのVR機能のみでの実装のため、Oculus Riftだけでなく、Gear VR、Google Cardboard、Daydreamでの動くと思われます。試していませんが。。