# Android 单通道立体渲染

> Explains how to use single-pass stereo rendering in your Android application.

Unity 支持 Android 设备的[单通道立体渲染](/engine/6000.0/manual/platform-specific/xr/graphics/single-pass-stereo-rendering/instancing.md)，但此设备需要支持多视图。多视图包括 [GL\_OVR\_multiview2](https://www.khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview2.txt) 和 [GL\_OVR\_multiview\_multisampled\_render\_to\_texture](https://www.khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview_multisampled_render_to_texture.txt) OpenGL ES 扩展功能。这两项扩展功能要求着色器使用包含两个切片（每只眼睛一个切片）的 2D 纹理数组。

## 着色器代码要求##shader-code-requirements

要使用自定义着色器进行单通道立体渲染，可能需要添加额外的着色器代码。自定义着色器符合以下要求时，就不需要添加额外的代码：

* 没有自定义顶点处理的表面着色器。
* 固定函数管线着色器。

**注意**：对这些着色器所作的更改与多通道立体渲染是兼容的。

### 修改着色器##modify-your-shaders

如果要使用 `unity_StereoEyeIndex` 内置着色器变量来了解 GPU 渲染到哪只眼睛，必须在现有的任何着色器阶段输出结构中声明 `UNITY_VERTEX_OUTPUT_STEREO`。例如：

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

要初始化输出数据，请在顶点着色器函数中使用 `UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()`。例如：

```
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;
}
```

要在后续阶段初始化 `unity_StereoEyeIndex`，必须在开头添加 `UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX()`。例如：

```
fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
	// sample the texture
	fixed4 col = tex2D(_MainTex, i.uv);
	// apply fog
	UNITY_APPLY_FOG(i.fogCoord, col);
	return col;
}
```

如果着色器使用的是其他着色器阶段，还应使用 `UNITY_TRANSFER_VERTEX_OUTPUT_STEREO()` 宏将眼睛索引传输到后续阶段。

**提示**：要计算对象的最终位置，最佳做法是使用 `UnityObjectToClipPos(IN.vertex)` 而不是 `mul(UNITY_MATRIX_MVP, IN.vertex)`。

## 后期处理着色器##post-processing-shaders

必须更新后期处理着色器，以处理作为纹理 2D 数组的眼睛纹理。为了有效解决这个问题，Unity 提供了 `UNITY_DECLARE_SCREENSPACE_TEXTURE()` 宏。要使纹理在多通道和单通道模式下都有效，请将每个纹理封装在此宏中。此外，对纹理进行采样时，请使用 `UNITY_SAMPLE_SCREENSPACE_TEXTURE()` 宏。

在单通模式下时，此宏要求预先调用 `UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX()`。Unity 还为深度纹理和屏幕空间阴影贴图提供了类似的宏。您可以在 `HLSLSupport.cginc` 的底部看到完整列表。
