URP學習之七--RenderFeature


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。

博友們如果有意見或者建議,可以留言哦~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM