開発環境
Unity2017.3
SteamVR
HTC Viveのグリッド線とは
HTC Viveのローディング画面では、HTC Viveのデフォルトの「空間+グリッド線」が見える。
Unityのシーンの遷移時にグリッド線が見える。
しかし、ゲームによってはグリッド線は見せたくない場合がある。
例えば、「シーン1 ⇢ 黒フェードイン ⇢ 黒 ⇢ 黒フェードアウト ⇢ シーン2」のようなときにフェードインとフェードアウトの期間にグリッド線を見せたくない。
HTC Viveのグリッド線を消す
グリッド線を消す方法を2つ紹介します。
SteamVRまたはOpenVRを使用するので、まずは2つの違いから説明します。
SteamVRとOpenVRの違い
私の理解不足のところもあるため、間違い等があるかもしれません。ご容赦ください。
以下の動画の冒頭でSteamVRとOpenVRについて説明されています。
https://www.youtube.com/watch?v=4Gs5k2Fti1U
SteamVR:
・Valveが開発しているSDK
・OpenVRをラッピングしたもの
・Steamユーザーやディベロッパーがインストールしたものに使用されている名前
OpenVR:
・Valveが開発しているSDK
・VRアプリケーションを制作することができる
(例)オブジェクトのトランスフォームを変更したり、ヘッドセットにテクスチャを描画している
(例)コントローラーやヘッドセットとインタラクティブなデータのやり取りをしている
・OpenVRに対応するアプリケーションは、OpenVRに対応するすべてのデバイス上で動く
(例)ゲーム ⇢ OpenVR ⇢ ハードウェア(HTC ViveやOculusなど)を繋いでいる
1. SteamVRを使用する場合
以下の方法でグリッド線は消えます。
- SteamVR_LoadLevel.csをコンポーネントとしてゲームオブジェクトに追加します。
- ShowGrid をFalseにします。
- ローディング画面の背景色を変更しい場合は、BackgroundColorを変更してください。
Front、Back、Left、Right、Top、Bottomに画像をセットしないでください。
理由は、これらの変数はローディング画面用のSkyboxのテクスチャとして使用されるので、Skyboxにテクスチャがある場合は、ShowGridの有無に関係なく、グリッド線が強制的に表示されるためです。
2. OpenVRを使用する場合
SteamVRを使用する方法では、ローディング画面のグリッド線が消えても、地平線のように見えるグラデーションは消えません。
SteamVRのスクリプトを確認しましたが、グリッド線とグラデーションを同時に消すための処理はないようです。
なので、今回はOpenVRを直接使用して、これらを消します。
スクリプトの概要
カメラ(プレイヤー)を6枚のテクスチャで覆ってしまうことで、カメラにはテクスチャしか見えないので、結果的にグリッド線や地平線が見えなくなります。
また、RenderOverlayを呼び出すと、StopRenderingOverlayゲームの進行やローディング画面に関係なく、ヘッドセットに直接テクスチャが描画されます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
public class OverlayRenderer : MonoBehaviour
{
/// <summary>
/// オーバーレイ用のテクスチャ。
/// OpenVRがテクスチャの非圧縮にのみ対応しているので、テクスチャは非圧縮に設定する。
/// </summary>
[SerializeField]
public Texture OverlayTexture = null;
private Vector3[] _ScreenPos = {
new Vector3( 0f, 2f, 2f), // 前
new Vector3( 0f, 2f, -2f), // 後ろ
new Vector3( 2f, 2f, 0f), // 右
new Vector3(-2f, 2f, 0f), // 左
new Vector3( 0f, 2f, 0f), // 上
new Vector3( 0f, 0f, 0f), // 下
};
private Vector3[] _ScreenRot = new Vector3[] {
new Vector3( 0f, 0f, 0f), // 前
new Vector3( 0f, 180f, 0f), // 後ろ
new Vector3( 0f, 90f, 0f), // 右
new Vector3( 0f, -90f, 0f), // 左
new Vector3(-90f, 0f, 0f), // 上
new Vector3( 90f, 0f, 0f), // 下
};
/// <summary>テクスチャのオーバーレイを描画する。</summary>
public void RenderOverlay()
{
if (OverlayTexture == null)
{
return;
}
var overlay = OpenVR.Overlay;
if (overlay == null)
{
return;
}
for (int i = 0; i < 6; i++)
{
// オーバーレイを新規作成する。
var OverlayHandle = _GetOverlayHandle("Overlay_" + i.ToString(),
transform,
_ScreenPos[i],
_ScreenRot[i]);
// オーバーレイにテクスチャを貼り付ける
if (OverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
{
var texture = new Texture_t();
texture.handle = OverlayTexture.GetNativeTexturePtr();
texture.eType = SteamVR.instance.textureType;
texture.eColorSpace = EColorSpace.Auto;
overlay.SetOverlayTexture(OverlayHandle, ref texture);
}
// オーバーレイを描画する。
overlay.ShowOverlay(OverlayHandle);
}
}
/// <summary>オーバーレイの描画をやめる。</summary>
public void StopRenderingOverlay()
{
var overlay = OpenVR.Overlay;
if (overlay == null)
{
return;
}
for (int i = 0; i < 6; i++)
{
// オーバーレイを新規作成する。
var OverlayHandle = _GetOverlayHandle("Overlay_" + i.ToString(),
transform,
_ScreenPos[i],
_ScreenRot[i]);
// オーバーレイの描画をやめる
overlay.HideOverlay(OverlayHandle);
}
}
/// <summary>
/// OpenVRのオーバーレイの新規作成または作成済みの再利用を行う。
/// </summary>
/// <returns>オーバーレイを返す。</returns>
/// <param name="overlayName">オーバーレイの名前</param>
/// <param name="transform"></param>
/// <param name="widthInMeters">Width in meters.</param>
private ulong _GetOverlayHandle(string overlayName, Transform transform, Vector3 pos, Vector3 rot)
{
// オーバーレイのハンドルの初期化
ulong handle = OpenVR.k_ulOverlayHandleInvalid;
// オーバーレイを取得
var overlay = OpenVR.Overlay;
if (overlay == null)
{
return handle;
}
// オーバーレイのキーを作成
var key = SteamVR_Overlay.key + "." + overlayName;
// オーバーレイのキーの検索
// キーが見つかった場合、オーバーレイのハンドルにオーバーレイ(ID)がセットされる。
// キーが見つからなかった場合、オーバーレイのハンドルにk_ulOverlayHandleInvalidがセットされる。
var error = overlay.FindOverlay(key, ref handle);
if (error == EVROverlayError.None)
{
return handle;
}
else
{
// キーがない場合、キーを新規登録する。
// また、オーバーレイのハンドルにオーバーレイ(ID)がセットされる。
error = overlay.CreateOverlay(key, overlayName, ref handle);
}
if (error == EVROverlayError.None)
{
// 上記の処理でエラーがない場合
// オーバーレイのアルファを設定する。
overlay.SetOverlayAlpha(handle, 1.0f);
// オーバーレイの幅を設定する。
overlay.SetOverlayWidthInMeters(handle, 5f);
// D3D textures are upside-down in Unity to match OpenGL.
// テクスチャタイプがDirectXの場合、Unityでは上下反転するらしいので、正しく表示するために修正する。
if (SteamVR.instance.textureType == ETextureType.DirectX)
{
var textureBounds = new VRTextureBounds_t();
textureBounds.uMin = 0;
textureBounds.vMin = 1;
textureBounds.uMax = 1;
textureBounds.vMax = 0;
overlay.SetOverlayTextureBounds(handle, ref textureBounds);
}
// Convert from world space to tracking space using the top-most camera.
var vrcam = SteamVR_Render.Top();
if (vrcam != null && vrcam.origin != null)
{
// オーバーレイの座標と回転を設定する。
var offset = new SteamVR_Utils.RigidTransform(vrcam.origin, transform);
offset.pos.x = pos.x;
offset.pos.y = pos.y;
offset.pos.z = pos.z;
offset.rot = Quaternion.Euler(rot);
// オーバーレイの座標と回転をHMD用に変換する。
var t = offset.ToHmdMatrix34();
// オーバーレイの座標と回転を絶対値に変換する。
overlay.SetOverlayTransformAbsolute(handle, SteamVR_Render.instance.trackingSpace, ref t);
}
}
return handle;
}
}
参考サイト
SteamVRにおいて「待」を表示させずに次のシーンをロードする方法
HTC Vive の音声ミラーをスクリプト制御する
まとめ
HTC Viveのローディング画面のグリッド線を消す、または、隠すことができました!
グリッド線を隠す方法は力技なので、他の方法もあるかと思います。
また、OpenVRには他にもできることがたくさんあるので、SteamVRでできないと行き詰まったら、OpenVRを直接使用してみるのも良いでしょう。
理解が間違っているところや他の方法をご存知の場合は、コメントにて教えていただけると幸いです。