【Unity URP】通过代码动态添加URP渲染通道RendererFeature

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/

猜你喜欢

转载自blog.csdn.net/boyZhenGui/article/details/125974779