Search Unity

ScriptableRenderPass: How To Get Current Scene Objects?

Discussion in 'Universal Render Pipeline' started by BirdiePeep, Feb 9, 2020.

  1. BirdiePeep

    BirdiePeep

    Joined:
    May 12, 2015
    Posts:
    10
    As the title suggests, inside of a ScriptableRenderPass:Execute() I'm trying to find the GameObjects in the scene which I'm currently rending.

    This seems like a simple question, however the "scene" in which we are rending depending, are we in a prefab, the main scene, the tilemap palette, etc... I've found a custom ScirptableRenderPass is called in many different situations.

    The RenderingData provides a camera object being used to render. I can ask for it's parent or scene property, however I'm finding this isn't always valid. While a prefab is open the scene is valid, however when in the editor the scene and parent property are null.

    If anyone knows a method I would appreciate knowing. If the information does not exist I'd like to request that something is added to expose this information.
     
    Last edited: Feb 9, 2020
  2. BirdiePeep

    BirdiePeep

    Joined:
    May 12, 2015
    Posts:
    10
    Looking into some of the rendering unity does, there doesn't appear to be a correct way to get this data. Here is a hack that appears to work for now, it would be nice if it was clear exactly what scene was being rendered.

    Code (CSharp):
    1. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    2. {
    3.     var scene = renderingData.cameraData.camera.scene;
    4.     if (!scene.IsValid())
    5.         scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
    6. }
     
  3. phil_lira

    phil_lira

    Unity Technologies

    Joined:
    Dec 17, 2014
    Posts:
    584
    You can get a handle to all visible objects by getting them from culling results. RenderingData.cullResults. This is an opaque handle so you don't get to see data about these objects.

    You can use this handle to render a batch of objects and apply some filtering and draw setting with ScriptableRenderContext.DrawRenderers(...)

    Here's one example script from the RenderObjects pass: https://github.com/Unity-Technologi...rsal/Runtime/Passes/RenderObjectsPass.cs#L108
     
  4. BirdiePeep

    BirdiePeep

    Joined:
    May 12, 2015
    Posts:
    10
    Yes this method exists, but only helps in the specific situation of trying to render pre-culled objects which are standard unity renderables.

    In my situation I'm using custom renderables, handling objects that might be off screen, and need to perform custom intersection tests before actually deciding to render anything.

    As an example, the Unity 2D Lighting system itself doesn't use "DrawRenderers" method for shadow casters. It instead keeps a global list in a singleton of the objects and manually loops through them for rendering since there is no other way to get them.
     
  5. phil_lira

    phil_lira

    Unity Technologies

    Joined:
    Dec 17, 2014
    Posts:
    584
    I see. Let's say we expose a way to inject render pass through scripting API. Then now you could have a MonoBehaviour in your scene that stores the list of renderers of your interest, feed in the renderers data to your render pass and inject this render pass with a callback to the pipeline.

    Would this solve your use case?
     
  6. BirdiePeep

    BirdiePeep

    Joined:
    May 12, 2015
    Posts:
    10
    If I remember correctly injecting render passes through a MonoBehaviour used to exist but then was removed at some later time. I believe it was a script placed on a camera that could do it. Now using a ScriptableRenderFeature appears to be the only method that I'm aware of.

    I see what you are trying to propose, however that makes the assumption that there is some top level script that always exists in your scene. This works for the main game, but you can't assume that in cases of editing a prefab, or other possible editor views.

    Right now the current way ScriptableRenderFeature and ScriptableRenderPass work is fine, it just that it doesn't expose everything you might care about when rendering. Just passing the actual scene we are rendering would solve my cases. The only better solution I could think of would be if a single ScriptableRenderPass was created for every scene being drawn so you could init data for each scene individually.
     
  7. Solovykh

    Solovykh

    Joined:
    Aug 28, 2017
    Posts:
    59
    Not to hijack this thread, but this would be awesome for us. I wrote a AOV system for URP which allows you to render objects on an object by object basis. In order to have that fine grain of control I basically have to turn off all other objects and then do

    Code (CSharp):
    1. camera.TryGetCullingParameters(outScriptableCullingParameters cullingParameters);
    2.          
    3. return context.Cull(ref cullingParameters);
    and then redo the shadow map with the toggled objects.

    Feels super hacky. If I could pass in a list of renderers that would be great.