Version: Unity 6.0 (6000.0)
言語 : 日本語
ステレオレンダリング
中心窩レンダリング

シングルパスインスタンスレンダリングとカスタムシェーダー

URP、HDRP、ShaderGraph、サーフェスシェーダー、およびビルトインシェーダーは、シングルパスステレオインスタンスレンダリングを、すでにサポートしています。ただし、アセットストアのシェーダー、サードパーティ製のシェーダー、または独自に作成したシェーダーの更新が必要となる場合があります。

インスタンス化されたレンダリングのシェーダーでのサポートについて、詳細は GPU インスタンシングを参照してください。このセクションの内容は、特にステレオレンダリングについて説明しており、インスタンス化されたレンダリング全般をサポートするために実施する必要のある変更を、すべてカバーしていない可能性があります。

頂点入力属性構造体の更新

UNITY_VERTEX_INPUT_INSTANCE_ID マクロを appdata 構造体に追加します。

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

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

頂点出力属性構造体の更新

UNITY_VERTEX_OUTPUT_STEREO マクロを v2f 出力構造体に追加します。

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

    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

主要頂点シェーダー機能の更新

主要な vert メソッドの先頭に、以下のマクロを順番に追加します。

  1. UNITY_SETUP_INSTANCE_ID()
  2. UNITY_INITIALIZE_OUTPUT(v2f, o)
  3. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()

UNITY_SETUP_INSTANCE_ID() はビルトインの unity_StereoEyeIndex および unity_InstanceID シェーダー変数を計算し、GPUが現在、描画している眼に基づいて正しい値に設定します。

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); //Insert
    UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert

    o.vertex = UnityObjectToClipPos(v.vertex);

    o.uv = v.uv;

    return o;
}

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

ポストプロセスシェーダーでシングルパスステレオインスタンシングをサポートする場合は、カスタムシェーダーの手順に加えて、以下の手順を行ってください。

注意: Unity の基本シェーダースクリプトは、すべて Unity のウェブサイトからダウンロードできます。

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

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

  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 のドキュメントを参照してください。

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
    
    // just invert the colors
    
    col = 1 - col;
    
    return col;
}

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

以下は、テンプレートイメージエフェクトシェーダーの簡単な例です。シングルパスステレオインスタンシングをサポートするための、前述したすべての変更が適用されています。シェーダーコードに追加された行は、コメント //Insert でマークされます。

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

//v2f output struct

struct v2f
{

    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    
    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

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

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
    
    // invert the colors
    
    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
      }
   }
}

ShaderGraph デバッグシェーダー

ShaderGraph は、シングルパスステレオレンダリングをサポートするために必要なマクロを、自動的に追加します。ShaderGraph にデバッグシェーダーを実装するには、視点インデックスに基づいて通常色を設定するカスタム関数ノードを使用します。

unity_StereoEyeIndex シェーダー属性を使用して、描画する眼インスタンスに応じて通常色を決定します。上記の例のカスタム関数ノードには、以下のコードが含まれています。

Out = lerp(LeftColor, RightColor, unity_StereoEyeIndex);
ステレオレンダリング
中心窩レンダリング