URP、HDRP、ShaderGraph、サーフェスシェーダー、ビルトインシェーダーはすでにシングルパスのインスタンス化されたステレオレンダリングをサポートしています。ただし、Asset Store や他のサードパーティからのシェーダー、または独自に作成したシェーダーはアップデートしなければならない場合があります。
シェーダーでのインスタンス化されたレンダリングのサポートについては、GPU Instancing を参照してください。このセクションの情報は特にステレオレンダリングについて述べており、 一般的にインスタンス化されたレンダリングをサポートするために必要なすべての変更を含んでいないかもしれません。
UNITY_VERTEX_INPUT_INSTANCE_ID
マクロを appdata
構造体に加えます。
例
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID //挿入
};
UNITY_VERTEX_OUTPUT_STEREO
マクロを v2f
出力構造体に加えます。
例
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO //挿入
};
以下のマクロを mainvert
メソッドの先頭に以下の順番で加えます。
UNITY_SETUP_INSTANCE_ID()
UNITY_INITIALIZE_OUTPUT(v2f, o)
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()
UNITY_SETUP_INSTANCE_ID()
は、現在どちらの目を GPU がレンダリングしているかに基づいて、ビルトインシェーダー変数 unity_StereoEyeIndex
と unity_InstanceID
を正しい値に計算し、設定します。
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO
は unity_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 ウェブサイト からダウンロードできます。
シングルパスに対応させたい各ポストプロセスシェーダーに、以下の手順を実行します。
シェーダーメソッドの frag メソッドの外側に UNITY_DECLARE_SCREENSPACE_TEXTURE(tex) マクロを加えます (配置例は下の例を参照)。すると、特定のステレオレンダリング方法を使用する場合、GPU は適切なテクスチャサンプラーを使用します。例えば、マルチパスレンダリングを使用する場合、GPU は Texture2D サンプラーを使用します。シングルパスインスタンシングまたはマルチビューレンダリングの場合、テクスチャサンプラーはテクスチャ配列です。
フラグメントシェーダー frag メソッドの前に UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i)
(配置例は下の例を参照)。unity_StereoEyeIndex
ビルトインシェーダー変数を使用して、GPU がどの目にレンダリングするかを調べる場合にのみ、このマクロを追加する必要があります。これは、ポストプロセスエフェクトをテストするときに便利です。
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
}
}
}
ShaderGraph はシングルパスステレオレンダリングのサポートに必要なマクロを自動的に加えます。ShaderGraph でデバッグシェーダーを実装するには、目のインデックスに基づいて基本色を設定する Custom Function ノード を使用できます。
unity_StereoEyeIndex
シェーダー属性を使用して、レンダリングされる目のインスタンスに応じて基本色を決定します。上の例の Custom Function ノードには以下のコードが含まれています。
Out = lerp(LeftColor, RightColor, unity_StereoEyeIndex);