夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

VRで右目の描画がおかしくなる問題の解消

本日はUnityShader枠です。

先日SteamVR用のアプリケーションを作成していると次のように描画がおかしくなる問題がありました。

f:id:Holomoto-Sumire:20220131204900p:plain

SkyBoxの描画がおかしく、スカイボックスが画像に映ると描画の画面がそのまま残ってしまう問題がありました。

〇原因

 以前も本ブログで取り上げていますが、xRデバイスでは右目、左目と2つのディスプレイを描画しています。

 この際に一部のシェーダーは両目の描画に対応しておらず、破断してしまうことがあります。

 通常のオブジェクトの場合、右目の描画が行われなくなるため片目のみの描画が行われることが多いですが、SkyBoxの場合上記画像のように描画が破断するようです。

redhologerbera.hatenablog.com

 この現象はShader側を修正することで改善します。

〇修正

この現象を修正するためにはSkyBoxに使用されているShaderを修正します。

 SkyBoxに使用されているShaderはUnity上部ワールドタブ[Window]→[Rendering]→[Lighting]から[LightingSettings]を開きます。

f:id:Holomoto-Sumire:20220131210503p:plain

[Environment]タブから確認することができます。

f:id:Holomoto-Sumire:20220131210653p:plain

マテリアルを選択してInspectorウィンドウからShaderを編集できます。

f:id:Holomoto-Sumire:20220131210808p:plain

〇Shaderの修正点

UnityではShaderは以下のような構造をしています。

Shader "Skybox/●●"
{
    Properties
    {
       ...
    }


    SubShader
    {
        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
    struct appdata
    {
     ...
    };
    

    struct v2f
    {
       ...
    };
    v2f vert(appdata v)
    {
        v2f o;
        ...
        return o;
    }
    
    half4 frag(v2f i) : COLOR
    {
        ...
    }

            ENDCG
        }
    } 
     ... 
 }

このうち修正する箇所はCGPROGRAM~ENDCG(もしくはHLSLPROGRAM~ENDHLSL)の部分です。

①appdata構造体に以下の一文を追加します。

 struct appdata
    {
     ...
     UNITY_VERTEX_INPUT_INSTANCE_ID//追加
    };

appdata構造体は3Dモデル自体の頂点や法線などの情報を格納します。一般的にappdata、appdata_tという名前が使われます。

②次にv2f構造体に以下の一文を追加します。

    struct v2f
    {
       ...
  UNITY_VERTEX_OUTPUT_STEREO//追加
    };

v2f構造体はVertex to fragmentの略でその名のように頂点シェーダーで計算したデータを格納しフラグメントシェーダーで使用するために使用します。

一般的にv2fが使用されますが、場合によってはv2g(Vertex to Geometry)などの名前が使用されることもあります。

③最後に頂点シェーダーに次の分を追加します。

    v2f vert(appdata v)
    {
        v2f o;
  UNITY_SETUP_INSTANCE_ID(v); //追加
    UNITY_INITIALIZE_OUTPUT(v2f, o); //追加
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //追加
        ...
        return o;
    }

以上で修正が完了しました。

これはシングルパスインスタンシングレンダリングといい、Steamの場合DirectX11以降で対応している手法です。(Oculus Quest、HoloLensも対応)

左右の描画のうち、共有する部分を同時に処理して処理の量を減らしパフォーマンス向上を図る技術になります。

docs.unity3d.com

この作業により描画がおかしくなる問題が解消しました。