版本:Unity 6 (6000.0)
语言:English
使用渲染管线转换器将着色器转换为 URP
将内置渲染管线的质量设置转换为 URP

升级自定义着色器以实现 URP 兼容性

为内置渲染管线一系列操作,用于获取场景的内容并在屏幕上显示。Unity 允许您选择预构建的渲染管线或编写自己的渲染管线。 更多信息
参见 术语表
编写的自定义着色器在 GPU 上运行的程序。 更多信息
参见 术语表
与通用渲染管线 (URP) 不兼容,并且您无法使用渲染管线转换器自动升级它们。相反,您必须重写着色器代码中不兼容的部分以使其与 URP 兼容。

您也可以在 Shader Graph 中重新创建自定义着色器。有关更多信息,请参阅有关ShaderGraph的文档。

注意:当您升级到 URP 时,您可以识别场景中使用自定义着色器的任何材质,因为它们会变成洋红色(亮粉色)以指示错误。

本指南演示了如何通过以下部分将自定义无光照着色器从内置渲染管线升级为完全兼容 URP

内置渲染管线自定义着色器示例

以下着色器是一个简单的无光照着色器,可与内置渲染管线配合使用。本指南演示了如何将此着色器升级为与 URP 兼容。

Shader "Custom/UnlitShader"
{
    Properties
    {
        [NoScaleOffset] _MainTex("Main Texture", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f
            {
                float4 position : SV_POSITION;
                float2 uv: TEXCOORD0;
            };

            float4 _Color;
            sampler2D _MainTex;

            v2f vert(appdata_base v)
            {
                v2f o;

                o.position = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;

                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 texel = tex2D(_MainTex, i.uv);
                return texel * _Color;
            }
            ENDCG
        }
    }
}

使自定义着色器与 URP 兼容

内置渲染管线着色器有两个问题,您可以在检视器一个 Unity 窗口,显示有关当前选定的游戏对象、资源或项目设置的信息,允许您检查和编辑值。 更多信息
参见 术语表
窗口中看到

  • 警告:在另一个 cbuffer 中找到材质属性
  • SRP 批处理程序属性显示不兼容

以下步骤显示了如何解决这些问题并使着色器与 URP 和 SRP 批处理程序兼容。

  1. CGPROGRAMENDCG更改为HLSLPROGRAMENDHLSL

  2. 更新 include 语句以引用Core.hlsl文件。

    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    

    注意Core.hlsl包含核心 SRP 库、URP 着色器变量以及矩阵定义和转换,但不包含灯光函数或默认结构体。

  3. "RenderPipeline" = "UniversalPipeline"添加到着色器标签。

    Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
    

    注意:URP 不支持所有 ShaderLab 标签。有关 URP 支持哪些标签的更多信息,请参阅URP ShaderLab 通道标签

  4. struct v2f代码块替换为以下struct Varyings代码块。这将结构体更改为使用 URP 的命名约定 Varyings 而不是 v2f,并更新着色器以使用 URP 的正确变量。

    struct Varyings
    {
        // The positions in this struct must have the SV_POSITION semantic.
        float4 positionHCS  : SV_POSITION;
        float2 uv : TEXCOORD0;
    };
    
  5. 在 include 语句下方和Varyings结构体上方,使用名称Attributes定义一个新结构体。这相当于内置渲染管线的 appdata 结构体,但使用了新的 URP 命名约定。

  6. 将下面显示的变量添加到Attributes结构体。

    struct Attributes
    {
        float4 positionOS   : POSITION;
        float2 uv : TEXCOORD0;
    };
    
  7. 更新v2f vert函数定义以使用新的Varyings结构体并以Attributes结构体的实例作为输入,如下所示。

    Varyings vert(Attributes IN)
    
  8. 更新 vert 函数以输出Varyings结构体的实例,并使用TransformObjectToHClip函数从对象空间转换为裁剪空间。该函数还需要获取输入Attributes UV 并将其传递到输出Varyings UV。

    Varyings vert(Attributes IN)
    {
        Varyings OUT;
    
        OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
        OUT.uv = IN.uv;
    
        return OUT;
    }
    

    注意:URP 着色器使用后缀来指示空间。OS表示对象空间,HCS表示齐次裁剪空间。

  9. CBUFFER代码块放在着色器使用的属性周围,以及UnityPerMaterial参数。

    CBUFFER_START(UnityPerMaterial)
    float4 _Color;
    sampler2D _MainTex;
    CBUFFER_END
    

    注意:要使着色器与 SRP 批处理程序兼容,必须在CBUFFER代码块中声明所有材质属性。即使着色器具有多个通道,所有通道也必须使用相同的CBUFFER块。

  10. 更新frag函数以使用Varyings输入和类型half4,如下所示。frag函数现在必须使用此类型,因为 URP 着色器不支持固定类型。

    half4 frag(Varyings IN) : SV_Target
    {
        half4 texel = tex2D(_MainTex, IN.uv);
        return texel * _Color;
    }
    

此自定义无光照着色器现在与 SRP 批处理程序兼容,并可在 URP 中使用。您可以在检视器窗口中检查这一点

  • 警告:在另一个 cbuffer 中找到材质属性不再出现。
  • SRP 批处理程序属性显示兼容

为着色器启用平铺和偏移

尽管着色器现在与 URP 和 SRP 批处理程序兼容,但您无法在没有进一步更改的情况下使用平铺偏移属性。要将此功能添加到自定义无光照着色器,请使用以下步骤。

  1. 将属性_MainTex重命名为_BaseMap以及对该属性的任何引用。这使着色器代码更接近标准 URP 着色器约定。

  2. _BaseMap属性中删除[NoScaleOffset]ShaderLabUnity 用于定义着色器对象结构的语言。 更多信息
    参见 术语表
    属性。您现在可以在着色器的检视器窗口中看到平铺偏移属性。

  3. [MainTexture] ShaderLab 属性添加到_BaseMap属性,并将[MainColor]属性添加到_Color属性。这告诉编辑器在您从项目的其他部分或在编辑器中请求主纹理或主颜色时返回哪个属性。着色器的“属性”部分现在应如下所示

    Properties
    {
        [MainTexture] _BaseMap("Main Texture", 2D) = "white" {}
        [MainColor] _Color("Color", Color) = (1,1,1,1)
    }
    
  4. CBUFFER块上方添加TEXTURE2D(_BaseMap)SAMPLER(sampler_BaseMap)宏。这些宏定义纹理和采样器状态变量以供以后使用。有关采样器状态的更多信息,请参阅使用采样器状态

    TEXTURE2D(_BaseMap);
    SAMPLER(sampler_BaseMap);
    
  5. CBUFFER块内的sampler2D _BaseMap变量更改为float4 _BaseMap_ST。此变量现在存储在检视器中设置的平铺和偏移值。

    CBUFFER_START(UnityPerMaterial)
    float4 _Color;
    float4 _BaseMap_ST;
    CBUFFER_END
    
  6. 更改frag函数以使用宏访问纹理,而不是直接使用tex2D。为此,请将tex2D替换为SAMPLE_TEXTURE2D宏,并将sampler_BaseMap作为附加参数添加,如下所示

    half4 frag(Varyings IN) : SV_Target
    {
        half4 texel = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
        return texel * _Color;
    }
    
  7. vert函数中,更改OUT.uv以使用宏,而不是直接将纹理坐标作为IN.uv传递。为此,请将IN.uv替换为TRANSFORM_TEX(IN.uv, _BaseMap)。您的vert函数现在应如下例所示

    Varyings vert(Attributes IN)
    {
        Varyings OUT;
    
        OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
        OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);
    
        return OUT;
    }
    

    注意:必须在CBUFFER块之后定义vert函数,因为TRANSFORM_TEX宏使用带有_ST后缀的参数。

此着色器现在具有纹理(由颜色修改),并且完全与 SRP 批处理程序兼容。它还完全支持平铺偏移属性。

要查看完整着色器代码的示例,请参阅本页的完整着色器代码部分。

完整着色器代码

Shader "Custom/UnlitShader"
{
    Properties
    {
        _BaseMap("Base Map", 2D) = "white" {}
        _Color("Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            HLSLPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 positionOS   : POSITION;
                float2 uv: TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionCS  : SV_POSITION;
                float2 uv: TEXCOORD0;
            };

            TEXTURE2D(_BaseMap);
            SAMPLER(sampler_BaseMap);

            CBUFFER_START(UnityPerMaterial)
            float4 _Color;
            float4 _BaseMap_ST;
            CBUFFER_END

            Varyings vert(Attributes IN)
            {
                Varyings OUT;

                OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
                OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap);

                return OUT;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                float4 texel = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN.uv);
                return texel * _Color;
            }
            ENDHLSL
        }
    }
}
使用渲染管线转换器将着色器转换为 URP
将内置渲染管线的质量设置转换为 URP