Search Unity

Resolved URP: No way to dynamically access/modify the RendererFeatures list at runtime?

Discussion in 'SRP Dev Blitz Day 2022 - Q&A' started by Invertex, Sep 29, 2022.

  1. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    I had been planning a feature that would have a cleaner workflow if I could instantiate it at runtime and enable/disable the feature as needed. But as far as I can tell there isn't an API for this. Accessing the
    UniversalRenderPipeline.asset.scriptableRenderer
    shows no methods for interacting with the RendererFeatures list, which appears to have its getter property protected. And no way of adding ScriptableRendererFeature instances.
     
    wwWwwwW1 likes this.
  2. Andre_Mcgrail

    Andre_Mcgrail

    Unity Technologies

    Joined:
    Dec 9, 2016
    Posts:
    244
    Hi,

    The concept of the RenderFeatures list is that it is static at build time, but that doesn't stop custom features from being enabled and disabled, for example you can add a static property to control wether the actual pass is injected/executed or not at runtime(example). This is functionality that was intended to be in the core system but has not been exposed in a nice API yet.

    But as you say, you wish to not even have the RenderFeature in the list at all, and want to add these at runtime.

    For this I would rather suggest avoiding render features and just inject the passes directly as RenderFeatures are more of a data container for pass settings and also an easy UI/code free way of injecting passes.

    To inject a pass you just need to get the UniversalAdditionalCameraData then you can call cameraData.scriptableRenderer.EnqueuePass(myCustomPass); much like you would inside a feature. This does mean you need a way of calling this at runtime, and it should ideally be only called in a BeginCameraRendering callback from the RenderPipelineManager.

    Here is an example of it being used in a script.
     
  3. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    Thanks, glad to know there are plans to expand on that functionality. It seemed odd for there to be options to activate and deactivate Features but no way of actually accessing it from code without reflection.

    This is indeed what I've been doing for now, though a bit more expanded, I ended up making a Renderer Feature that can be hooked into to then Enqueue other Passes dynamically and get callbacks when they complete. Works well enough!
     
    Andre_Mcgrail likes this.
  4. aveakrause

    aveakrause

    Joined:
    Oct 3, 2018
    Posts:
    70
    Sorry to necro an old thread.
    I'm looking to see if an API for this is being worked on, or considered? I'm having to do some pretty ugly reflection to get around the lack of one.

    Code (CSharp):
    1. public static List<ScriptableRendererFeature> GetRendererFeatures() {
    2.     var renderer = (GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset).scriptableRenderer;
    3.     return typeof(ScriptableRenderer)
    4.         .GetField("m_RendererFeatures", BindingFlags.NonPublic | BindingFlags.Instance)
    5.         .GetValue(renderer) as List<ScriptableRendererFeature>;
    6. }
    Can we at the very least get a public get property to access the field until you give us a proper API?
     
    kulesz, OskarNordlight and clabbe like this.
  5. kulesz

    kulesz

    Joined:
    Jul 1, 2012
    Posts:
    140
    +1 for the public property idea.
    Ability to write to a depth buffer is a very useful thing, shame it can be done only by reflection.