Unity URP Shader Default LightMode Tag

不同于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的代码和文档之后,我大致梳理出了其中的运行原理。

image-20240618182409983

从文档中可以得知URP使用LightMode这个Tag作为依据来决定执行哪个Pass,且无LightMode的Pass会被默认标记为SRPDefaultUnlit


那么我们从代码中看下

主要涉及的文件有UniversalRenderer.cs/UniversalRendererRenderGraph.cs/DrawObjectsPass.cs


其中UniversalRenderer.cs/UniversalRendererRenderGraph.cs中管控了URP中默认的渲染逻辑

从中我们可以找到:


UniversalRenderer.cs

image-20240618183816195

image-20240618191848967

UniversalRendererRenderGraph.cs

image-20240618183906845

image-20240618192020928

对于前向渲染的不透明或透明物体,URP默认处理逻辑都是在UniversalRenderer的构造函数中新建一个DrawObjectsPass

并且在管线中的OnMainRendering函数中调用DrawObjectsPassRender函数。


DrawObjectsPass.cs

image-20240618183024583

而在DrawObjectsPass的构造函数中,我们可以看到如果没有指定,默认的ShaderTagId为:

SRPDefaultUnlit/UniversalForward/UniversalForwardOnly


于是我们可以知道在URP的默认渲染流程中,会有如下操作:

  1. 将所有无依次LightMode的Pass指定为SRPDefaultUnlit
  2. 依次分别执行LightModeSRPDefaultUnlit/UniversalForward/UniversalForwardOnly第一个Pass

我在Unity Frame Debugger中也实验印证了这一点,

所以当我们想要Multi-Pass Shader,同时又不想额外使用C#自定义渲染管线时,可以利用这一点进行Hack,从而实现最多三个Pass的Shader。

URP文档中也提到了这一点:

image-20240618191413618


URP版本16.0.5

参考文档:https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@16.0/manual/urp-shaders/urp-shaderlab-pass-tags.html