Version: 6000.3
语言: 中文
使用渲染管线转换器将着色器转换为URP
更改光源淡入淡出方式以匹配内置渲染管线

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

习惯着色器GPU 上运行的程序。更多信息
请参阅术语表
为 Built-In 编写渲染管线(Render Pipeline) 获取场景内容并将其显示在屏幕上的一系列作。Unity 允许您从预构建的渲染管道中进行选择,或编写自己的渲染管道。更多信息
请参阅术语表
与通用渲染管线(URP)不兼容,并且你无法使用渲染管线转换器自动升级它们。相反,您必须重写着色器代码中不兼容的部分才能使用 URP。

您还可以在着色器图表中重新创建自定义着色器。有关更多信息,请参阅有关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 中找到 Material 属性的警告。
  • SRP Batcher 属性显示不兼容

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

  1. 改变CGPROGRAMENDCGHLSLPROGRAMENDHLSL.

  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 Pass标签

  4. struct v2fcode 块包含以下内容struct Varyingscode 块。这会将结构更改为使用 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语句下方和Varyingsstruct,定义一个名为Attributes. 这相当于内置渲染管线的appdata结构。

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

    struct Attributes
    {
        float4 positionOS   : POSITION;
        float2 uv : TEXCOORD0;
    };
    
  7. 更新v2f vert函数定义以使用新的Varyingsstruct 并获取Attributesstruct 作为输入,如下所示。

    Varyings vert(Attributes IN)
    
  8. 更新 vert 函数以输出Varyingsstruct 并使用TransformObjectToHClip函数从对象空间转换为裁剪空间。该函数还需要接受输入AttributesUV 并将其传递给输出Varyings紫外线。

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

    注意:URP 着色器使用后缀来指示空间。OS表示对象空间,以及HCS表示均匀的夹子空间。

  9. 放置一个CBUFFERCode 块,以及UnityPerMaterial参数。

    CBUFFER_START(UnityPerMaterial)
    float4 _Color;
    sampler2D _MainTex;
    CBUFFER_END
    

    注意:要使着色器与 SRP Batcher 兼容,您必须在CBUFFER代码块。即使着色器有多个通道,所有通道也必须使用相同的CBUFFER块。

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

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

这个自定义无点亮着色器现在与 SRP Batcher 兼容,可以在 URP 中使用。你可以在 Inspector 窗口中检查这一点:

  • 不再出现在另一个 cbuffer 中找到 Material 属性的警告。
  • SRP Batcher 属性显示为兼容

为着色器启用平铺和偏移

尽管着色器现在与 URP 和 SRP Batcher 兼容,但如果不进行进一步更改,你就无法使用 TilingOffset 属性。要将此功能添加到自定义无光照着色器,请使用以下步骤。

  1. 重命名属性_MainTex_BaseMap以及对此属性的任何引用。

  2. 删除[NoScaleOffset] ShaderLabUnity用于定义 Shader 对象结构的语言。更多信息
    请参阅术语表
    属性_BaseMap财产。 现在,您可以在着色器的 Inspector 窗口中看到 TilingOffset 属性。

  3. 添加[MainTexture]ShaderLab 属性添加到_BaseMap属性和[MainColor]属性添加到_Color财产。 这告诉编辑器,当你从项目的另一部分或编辑器中请求主纹理或主颜色时,要返回哪个属性。 这Properties部分现在应如下所示:

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

    TEXTURE2D(_BaseMap);
    SAMPLER(sampler_BaseMap);
    
  5. sampler2D _BaseMap变量CBUFFERblock 设置为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.uvTRANSFORM_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;
    }
    

    注意:请务必定义vert函数CBUFFER块,作为TRANSFORM_TEX宏将参数与_ST后缀。

此着色器现在具有纹理,可按颜色修改,并且完全兼容 SRP Batcher。它还完全支持 TilingOffset 属性。

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

完整的着色器代码

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
更改光源淡入淡出方式以匹配内置渲染管线