Version: 5.5
ホロレンズ
VR Audio Spatializers

シングルパスステレオレンダリング

シングルパスステレオレンダリングは、PC と Playstation 4 ベースの VR アプリケーション機能です。左右の目の画像を同時に 1 つのまとまったレンダーテクスチャにレンダリングします。つまり、シーン全体が 1 回だけレンダリングされ、CPU 処理時間が大幅に短縮されます。この機能がないと、Unity は、最初は左目画像を次に右目画像をというように、シーンを 2 回レンダリングします。

下の 2 つの画像は、通常の VR レンダリングとシングルパスステレオレンダリングの違いを比較しています。

通常の VR レンダリング

左目の画像を左にレンダリング、右目の画像を右にレンダリング
左目の画像を左にレンダリング、右目の画像を右にレンダリング

シングルパスステレオ VR レンダリング

左右の目の画像を 1 つにまとめてレンダリング
左右の目の画像を 1 つにまとめてレンダリング

この機能を有効にするには PlayerSettings __ を開きます (Edit > Project Settings > Player)。PlayerSettings__ で Other Settings に移動し、Virtual Reality Supported にチェックを入れ、それからその下の Single-Pass Stereo Rendering にチェックを入れます (2017.3 の新しいバージョンでは、PlayerSettingsXR Settings に移動し、Virtual Reality Supported にチェックを入れ、その下の __Stereo Rendering Mothod __ ドロップダウンで Single Pass を選択します)。

Unity のビルトインのレンダー機能とスタンダードアセットはすべてこの機能と互換性があります。 ただし、カスタムシェーダーや Asset Store からダウンロードしたシェーダーは変更しなくてはならない場合があります (例えば、1 つにまとめたレンダーテクスチャの適切な半分にアクセスするために、スクリーンスペース座標にスケールとオフセットが必要な場合があります)。

シングルパスステレオレンダリングをサポートするシェーダーの作成と修正

UnityCG.cginc の既存のヘルパー関数はシングルパスステレオレンダリングをサポートします。

UnityCG.cginc には以下のヘルパー関数もあり、ステレオスコピックシェーダーを作成する支援をします。

プロパティー 機能
UnityStereoScreenSpaceUVAdjust(uv, sb) パラメーター:
uv - UV テクスチャ座標。標準 UV には float2。2 つの UV を 1 つにまとめたものには float4。
sb - 2D スケールと 2D バイアスを含む float4 が UV に適用されます (xy にスケール、zy にバイアス)。 
説明: sb のスケールとバイアスを uv のテクスチャ座標に適用した結果を返します。 これは、UNITY_SINGLE_PASS_STEREO が定義されている場合にのみ発生します。そうでない場合は、テクスチャ座標は変更されずに返されます。 これは、シングルパスステレオレンダリングモードの場合にのみ、目ごとのスケールとバイアスを適用するためによく使用されます。
UnityStereoTransformScreenSpaceTex(uv) パラメーター:
uv - UV テクスチャ座標。標準 UV には float2。2 つの UV を 1 つにまとめたものには float4。
説明: uv のテクスチャ座標に現在の目のスケールとバイアスを適用した結果を返します。 これは、UNITY_SINGLE_PASS_STEREO が定義されている場合にのみ発生します。そうでない場合は、テクスチャ座標は変更されずに返されます。
UnityStereoClamp(uv, sb) パラメーター:
uv - UV テクスチャ座標。標準 UV には float2。2 つの UV を 1 つにまとめたものには float4。
sb - 2D スケールと 2D バイアスを含む float4 が UV に適用されます (xy にスケール、zy にバイアス)。 
説明: sb が提供する幅とバイアスによって決定された x 値にクランプされた uv を 返します。これは、UNITY_SINGLE_PASS_STEREO が定義されている場合にのみ発生します。そうでない場合は、テクスチャ座標は変更されずに返されます。 これは、目と目の間の色の漏れを避けるために、シングルパスステレオレンダリングモードで各目のクランプ値を適用するためによく使用されます。

加えて、定数 unity_StereoEyeIndex はシェーダーからアクセス可能で、そのため、目に依存した計算が行われます。unity_StereoEyeIndex の値は、左目のレンダリングに関しては 0、右目に関しては 1 です。

この UnityCG.cginc の例は unity_StereoEyeIndex を使ってスクリーンスペース座標を変更する方法を示しています。

float2 TransformStereoScreenSpaceTex(float2 uv, float w)
{
    float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
    return uv.xy * scaleOffset.xy + scaleOffset.zw * w;
}

ほとんどの場合、シェーダーを変更する必要はありません。 ただし、シングルパスステレオレンダリングのソースとして平面視テクスチャをサンプリングする必要がある場合があります。例えば、フルスクリーンのフィルムのグレインまたはノイズ効果を作成する場合、ソース画像は 1 つのステレオスコピック画像にまとめられるのではなく、両目に同じ画像があることが必要です。 このような状況では、ComputeScreenPos() の代わりに ComputeNonStereoScreenPos() を使用して、完全なソーステクスチャから位置を計算します。

Image Effects

When using Single-Pass Stereo rendering, Image Effects require some extra attention. Each Image Effect runs once on the packed Render Texture (which contains both the left-eye and right-eye images), but all draw commands that run during the Image Effect are applied twice: once to the left-eye half of the destination Render Texture, and once to the right-eye half.

Image Effects do not automatically detect Single-Pass Stereo rendering, so you need to adjust any reads of packed Stereo Render Textures so that they only read from the correct side for the eye being rendered. There are two ways to do this depending on how your Image Effect is being rendered:

  • Graphics.Blit()

  • メッシュベースの描画

これらの方法に関しては以下を参照してください。

これらの調整を行わないと、各描画コマンドはソースのレンダーテクスチャのすべて (左目と右目の両方のビューを含む) を読み込み、画像全体を出力レンダリングテクスチャの左目と右目の両方に出力します。結果的に、誤って各目にソース画像全体が描画されます。

The reason this happens is that each Image Effect is either drawn using Graphics.Blit or by drawing a full-screen polygon with a Texture map. Both methods reference the entire output of the previous Image Effect in the chain. When they are used to refer to an area in a packed Stereo Render Texture, they reference the whole packed Render Texture instead of just the relevant half of it.

Graphics.Blit()

Image Effects rendered with Blit() do not automatically reference the correct part of packed stereo Render Textures. By default, they refer to the entire Texture. This incorrectly stretches the image effect across both eyes.

Blit() を使用したシングルパスステレオレンダリングの場合、シェーダーのテクスチャサンプラーには自動的に計算された追加の変数があり、描かれる目に応じて、1 つにまとまめられたステレオレンダーテクスチャの正しい半分を参照するために使用されます。この変数には、ターゲット座標を正しい位置に変換するためのスケール値とオフセット値が含まれています。

この変数にアクセスするには、サンプラーと同じ名前のシェーダーで half4 を宣言し、suffix _ST を追加します。このコード例は以下を参照してください。UV 座標を調整するには、 _ST 変数を scaleAndOffset に渡し、UnityStereoScreenSpaceUVAdjust(uv, scaleAndOffset) を使用します。この関数は非シングルパスステレオビルドでは何もコンパイルしません。つまり、このモードをサポートするように変更されたシェーダーは非シングルパスステレオビルドと互換性があります。

The following example code from the SepiaTone Image Effect Shader (in the Standard Assets) demonstrates adjustments made to make it compatible with with Single-Pass Stereo rendering.

Original:

uniform sampler2D _MainTex;

fixed4 frag (v2f_img i) : SV_Target

{   

    fixed4 original = tex2D(_MainTex, i.uv);
    

Single-Pass Stereo updated:

uniform sampler2D _MainTex;

half4 _MainTex_ST;

fixed4 frag (v2f_img i) : SV_Target

{   

    fixed4 original = tex2D(_MainTex, UnityStereoScreenSpaceUVAdjust(i.uv, _MainTex_ST));

メッシュベースの描画

Image Effects rendered using Meshes (for example, by drawing a quadrilateral in immediate mode using the low level graphics API) also need to adjust the UV coordinates on the target Texture based on which eye is being rendered. To adjust your coordinates in these circumstances, use UnityStereoTransformScreenSpaceTex(uv). This function adjusts correctly for packed stereo Render Textures in Single-Pass Stereo rendering mode, and automatically compiles for non-packed Render Textures if Single-Pass Stereo rendering mode is disabled. However, if you intend to use a Shader both for packed stereo Render Textures and non-packed Render Textures in the same mode, you need to have two separate Shaders.

スクリーンスペースエフェクト

Screen space effects are visual effects that are drawn over a pre-rendered image. Examples of screen space effects include screen-space ambient occlusion, depth of field, and bloom.

例えば、画面全体にイメージの描画が必要なスクリーンスペースエフェクトがある場合を想像してください (例えば、画面上に飛び散った何らかの汚れの描画など)。 この場合、汚れの描画を両目の範囲に引き伸ばして出力表示域全体にエフェクトを適用するのではなく、片方の目に 1 回ずつ、描画を 2 回適用する必要があります。 これを処理するには、1 つにまとめられたレンダーテクスチャ全体を参照するテクスチャ座標を、各目を参照する座標に変換する必要があります。

以下のコード例は、入力テクスチャ (_Detail) を出力イメージ全体に 8 x 6 回繰り返すサーフェスシェーダーを表しています。2 番目の例では、出力先の座標はシングルパスステレオモードで変換され、現在レンダリング中の目を表す出力テクスチャ部分を参照します。

__例 1:__ シングルパスステレオのサポートがない Detail テクスチャ

void surf(Input IN, inout SurfaceOutput o) {

    o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;

    float2 screenUV = IN.screenPos.xy / IN.screenPos.w;

    screenUV *= float2(8,6);

    o.Albedo *= tex2D(_Detail, screenUV).rgb * 2;

}

__例 2:__ シングルパスステレオのサポートがある Detail テクスチャ

void surf(Input IN, inout SurfaceOutput o) {

    o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;

    float2 screenUV = IN.screenPos.xy / IN.screenPos.w;

    #if UNITY_SINGLE_PASS_STEREO

    // シングルパスステレオモードが有効の場合は、

    // 現在処理中の目の正しい出力 UV を取得するように座標を変換します。

    float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];

    screenUV = (screenUV - scaleOffset.zw) / scaleOffset.xy;

    #endif

    screenUV *= float2(8,6);

    o.Albedo *= tex2D(_Detail, screenUV).rgb * 2;
}

ホロレンズ
VR Audio Spatializers