版本:Unity 6 (6000.0)
语言:English
立体渲染
注视点渲染

单通道实例化渲染和自定义着色器

URP、HDRP、ShaderGraph、Surface 着色器在 GPU 上运行的程序。 更多信息
参见 术语表
和内置着色器已支持单通道立体实例化渲染。但是,来自 Asset StoreUnity 和社区成员创建的不断增长的免费和商业资产库。提供各种各样的资产,从纹理、模型和动画到完整的项目示例、教程和编辑器扩展。 更多信息
参见 术语表
、其他第三方或您自己编写的着色器可能需要更新。

有关在着色器中支持实例化渲染的更多信息,请参阅 GPU 实例化。本节中的信息专门讨论立体渲染,可能不包含支持一般实例化渲染所需的所有更改。

更新顶点输入属性结构

UNITY_VERTEX_INPUT_INSTANCE_ID 宏添加到 appdata 结构中。

示例

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

更新顶点输出属性结构

UNITY_VERTEX_OUTPUT_STEREO 宏添加到 v2f 输出结构中。

示例

struct v2f
{
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;

    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

更新主顶点着色器函数

将以下宏添加到主 vert 方法的开头(按顺序)

  1. UNITY_SETUP_INSTANCE_ID()
  2. UNITY_INITIALIZE_OUTPUT(v2f, o)
  3. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO()

UNITY_SETUP_INSTANCE_ID() 根据 GPU 当前正在渲染的哪个眼球计算并设置内置 unity_StereoEyeIndexunity_InstanceID 着色器变量为正确的值。

UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO 根据 unity_StereoEyeIndex 的值告诉 GPU 纹理数组中应渲染到哪个眼球。此宏还从 顶点着色器在渲染模型时,在 3D 模型的每个顶点上运行的程序。 更多信息
参见 术语表
传输 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); //Insert
    UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert

    o.vertex = UnityObjectToClipPos(v.vertex);

    o.uv = v.uv;

    return o;
}

后期处理着色器

如果希望您的 后期处理在图像显示在屏幕上之前应用滤镜和效果来改善产品视觉效果的过程。例如,您可以使用后期处理效果来模拟物理相机和胶片属性,例如 Bloom 和景深。 更多信息 post processing, postprocessing, postprocess
参见 术语表
着色器支持单通道立体实例化,请按照自定义着色器的步骤以及以下步骤操作。

注意:您可以从 Unity 网站 下载所有 Unity 基本着色器 脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性并以任何您喜欢的方式响应用户输入。 更多信息
参见 术语表

对于要支持单通道实例化的每个后期处理着色器,请执行以下操作

  1. 在 Shader 脚本中,在 frag 方法之外添加 UNITY_DECLARE_SCREENSPACE_TEXTURE(tex) 宏(有关放置位置,请参见下面的示例),以便在使用特定立体渲染方法时,GPU 使用相应的纹理采样器。例如,如果使用多通道渲染,则 GPU 使用纹理 2D 采样器。对于单通道实例化或多视图渲染,纹理采样器是纹理数组。

  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() 宏会检测正在使用的哪个立体 渲染路径渲染管线用于渲染图形的技术。选择不同的渲染路径会影响光照和阴影的计算方式。某些渲染路径比其他渲染路径更适合不同的平台和硬件。 更多信息
    参见 术语表
    ,然后以正确的方式自动采样纹理。有关用于深度纹理和屏幕空间阴影贴图的类似宏,请参阅 Unity 文档 HLSLSupport.cginc

示例

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
    
    // just invert the colors
    
    col = 1 - col;
    
    return col;
}

完整的示例着色器代码

下面是模板图像效果着色器的简单示例,其中应用了前面提到的所有更改以支持单通道立体实例化。添加到着色器代码中的行用以下注释标记://Insert

struct appdata
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
    
    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

//v2f output struct

struct v2f
{

    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
    
    UNITY_VERTEX_OUTPUT_STEREO //Insert
};

v2f vert (appdata v)
{
    v2f o;
    
    UNITY_SETUP_INSTANCE_ID(v); //Insert
    UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert
    
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = v.uv;
    return o;
}

UNITY_DECLARE_SCREENSPACE_TEXTURE(_MainTex); //Insert

fixed4 frag (v2f i) : SV_Target
{
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); //Insert
    
    fixed4 col = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_MainTex, i.uv); //Insert
    
    // invert the colors
    
    col = 1 - col;
    
    return col;
}

过程化几何体

如果使用 Graphics.DrawProceduralIndirect()CommandBuffer.DrawProceduralIndirect() 方法在 GPU 上绘制完全过程化的几何体,请注意,这两种方法都从计算缓冲区接收其参数。这意味着在运行时很难增加实例计数。要增加实例计数,必须手动将计算缓冲区中包含的实例计数加倍。

调试着色器

以下着色器代码将 游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等。游戏对象的功用由附加在其上的组件定义。 更多信息
参见 术语表
渲染为用户的左眼为绿色,右眼为红色。此着色器可用于调试立体渲染,因为它允许您验证所有立体图形是否正常工作且功能正确。

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 自动添加支持单通道立体渲染所需的宏。要在 ShaderGraph 中实现调试着色器,您可以使用 自定义函数节点,该节点根据眼球索引设置基础颜色。

使用 unity_StereoEyeIndex 着色器属性根据正在渲染哪个眼球实例来确定基础颜色。上面示例中的自定义函数节点包含以下代码

Out = lerp(LeftColor, RightColor, unity_StereoEyeIndex);
立体渲染
注视点渲染