Version: 2022.1
Screen configuration
Framebuffer orientation

Single-pass stereo rendering for Android

Unity supports single-pass stereo rendering for Android devices that support multiview. Multiview consists of the GL_OVR_multiview2 and GL_OVR_multiview_multisampled_render_to_texture OpenGL ES extensions. These extensions require shaders to use a 2D texture array that consists of two slices, one slice per eye. This differs from Unity’s PC/PS4 implementation of single-pass stereo rendering which uses a double-wide 2D texture. This means that shader modifications to support single-pass stereo rendering on Android are different from other platforms.

Shader code requirements

To use single-pass stereo rendering with custom shaders, you may need to include additional shader code. You don’t need to include additional code if your custom shaders are:

  • Surface Shaders that don’t have custom vertex processing.
  • Fixed-function pipeline shaders.

Note: These shader changes are compatible with multi-pass stereo rendering.

Modify your shaders

If you want to use the unity_StereoEyeIndex built-in shader variable to know which eye the GPU is rendering to, you must declare UNITY_VERTEX_OUTPUT_STEREO in any shader stage output structs that you have. For example:

struct v2f {
    float2 uv : TEXCOOR0;
    float4 vertex : SV_POSITION;
    UNITY_VERTEX_OUTPUT_STEREO
};

To initialize the output data, use UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO() in the vertex shader function. For example:

v2f vert (appdata v)
{
    v2f o;
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    return o;
}

To initialize unity_StereoEyeIndex in subsequent stages, add UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX() at the beginning. For example:

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
    // 对纹理进行采样
    fixed4 col = tex2D(_MainTex, i.uv);
    // 应用雾
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

If your shaders use other shader stages, use the UNITY_TRANSFER_VERTEX_OUTPUT_STEREO() macro to transfer the eye index to the subsequent stages.

Tip: To calculate the final position of the object, it’s best practice to use UnityObjectToClipPos(IN.vertex) instead of mul(UNITY_MATRIX_MVP, IN.vertex).

Post-Processing Shaders

You must update post-processing shaders to deal with the eye textures being a 2D texture array. To help with this, Unity includes the UNITY_DECLARE_SCREENSPACE_TEXTURE() macro. To make textures work in both multi-pass and single-pass modes, wrap each textures in this macro. Also, when you sample the texture, use the UNITY_SAMPLE_SCREENSPACE_TEXTURE() macro.

This macro requires that you call UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX() beforehand when in single-pass mode. Unity also includes similar macros for depth textures and screen space shadow maps. You can see the full list at the bottom of HLSLSupport.cginc.

Screen configuration
Framebuffer orientation