Version: 6000.3
语言: 中文
立体渲染
注视点渲染

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

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

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

更新顶点输入属性结构体

添加UNITY_VERTEX_INPUT_INSTANCE_IDmacro 添加到appdata结构。

例:

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

    UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};

更新顶点输出属性结构

UNITY_VERTEX_OUTPUT_STEREOmacro 添加到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()计算并设置内置的unity_StereoEyeIndexunity_InstanceID着色器变量设置为正确的值,具体取决于 GPU 当前正在渲染的眼睛。

UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO告诉 GPU 它应该渲染到纹理数组中的哪只眼睛,基于unity_StereoEyeIndex.此宏还会传输unity_StereoEyeIndex顶点着色器 渲染模型时在 3D 模型的每个顶点上运行的程序。更多信息
请参阅术语表
因此,只有在UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX在片段着色器中调用frag方法。

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

后处理着色器

如果你想要你的后处理图像出现在屏幕上之前应用滤镜和效果来改善产品视觉效果的过程。你可以使用后期处理效果来模拟物理摄像机和胶片属性,例如泛光和景深。更多信息 后处理, 后处理, 后处理
术语表中查看
着色器要支持单通道立体实例化,请按照自定义着色器的步骤以及以下步骤作。

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

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

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

  2. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i)在片段着色器碎片方法的开头(有关放置,请参阅下面的示例)。只有在要使用unity_StereoEyeIndex内置着色器变量,以找出 GPU 渲染到哪只眼睛。这在测试后期处理效果时很有用。

  3. 使用UNITY_SAMPLE_SCREENSPACE_TEXTURE()宏(见下面的示例)。标准着色器使用基于 2D 纹理的后台缓冲区对纹理进行采样。单通道立体实例化不使用这种类型的反向缓冲区,因此,如果未为 2D 纹理采样指定不同的方法,则着色器将无法正确呈现。为了防止呈现问题,请UNITY_SAMPLE_SCREENSPACE_TEXTURE()宏检测哪个立体声渲染路径渲染管道用于渲染图形的技术。选择不同的渲染路径会影响照明和着色的计算方式。某些渲染路径比其他路径更适合不同的平台和硬件。更多信息
    请参阅术语表
    您正在使用,然后以正确的方式自动对纹理进行采样。请参阅 HLSLSupport.cginc 上的 Unity 文档,详细了解用于深度纹理和屏幕空间阴影贴图的类似宏。

例:

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中实现调试着色器,您可以使用自定义函数节点,该节点根据眼睛索引设置基础颜色。

ShaderGraph中的自定义函数节点。
ShaderGraph中的自定义函数节点。

使用unity_StereoEyeIndexShar 属性,根据要渲染的眼睛实例确定基础颜色。上例中的自定义函数节点包含以下代码:

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