URP的渲染通道RendererFeature可以很方便的实现一些渲染问题,比如渲染顺序问题,遮挡后的材质替换等等。
那么我们如何通过代码来动态添加和修改呢?
首先我们需要获取到当前的URP配置文件,在对配置文件进行添加
1.通过反射获取当前UniversalRendererData
我们通过GraphicsSettings.renderPipelineAsset或QualitySettings.renderPipeline,可以获取到Edit中Graphic或Quality中设置的URP配置。
但无法获取配置中的RendererList,
UniversalRenderPipelineAsset并没有开放此属性。
所以我们可以通过反射来获取此属性。(获取了RendererList中第一个data)
UniversalRenderPipelineAsset URPAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
UniversalRendererData URPData = (UniversalRendererData)(((ScriptableRendererData[])propertyInfo?.GetValue(URPAsset))?[0]);
2. 动态添加RendererFeature渲染
代码完成AddRendererFeature功能(运行时可用)
以在最前方渲染为例:
RenderObjects rendererFeatrue = ScriptableObject.CreateInstance<RenderObjects>();
rendererFeatrue.name = "Test";
//填写期望的layer
rendererFeatrue.settings.filterSettings.LayerMask = (1 << LayerMask.NameToLayer("yourlayer0") | 1 << LayerMask.NameToLayer("yourlayer1"));
//设置材质是否透明
rendererFeatrue.settings.filterSettings.RenderQueueType = RenderQueueType.Transparent;
rendererFeatrue.settings.overrideDepthState = true;
rendererFeatrue.settings.depthCompareFunction = CompareFunction.Disabled;
创建完成后,添加到UniversalRendererData的rendererFeatures中
URPData.rendererFeatures.Add(rendererFeatrue);
如在编辑器模式中添加,则还需要RenderObjects的本地文件id,添加到UniversalRendererData的m_RendererFeatureMap中 。 m_RendererFeatureMap使用反射获取
FieldInfo propertyInfo = _urpData.GetType().GetField("m_RendererFeatureMap", BindingFlags.Instance | BindingFlags.NonPublic);
List<long> renderFeatureMapList = (List<long>)propertyInfo?.GetValue(_urpData);
UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(rendererFeatrue, out var guid, out long localId);
renderFeatureMapList.Add(localId);
要注意,如在Editor下添加,需将动态添加的Reature写入URP配置文件中,否则,缓存丢失后,该Reature会报空错误提示。
UnityEditor.AssetDatabase.AddObjectToAsset(rendererFeatrue , URPAsset );
最后要使改动立刻生效。
URPData.SetDirty();
完整代码:
private RenderObjects rendererFeatrue;
private UniversalRendererData URPData;
private void Start()
{
AddRenderFeatrue();
}
private void OnDestroy()
{
URPData.rendererFeatures.Remove(rendererFeatrue);
}
private void AddRenderFeatrue()
{
rendererFeatrue = ScriptableObject.CreateInstance<RenderObjects>();
rendererFeatrue.name = "Test";
rendererFeatrue.settings.filterSettings.LayerMask = (1 << LayerMask.NameToLayer("yourlayer0") | 1 << LayerMask.NameToLayer("yourlayer1"));
rendererFeatrue.settings.filterSettings.RenderQueueType = RenderQueueType.Transparent;
rendererFeatrue.settings.overrideDepthState = true;
rendererFeatrue.settings.depthCompareFunction = CompareFunction.Disabled;
UniversalRenderPipelineAsset URPAsset = (UniversalRenderPipelineAsset)QualitySettings.renderPipeline;
FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
URPData = (UniversalRendererData)(((ScriptableRendererData[])propertyInfo?.GetValue(URPAsset))?[0]);
URPData.rendererFeatures.Add(rendererFeatrue);
//在编辑器模式下,需将RenderObjects的本地文件id添加到m_RendererFeatureMap中
FieldInfo propertyInfo = URPAsset.GetType().GetField("m_RendererFeatureMap", BindingFlags.Instance | BindingFlags.NonPublic);
List<long> renderFeatureMapList = (List<long>)propertyInfo?.GetValue(URPAsset);
UnityEditor.AssetDatabase.TryGetGUIDAndLocalFileIdentifier(rendererFeatrue, out var guid, out long localId);
renderFeatureMapList.Add(localId);
UnityEditor.AssetDatabase.AddObjectToAsset(rendererFeatrue , URPAsset );
URPData.SetDirty();
}
参考https://forum.unity.com/threads/how-to-access-scriptablerendererdata-from-script.1012336/