Help us understand the problem. What is going on with this article?

HTC Vive ローディング画面(グリッド線・地平線)を消す方法

More than 1 year has passed since last update.

開発環境

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を使用する場合

以下の方法でグリッド線は消えます。
1. SteamVR_LoadLevel.csをコンポーネントとしてゲームオブジェクトに追加します。
2. ShowGrid をFalseにします。
3. ローディング画面の背景色を変更しい場合は、BackgroundColorを変更してください。

Front、Back、Left、Right、Top、Bottomに画像をセットしないでください。
理由は、これらの変数はローディング画面用のSkyboxのテクスチャとして使用されるので、Skyboxにテクスチャがある場合は、ShowGridの有無に関係なく、グリッド線が強制的に表示されるためです。

2. OpenVRを使用する場合

SteamVRを使用する方法では、ローディング画面のグリッド線が消えても、地平線のように見えるグラデーションは消えません。
SteamVRのスクリプトを確認しましたが、グリッド線とグラデーションを同時に消すための処理はないようです。
なので、今回はOpenVRを直接使用して、これらを消します。

スクリプトの概要

カメラ(プレイヤー)を6枚のテクスチャで覆ってしまうことで、カメラにはテクスチャしか見えないので、結果的にグリッド線や地平線が見えなくなります。
また、RenderOverlayを呼び出すと、StopRenderingOverlayゲームの進行やローディング画面に関係なく、ヘッドセットに直接テクスチャが描画されます。

OverlayRenderer.cs
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を直接使用してみるのも良いでしょう。

理解が間違っているところや他の方法をご存知の場合は、コメントにて教えていただけると幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした