Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question SRP render pass, filter by tag rather than layer mask

Discussion in 'Universal Render Pipeline' started by iv2b, Oct 14, 2020.

  1. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    Hey, i'm working on a project using URP.
    There's a Render Objects render feature included with the package, which can alter how objects are drawn, filtering them using a layer mask.
    So for example i can replace all materials of all objects in the default layer.

    Right now i'm trying to find a way to filter by tag, allowing me to apply effects to objects by changing their tag instead of putting them in a different layer temporarily and messing up with physics.

    However i'm not sure how i'd do that, especially considering a good chunk of the Render Objects script is making use of scripts i can't see the code of:

    Notice how RenderObjectsPass for example has no highlight color.

    Does anyone happen to know why and/or how i can filter by tags instead of just relying on a layer mask?

    P.s.
    I've asked the same question in scripting, i'm not sure which place would be more fitting, apologies if this is a problem.
     
  2. Tibor0991

    Tibor0991

    Joined:
    Dec 11, 2016
    Posts:
    27
    Are tags a mandatory requisite or are you open to different methods? Because you can use a SO as a subscription service and use monobehaviours as a tag system.
    Also, rather than copying the mechanism of RenderObjects, write your own custom renderer feature, this link will help you getting started: https://samdriver.xyz/articles/scriptableRender.htm

    In short, a Feature is a thingy that you add in your ForwardRenderer asset, it's literally a way of saying to the renderer "in addition to the base stuff, do this other quirky thing"; in order for a feature to work you need to enqueue at least a custom RenderPass, which is the part that actually pushes meshes into the screen.
    If you go to Create > Rendering > URP > RenderFeature the editor will generate a basic template for you.
     
  3. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    I've been using RenderObjects since it already did exactly what i need, specifically i want to draw some gameobjects with a different field of view, temporarily.

    I don't need to use tags specifically, as long as i'm not creating more and more layers it's all good.
    I fact it may even be better, if i could add a script to an object and it'll be drawn with a fov specified in the script that'd be the best possible solution (so if i want an object to be drawn with a fov of 50 i can then add a component to it and set a variable to 50).

    I'm not too sure about what you mean with "use a SO as a subscription service and use monobehaviours as a tag system", care to elaborate?

    This is what i'm working on, both animations are identical, but in the second i'm changing the arms' field of view temporarily to match the world camera (instead of the overlay camera), then doing the opposite after grabbing the item.


    That said, thank you for the link, i'll try to look into it. I'm still wrapping my head around tinkering with the rendering pipeline. :)
     
    Last edited: Oct 14, 2020
  4. Tibor0991

    Tibor0991

    Joined:
    Dec 11, 2016
    Posts:
    27
    You can use a Scriptable Object to set up a basic pub/sub pattern: say you have a Component named RenderWithFOV and a single SO named something like AlternateFOVRenderFeatureManager (ok, kinda verbose, but you get the point); each RenderWithFOV component holds a reference to this Manager object, and on its OnEnable/OnDisable messages it subscribes/unsubscribes from this Manager.
    Then, in the RenderPass you can hold another reference to the Manager and on each frame you can poll it to get the list of Renderers that must be rendered with a different FOV.

    Using a SO is just one way of doing things editor-friendly, but you can implement it however you like; about the actual way of changing the FOV I don't know the best way to do it, but if you search on the forum somebody already tried that.
     
  5. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    You lost me at "in the RenderPass you can hold another reference to the Manager and on each frame you can poll it to get the list of Renderers that must be rendered with a different FOV.".

    Let's say i have a component, it has a list of all game objects that should be rendered differently, i have a reference of this component available in the render pass script.

    How do i actually tell unity to only apply the effect to these objects? That's the part i'm not quite grasping just yet.

    Also now that i think about it... if i do not change the object's layer (ex: default) it'll be drawn twice, once by default and again but with a different fov.
    My current solution can only draw one or the other as the first layer is drawn by default, while the second is only seen by the additional pass.

    Although if i can have a different field of view for each component that'd be a big improvement as then i can handle multiple at the same time, staggered.

    Maybe there's a better approach entirely? Such as a script to put on a gameObject that takes as input a camera's transport, its fov and the target fov, then tweaks size/scale to match?
    That'd work as long as i'm not scaling colliders too...

    *edit*
    I've searched for a way to re-create the same fov effect but i haven't been able to find anything. :/
     
    Last edited: Oct 14, 2020
  6. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    Update:
    I've found the code of the RenderObjectPass here: https://github.com/Unity-Technologi...universal/Runtime/Passes/RenderObjectsPass.cs

    This means i can use its fov altering code, so no problem there.

    Now the only challenge left is somehow seeing which object/renderer i'm rendering.
    I can create a list with all gameobjects/renderers i want to affect, but at some point i'll have to do: "if the object i'm rendering is in this list, do X", which i have no clue how to do.
    I do have the list available, but i have no way of knowing what i'm rendering and if it's in the list.
     
  7. peterbay

    peterbay

    Unity Technologies

    Joined:
    Nov 2, 2017
    Posts:
    100
    laurentlavigne likes this.
  8. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    That's interesting, i could then have a list and use the rendering layer or the rendering layer as a way to apply a different value to each object.

    What is the limit on the number of rendering layer masks i can have? I see it uses a uint, but the drag down only shows 32.
    I'd only need a dozen at most, but reserving a hundred or so would be neat.
    Otherwise i can reserve a range of render queue values (ex: 2000-2050 and another 50 for transparent), then i can use that 0-50 value as index for the list (eg: if i'm rendering something with value 2004, it'll have the fov value of the 5th element in my list).

    However if i can have more than 32 rendering layers i could use something like 1000-1100 and that will never cause issues elsewhere down the line.

    *edit*
    Ah i see, each bit corresponds to a layer, so going past 32 assigns multiple layers.
    What happens if i filter using multiple rendering layers?
    Will it render if any of them match or do all have to match?

    So for example can i render all objects that are in rendering layer 1 but are not in rendering layer 2?

    *edit*
    Actually it seems the code i've found on github earlier doesn't really work...
    A ton of lines complain about variables being inaccessible due to protection level (like pretty much everything from cameraData) and it's complaining some methods do not have a return value (which i fixed by slapping void, but who knows if that's a working solution haha).
     
    Last edited: Oct 15, 2020
  9. Gondophares

    Gondophares

    Joined:
    Mar 9, 2013
    Posts:
    28
    Hey, you might be interested in this topic, which also concerns using the Rendering Layer Mask in the way you describe. In fact, I still feel Rendering Layer Mask was designed with this exact purpose in mind, but I wonder if that decision maybe didn't make its way to the developers of the Renderer Features. Unity is currently investigating adding this in future releases.
     
  10. iv2b

    iv2b

    Joined:
    Aug 2, 2018
    Posts:
    25
    That's nice, glad they're working on it!

    At the moment i could work around it by taking the RenderObjectsPass' code and making a new pass out of it, but i'm really out of luck i think.
    I can't see/edit the code from within visual studio and the code i've found on github doesn't work.
    Which is a bummer since i need both the camera and depth features it's providing, which makes it quite convenient.

    I'll try to see if i can make a feature+pass on my own, but i don't think i'll be able to especially since i can't do much if anything with the RenderingData.cameraData in the execute function.


    *edit*

    I did get it to work, somewhat, or at least the depth does.
    What i did was removing everything that was red (so for example i deleted the if statement in the image, making it always true).
    But the field of view does not change anymore haha, turns out some of the stuff i had to remove was necessary.
     
    Last edited: Oct 15, 2020