Version: 2022.1
言語: 日本語
Stereo rendering
VR フレームタイミング

Single Pass Instanced rendering and custom shaders

URPO, HDRP, and built-in shaders already support single-pass instanced rendering. However, shaders from the Asset Store, from other third parties, or those that you have written yourself might need to be updated.

以下の手順を実行する前に、カスタムシェーダーでインスタンシングを利用できるように更新してください (GPU インスタンシング を参照)。

次に、カスタムシェーダーのフラグメントシェーダー (Vertex/Hull/Domain/Geometry) より前の最後のシェーダーステージに、さらに 2 つの変更を加える必要があります。

シングルパスインスタンシングに対応させたい各カスタムシェーダに、以下の手順を実行します。

ステップ 1: appdata 構造体に UNITY_VERTEX_INPUT_INSTANCE_ID を加えます。

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;

    UNITY_VERTEX_INPUT_INSTANCE_ID //挿入
};

ステップ 2: v2f 出力構造体に UNITY_VERTEX_OUTPUT_STEREO を加えます。

struct v2f
{
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;

    UNITY_VERTEX_OUTPUT_STEREO //挿入

};

ステップ 3: Main の vert メソッドの最初に UNITY_SETUP_INSTANCE_ID() マクロを加え、その後に UNITY_INITIALIZE_OUTPUT(v2f, o)UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO() の呼び出しを加えます。

UNITY_SETUP_INSTANCE_ID() は、現在どちらの目を GPU がレンダリングしているかに基づいて、unity_StereoEyeIndexunity_InstanceID の Unity のビルトインシェーダー変数を正しい値に計算し、設定します。

UNITY_INITIALIZE_VERTEX_OUTPUT_STEREOunity_StereoEyeIndex の値に基づいてレンダリング先になるテクスチャ配列の目を GPU に伝えます。このマクロは、unity_StereoEyeIndex の値を頂点シェーダーから転送し、フラグメントシェーダーの frag メソッドで UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEXが呼び出された場合にのみ、フラグメントシェーダーでアクセスできるようにします。

UNITY_INITALIZE_OUTPUT(v2f,o) はすべての v2f 値を 0 に初期化します。

v2f vert (appdata v)
{
    v2f o;

    UNITY_SETUP_INSTANCE_ID(v); //挿入
    UNITY_INITIALIZE_OUTPUT(v2f, o); //挿入
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //挿入

    o.vertex = UnityObjectToClipPos(v.vertex);

    o.uv = v.uv;

    return o;
}

ポストプロセスシェーダー

ポストプロセスシェーダーでシングルパスインスタンシングをサポートする場合は、カスタムシェーダーの手順と以下の手順に従ってください。すべての Unity の基本的なシェーダーソースは、Unity ダウンロード アーカイブ からダウンロードできます。

シングルパスインスタンシングに対応させたい各ポストプロセスシェーダーに、以下の手順を実行します。

ステップ 1: シェーダーメソッドの frag メソッドの外側に UNITY_DECLARE_SCREENSPACE_TEXTURE(tex) マクロを加えます (配置例は下の例を参照)。 そうすると、特定のステレオレンダリング方法を使用する場合、GPU は適切なテクスチャサンプラーを使用します。例えば、マルチパスレンダリングを使用する場合、GPU は Texture2D サンプラーを使用します。シングルパスインスタンシングまたはマルチビューレンダリングの場合、テクスチャサンプラーはテクスチャ配列です。

ステップ 2: フラグメントシェーダー frag メソッドの前に UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i) を加えます (配置例は下の例を参照)。unity_StereoEyeIndex ビルトインシェーダー変数を使用して、GPU がどの目にレンダリングするかを調べる場合にのみ、このマクロを追加する必要があります。これは、ポストプロセスエフェクトをテストするときに便利です。

ステップ 3: 2D テクスチャをサンプリングするときに UNITY_SAMPLE_SCREENSPACE_TEXTURE() を使用します (配置例は下の例を参照)。スタンダードシェーダーは 2D テクスチャベースのバックバッファを使用してテクスチャをサンプリングします。シングルパスステレオインスタンシングはこのタイプのバックバッファを使用しないため、2D テクスチャのサンプリングに別の方法を指定しないと、シェーダーは正しくレンダリングしません。レンダリングの問題を防ぐために、UNITY_SAMPLE_SCREENSPACE_TEXTURE() マクロはどのステレオレンダリングパスを使用しているかを検出し、自動的に適切な方法でテクスチャをサンプリングします。 深度テクスチャとスクリーンスペースシャドウマップに使用される類似のマクロの詳細については、HLSLSupport.cginc を参照してください。

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //挿入

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //挿入
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //挿入
    
    // 色を反転させます    
    col = 1 - col;
    
    return col;
}

完全なサンプルシェーダーコード

以下はイメージエフェクトシェーダーの簡単なテンプレートの例です。前述の変更がすべて反映され、シングルパスインスタンシングに適応可能になっています。シェーダーコードで追加された部分にはコメント (//挿入) が入っています。

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    
    UNITY_VERTEX_INPUT_INSTANCE_ID //挿入
};

//v2f 出力構造体

struct v2f
{

    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    
    UNITY_VERTEX_OUTPUT_STEREO //挿入
};

v2f vert (appdata v)
{
    v2f o;
    
    UNITY_SETUP_INSTANCE_ID(v); //挿入
    UNITY_INITIALIZE_OUTPUT(v2f, o); //挿入
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //挿入
    
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = v.uv;
    return o;
}

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //挿入

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //挿入
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //挿入
    
    // 色を反転させます    
    col = 1 - col;
    
    return col;
}

プロシージャルジオメトリ

Graphics.DrawProceduralIndirect() および CommandBuffer.DrawProceduralIndirect() メソッドを使用して GPU に完全にプロシージャルなジオメトリを描画する場合、両方のメソッドが コンピュートバッファから引数を受け取ることに注意してください。つまり、ランタイムにインスタンス数を増やすことは難かしいということです。インスタンス数を増やすには、コンピュートバッファに含まれるインスタンス数を手動で 2 倍にする必要があります。

シェーダーのデバッグ

次のシェーダーコードは、ゲームオブジェクトをユーザーの左目用に緑色に、右目用に赤色にレンダリングします。このシェーダーは、すべてのステレオグラフィックスが機能し、正しく機能していることを確認できるため、ステレオレンダリングのデバッグに便利です。

Shader "XR/StereoEyeIndexColor"
{
   Properties
   {
       _LeftEyeColor("Left Eye Color", COLOR) = (0,1,0,1)
       _RightEyeColor("Right Eye Color", COLOR) = (1,0,0,1)
   }

   SubShader
   {
      Tags { "RenderType" = "Opaque" }

      Pass
      {
         CGPROGRAM

         #pragma vertex vert
         #pragma fragment frag

         float4 _LeftEyeColor;
         float4 _RightEyeColor;

         #include "UnityCG.cginc"

         struct appdata
         {
            float4 vertex : POSITION;

            UNITY_VERTEX_INPUT_INSTANCE_ID
         };

         struct v2f
         {
            float4 vertex : SV_POSITION;

            UNITY_VERTEX_INPUT_INSTANCE_ID 
            UNITY_VERTEX_OUTPUT_STEREO
         };

         v2f vert (appdata v)
         {
            v2f o;

            UNITY_SETUP_INSTANCE_ID(v);
            UNITY_INITIALIZE_OUTPUT(v2f, o);
            UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

            o.vertex = UnityObjectToClipPos(v.vertex);

            return o;
         }

         fixed4 frag (v2f i) : SV_Target
         {
            UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

            return lerp(_LeftEyeColor, _RightEyeColor, unity_StereoEyeIndex);
         }
         ENDCG
      }
   }
}
Stereo rendering
VR フレームタイミング
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961