シングルパスインスタンシング レンダリング (ステレオインスタンシングとも呼ばれます) を使用すると、GPU は各ドローコールをインスタンス化したドローコールに置き換えて、1 つのレンダリングパスを実行します。これを使用すると、2 つのドローコール間のキャッシュコヒーレンシのため、CPU 使用率を著しく低下させ、GPU 使用率もわずかに低下させることができます。これにより、アプリケーションの消費電力をはるかに削減できます。
PlayStation VR
Oculus Rift (DirectX 11)
HoloLens
Magic Leap
Multiview 拡張をサポートする Android デバイス
デスクトップの DirectX の場合は、GPU は Direct3D 11 と VPAndRTArrayIndexFromAnyShaderFeedingRasterizer
拡張をサポートする必要があります。
GL_NV_viewport_array2
GL_AMD_vertex_shader_layer
GL_ARB_shader_viewport_layer_array
この機能を有効にするには Player 設定を開きます (Edit > Project Settings > Player)。Player 設定の XR Settings に移動し、Virtual Reality Supported チェックボックスをチェックし、それから Stereo Rendering Method ドロップダウンから Single Pass Instanced (Preview) を選択します。
デフォルトの Stereo Rendering Method は Multi Pass です。この設定は高速ではありませんが、カスタムのシェーダーに適しています。カスタムシェーダーの場合は、Single Pass Instanced レンダリングに対応できるようにシェーダーの調整が必要な場合があります。
以下の手順を実行する前に、カスタムシェーダーでインスタンシングを利用できるように更新してください (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 output struct
に 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_StereoEyeIndex
と unity_InstanceID
の Unity のビルトインシェーダー変数を正しい値に計算し、設定します。
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 ダウンロード アーカイブ からダウンロードできます。
シングルパスインスタンシングに対応させたい各ポストプロセスシェーダーに、以下の手順を実行します。
ステップ 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
}
}
}
2018–09–07 限られた 編集レビュー でパブリッシュされたページ
シングルパスインスタンシングは 2017.3 2017.3 で新規追加NewIn20173
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.