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。
博友们如果有意见或者建议,可以留言哦~
来源:oschina
链接:https://my.oschina.net/u/4393390/blog/4318222