Unity内置管线是无法实现控制每个层级的渲染,而URP通用渲染管线却给了我们机会,这里就介绍如何自定义渲染。
效果
本次示例场景中有一块plane和几个物体,这里将plane先渲染之后再渲染其他物体,
图中是最终结果。
从FrameDebug中看到了先渲染了Plane,这里不是通过改变单独的RendererQueue实现的,这是相当于自己实现了渲染物体。
原理详解
URP版本10.3.1,Unity2020.2.3
实现原理官方在URP代码上已经给出,在管线代码上可以找到RenderObjects.cs和DrawObjectPass.cs两个脚本,它们就是渲染不透明物体和半透明物体所使用的Pass,只要将它们拷贝出来实现自己的Feature和Pass就可以自己自定义渲染啦。
脚本解析
我将它们拷贝了一份出来并做了一些简化,同时加了一点功能:当我们自己这个Pass渲染完之后可以选择是否将当前的颜色缓冲区信息或深度信息存在一张RT上,比如上面渲染完plane马上将颜色缓冲区的信息保存到一张RT上。
自定义的代码名字对应:
RenderObjects.cs对应CustomRendererFeature.cs
DrawObjectPass.cs对应CustomRendererPass.cs
CustomRendererFeature.cs解析
面板上我将这些参数暴露出来可修改
PassEvent:什么时候插入渲染
Queue:渲染队列(Opaque、Transparent)
LayerMask:遮罩层(跟相机遮罩一样)
Color:启动拷贝颜色缓冲区内容
Depth:启动拷贝深度缓冲内容
TexFormat:存储内容的RT格式
TexName:RT名字
上述效果的配置如上图所示,这里只渲染Terrain层,并将plane的Layer设置成Terrain,如下图。
由于plane被自定义渲染了,因此在管线配置上也将这里的Terrain钩去掉,防止重复渲染。
开启了copy深度信息要把深度图打开
Create
这里做了模板缓冲相关设置,本次测试我将forwardOnlyStencilState.enabled = false设置成false关闭模板缓冲,代码还保留着是为了官方代码的完整性。之后将需要识别的ShaderTag标签打包传给Pass,这个是渲染的时候只有有这些标签的SubShader才会生效。最后将要拷贝颜色缓冲、深度信息相关配置也传到Pass上。
AddRenderPasses
日常操作,将当前的颜色缓冲RT表示传给Pass,然后将Pass加入队列
CustomRendererPass.cs解析
CustomRendererPass
构造函数,先设置Profiling上显示内容,然后设置识别标签入队列,用渲染队列类型和遮罩创建Filter,创建模板测试盒,模板测试赋值。
Init
在Feature的Create方法最后面调用,设置要拷贝颜色缓冲或深度信息的相关信息,其中开启了深度信息会启动开启深度信息的宏,因此不开不采图节省不必要操作
OnCameraSetup
在管线将相机数据设置到RenderingData以后会调用这个方法,在这里创建要存储信息的RT。
Execute
首先设置物体渲染的排序方式,之后将要是别的Shader标签,相机信息,如何排序组装成DrawingSettings,然后调用DrawRenderers渲染物体。
RenderingData.cullResults:这个在渲染之前会将相机对场景做一次剔除,这个是剔除后留下来的钥匙,剔除的信息已经存在context中,
DrawSettings:上面说了
m_FilteringSettings:上面有所解释,就是过滤。
M_RenderStateBlock:模板缓冲设置
后面就是将当前颜色缓冲区或深度信息copy一份到新创建的RT上。
FrameCleanup
在所有渲染结束后释放创建的RT,一帧渲染结束。
工程文件