说来惭愧,最近也做了不少把built-in shader转URP/HDRP的工作...但一直在很没出息地用Shader Graph.....趁这几天闲,好好掰扯掰扯URP和HDRP的Shader区别。
本篇引擎版本为Unity 2021.3.3f1c1 Universal RP 12.1.6
从Built-In到URP
PASS可用差别
之前Built-in管线写前向渲染时,使用一个pass计算主光,再用多个其他pass叠加光照。但URP中不支持多个渲染Pass。 URP提供的几个默认Shader中包含多个Pass,但是只能有一个渲染Pass:
-
渲染Pass
"LightMode" = "UniversalForward"
输出到帧缓存,只能有一个
-
投影Pass
"LightMode" = "ShadowCaster"
-
深度Pass
"LightMode" = "DepthOnly"
- 其他Pass 专门用于烘焙的Pass,专门用于2D渲染的Pass等
通过Render Feature可以实现之前多Pass的描边等效果。
为了使URP认识并能渲染所需的pass,要记得在SubShader中加上tag:
"RenderPipeline"="UniversalPipeline"
CG to HLSL
URP和HDRP都使用了HLSL,包含Shader语言的代码块要改为:
HLSLPROGRAME
...
ENDHLSL
头文件变化
包含的头文件也需要从"UnityCG.cginc"改为
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
Lighting相关的头文件为
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
对应的一些函数名称也会有变化。
CBUFFER
为使用SRP Batcher,所有贴图外的暴露参数需要用CBUFFER_START(UnityPerMaterial)与CBUFFER_END包裹,并置于Pass之前。
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float _Color;
CBUFFER_END
Basic Shader Structure
以下是一个可以有URP编译的基础Shader:
// This shader fills the mesh shape with a color predefined in the code.
Shader "Example/URPUnlitShaderBasic"
{
// The properties block of the Unity shader. In this example this block is empty
// because the output color is predefined in the fragment shader code.
Properties
{ }
// The SubShader block containing the Shader code.
SubShader
{
// SubShader Tags define when and under which conditions a SubShader block or
// a pass is executed.
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
// The HLSL code block. Unity SRP uses the HLSL language.
HLSLPROGRAM
// This line defines the name of the vertex shader.
#pragma vertex vert
// This line defines the name of the fragment shader.
#pragma fragment frag
// The Core.hlsl file contains definitions of frequently used HLSL
// macros and functions, and also contains #include references to other
// HLSL files (for example, Common.hlsl, SpaceTransforms.hlsl, etc.).
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// The structure definition defines which variables it contains.
// This example uses the Attributes structure as an input structure in
// the vertex shader.
struct Attributes
{
// The positionOS variable contains the vertex positions in object
// space.
float4 positionOS : POSITION;
};
struct Varyings
{
// The positions in this struct must have the SV_POSITION semantic.
float4 positionHCS : SV_POSITION;
};
// The vertex shader definition with properties defined in the Varyings
// structure. The type of the vert function must match the type (struct)
// that it returns.
Varyings vert(Attributes IN)
{
// Declaring the output object (OUT) with the Varyings struct.
Varyings OUT;
// The TransformObjectToHClip function transforms vertex positions
// from object space to homogenous clip space.
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
// Returning the output.
return OUT;
}
// The fragment shader definition.
half4 frag() : SV_Target
{
// Defining the color variable and returning it.
half4 customColor = half4(0.5, 0, 0, 1);
return customColor;
}
ENDHLSL
}
}
}