不同于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