为内置渲染管线一系列操作,用于获取场景的内容并在屏幕上显示。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
}
}
}
内置渲染管线着色器有两个问题,您可以在检视器一个 Unity 窗口,显示有关当前选定的游戏对象、资源或项目设置的信息,允许您检查和编辑值。 更多信息
参见 术语表窗口中看到
以下步骤显示了如何解决这些问题并使着色器与 URP 和 SRP 批处理程序兼容。
将CGPROGRAM
和ENDCG
更改为HLSLPROGRAM
和ENDHLSL
。
更新 include 语句以引用Core.hlsl
文件。
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
注意:
Core.hlsl
包含核心 SRP 库、URP 着色器变量以及矩阵定义和转换,但不包含灯光函数或默认结构体。
将"RenderPipeline" = "UniversalPipeline"
添加到着色器标签。
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
注意:URP 不支持所有 ShaderLab 标签。有关 URP 支持哪些标签的更多信息,请参阅URP ShaderLab 通道标签。
将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;
};
在 include 语句下方和Varyings
结构体上方,使用名称Attributes
定义一个新结构体。这相当于内置渲染管线的 appdata 结构体,但使用了新的 URP 命名约定。
将下面显示的变量添加到Attributes
结构体。
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
更新v2f vert
函数定义以使用新的Varyings
结构体并以Attributes
结构体的实例作为输入,如下所示。
Varyings vert(Attributes IN)
更新 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
表示齐次裁剪空间。
将CBUFFER
代码块放在着色器使用的属性周围,以及UnityPerMaterial
参数。
CBUFFER_START(UnityPerMaterial)
float4 _Color;
sampler2D _MainTex;
CBUFFER_END
注意:要使着色器与 SRP 批处理程序兼容,必须在
CBUFFER
代码块中声明所有材质属性。即使着色器具有多个通道,所有通道也必须使用相同的CBUFFER
块。
更新frag
函数以使用Varyings
输入和类型half4
,如下所示。frag
函数现在必须使用此类型,因为 URP 着色器不支持固定类型。
half4 frag(Varyings IN) : SV_Target
{
half4 texel = tex2D(_MainTex, IN.uv);
return texel * _Color;
}
此自定义无光照着色器现在与 SRP 批处理程序兼容,并可在 URP 中使用。您可以在检视器窗口中检查这一点
尽管着色器现在与 URP 和 SRP 批处理程序兼容,但您无法在没有进一步更改的情况下使用平铺和偏移属性。要将此功能添加到自定义无光照着色器,请使用以下步骤。
将属性_MainTex
重命名为_BaseMap
以及对该属性的任何引用。这使着色器代码更接近标准 URP 着色器约定。
从_BaseMap
属性中删除[NoScaleOffset]
ShaderLabUnity 用于定义着色器对象结构的语言。 更多信息
参见 术语表属性。您现在可以在着色器的检视器窗口中看到平铺和偏移属性。
将[MainTexture]
ShaderLab 属性添加到_BaseMap
属性,并将[MainColor]
属性添加到_Color
属性。这告诉编辑器在您从项目的其他部分或在编辑器中请求主纹理或主颜色时返回哪个属性。着色器的“属性”部分现在应如下所示
Properties
{
[MainTexture] _BaseMap("Main Texture", 2D) = "white" {}
[MainColor] _Color("Color", Color) = (1,1,1,1)
}
在CBUFFER
块上方添加TEXTURE2D(_BaseMap)
和SAMPLER(sampler_BaseMap)
宏。这些宏定义纹理和采样器状态变量以供以后使用。有关采样器状态的更多信息,请参阅使用采样器状态。
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
将CBUFFER
块内的sampler2D _BaseMap
变量更改为float4 _BaseMap_ST
。此变量现在存储在检视器中设置的平铺和偏移值。
CBUFFER_START(UnityPerMaterial)
float4 _Color;
float4 _BaseMap_ST;
CBUFFER_END
更改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;
}
在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
}
}
}