不同于Unity Built-in Render Pipeline,Unity URP中并不支持直接在ShaderLab中直接编写多Pass Shader,而是会仅执行第一个Pass;
但是当给另一个Pass加入Tags{"LightMode" = "UniversalForward"}时,则不仅会先执行第一个无LightMode Tag的Pass,其后还会执行LightMode为UniversalForward的这一个Pass。(注意:这里最多执行两个Pass,且执行顺序为第一个无LightMode Pass => 第一个UniversalForward Pass)
这是什么原因呢?看了URP的代码和文档之后,我大致梳理出了其中的运行原理。

从文档中可以得知URP使用LightMode这个Tag作为依据来决定执行哪个Pass,且无LightMode的Pass会被默认标记为SRPDefaultUnlit
那么我们从代码中看下
主要涉及的文件有UniversalRenderer.cs/UniversalRendererRenderGraph.cs/DrawObjectsPass.cs
其中UniversalRenderer.cs/UniversalRendererRenderGraph.cs中管控了URP中默认的渲染逻辑
从中我们可以找到:
UniversalRenderer.cs


UniversalRendererRenderGraph.cs


对于前向渲染的不透明或透明物体,URP默认处理逻辑都是在UniversalRenderer的构造函数中新建一个DrawObjectsPass,
并且在管线中的OnMainRendering函数中调用DrawObjectsPass的Render函数。
DrawObjectsPass.cs

而在DrawObjectsPass的构造函数中,我们可以看到如果没有指定,默认的ShaderTagId为:
SRPDefaultUnlit/UniversalForward/UniversalForwardOnly
于是我们可以知道在URP的默认渲染流程中,会有如下操作:
- 将所有无依次
LightMode的Pass指定为SRPDefaultUnlit - 依次分别执行
LightMode为SRPDefaultUnlit/UniversalForward/UniversalForwardOnly的第一个Pass
我在Unity Frame Debugger中也实验印证了这一点,
所以当我们想要Multi-Pass Shader,同时又不想额外使用C#自定义渲染管线时,可以利用这一点进行Hack,从而实现最多三个Pass的Shader。
URP文档中也提到了这一点:

URP版本16.0.5
参考文档:https://docs.unity3d.com/Packages/[email protected]/manual/urp-shaders/urp-shaderlab-pass-tags.html