Unity的URP给了我们扩展渲染Pass的接口--RenderFeature,我们之前在讲URP-ForwardRenderer的时候提到过RenderFeature,这个东西是可以用来扩展Pass的。RenderFeature是依附于ForwardRenderer的,如下图所示:
现在我们会看到RendererFeatures的列表是空的,我们来添加一个,点击加号,我们会发现只有一个RenderObjects可以选择,我们可以先用这个RenderObjects的RenderFeature来熟悉一下一个Feature是怎么执行的。添加后点击添加的条目,会有以下参数:
我们首先看这个Feature怎么用:创建一个Unlit材质,将Pass的Name修改为"TestPass",然后将ShaderPasses中的PassName设置为“TestPass“,如下图:
这样,我们就能正确的通过其他Pass来渲染这个物体了,这个Pass通过我们自己在Shader中的自定义可以实现各种效果,比如我们实现一个多Pass描边,继续刚才我们的例子,因为我们将原来的PassName改为了Feature的PassName(”TestPass“),所以URP就不会调用UniversalForwardPass了。如果我们把UniversalForwardPass加回来,同时有UniversalForwardPass和TestPass两个Pass,就等于这个物体会在两个Pass中被渲染,即我们以前内置管线的多Pass渲染,通过这种方式我们就可以在URP中制作很多功能了。比如举个栗子,多Pass描边效果:
一个PASS的RenderMode为UniversalForward,另一个为TestPass,第一个Pass为了方便演示,直接Unlit,第二个Pass描边,于是有了这个效果。除了这个,这个RenderObjects的Feature还能实现很多效果,具体就由小伙伴们发挥自己的想象力啦!我们现在借助RenderObjects了解了如何使用一个Feature,那么现在我们看看这个Feature是怎么写的。因为一个Feature不能满足我们全部的需求,所以我们要学会扩展自己的Feature。
找到RenderObjects代码,如下:
[MovedFrom("UnityEngine.Experimental.Rendering.LWRP")]public class RenderObjects : ScriptableRendererFeature
我们可以看到所有的Feature都要继承ScriptableRendererFeature类。再往下我们可以看到里面定义了几个类:
[System.Serializable] public class RenderObjectsSettings { public string passTag = "RenderObjectsFeature"; public RenderPassEvent Event = RenderPassEvent.AfterRenderingOpaques; public FilterSettings filterSettings = new FilterSettings(); public Material overrideMaterial = null; public int overrideMaterialPassIndex = 0; public bool overrideDepthState = false; public CompareFunction depthCompareFunction = CompareFunction.LessEqual; public bool enableWrite = true; public StencilStateData stencilSettings = new StencilStateData(); public CustomCameraSettings cameraSettings = new CustomCameraSettings(); } [System.Serializable] public class FilterSettings { // TODO: expose opaque, transparent, all ranges as drop down public RenderQueueType RenderQueueType; public LayerMask LayerMask; public string[] PassNames; public FilterSettings() { RenderQueueType = RenderQueueType.Opaque; LayerMask = 0; } } [System.Serializable] public class CustomCameraSettings { public bool overrideCamera = false; public bool restoreCamera = true; public Vector4 offset; public float cameraFieldOfView = 60.0f; }
这些结构就是我们看到的Renderer中Feature的参数界面,也就是说Feature的参数都是在这里定义的。然后需要实现基类的两个方法:
public override void Create() { FilterSettings filter = settings.filterSettings; renderObjectsPass = new RenderObjectsPass(settings.passTag, settings.Event, filter.PassNames, filter.RenderQueueType, filter.LayerMask, settings.cameraSettings); renderObjectsPass.overrideMaterial = settings.overrideMaterial; renderObjectsPass.overrideMaterialPassIndex = settings.overrideMaterialPassIndex; if (settings.overrideDepthState) renderObjectsPass.SetDetphState(settings.enableWrite, settings.depthCompareFunction); if (settings.stencilSettings.overrideStencilState) renderObjectsPass.SetStencilState(settings.stencilSettings.stencilReference, settings.stencilSettings.stencilCompareFunction, settings.stencilSettings.passOperation, settings.stencilSettings.failOperation, settings.stencilSettings.zFailOperation); } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { renderer.EnqueuePass(renderObjectsPass); }
通过代码我们可以看到这个Feature其实就是又执行了一遍RenderObjectsPass,只不过执行时机可以自己定义。我们需要找到这两个方法在哪里调用,才能知道整个流程。
for (int i = 0; i < rendererFeatures.Count; ++i) rendererFeatures[i].AddRenderPasses(this, ref renderingData);
AddRenderPass在ForwardRenderer的SetUp方法里面执行,如上代码。
public ScriptableRenderer(ScriptableRendererData data) { foreach (var feature in data.rendererFeatures) { if (feature == null) continue; feature.Create(); m_RendererFeatures.Add(feature); } Clear(); }
Create方法在ScriptableRenderer的构造函数中,如上代码。
这样,我们就可以总结出如何做自己的RenderFeature:
1.创建自己的Feature类
2.找到Feature类要执行的Pass和时机
3.如果Feature需要自定义Pass需要自己扩展URP的Pass。
扩展Feature三步走,当然,还有Feature编辑器界面,这个忽略(啊哈哈哈哈),这节主要学习了如何创建自己的Feature,具体在应用中小伙伴们要根据时机需求看是否需要扩展Feature和Pass。
博友们如果有意见或者建议,可以留言哦~