Search Unity

Question Selective Outline with Rendererer Features > Render Objects?

Discussion in 'Universal Render Pipeline' started by Deive_Ex, May 23, 2020.

  1. Deive_Ex

    Deive_Ex

    Joined:
    Dec 30, 2014
    Posts:
    26
    TLDR: Is it possible to do a "selective outline" using the "Render Objects" from the "Renderer Feature" options?

    So, I'm testing Shader Graph and trying to learn more about how the new Render Pipeline stuff works and one thing I've always liked was outlines on cartoon/anime characters, and so I've started searching how to do that on the new pipeline.

    I'm no shader expert, but I do know a little bit of shader programmin and I know how you could simply add a new pass on an existing shader that created the outline, but from everything I've seen, that's not possible anymore in the new pipeline.

    Then I found about Shader Features and, specifically, the new "Render Objects" option, and thus I was able to add a outline following the example shown here:



    And I think the fact that you can override the material of certain objects without having to edit the object or the material its using is pretty awesome!

    But then, on one game I'm working on, I'm doing a little feedback thing where the outline only appears when you place the mouse above the object, and so here's my question: Is it possible to do this same type of "selective outline" using this "Render Objects" feature?
     
  2. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    467
    Yes, that’s possible with the option provided in the video roughly at 14 minutes. You can define a layer that will be rendered with an outline. All you have to do is to change the layer of the object that is hovered and setup the render feature as shown in the video.
     
  3. Deive_Ex

    Deive_Ex

    Joined:
    Dec 30, 2014
    Posts:
    26
    Well, true, but what if I'm already using a layermask for the raycast to detect which objects should be selectable? If I change the layer of the object, my raycast won't hit it anymore?
    Or what if I want to change the color of the outline for only the object I have selected?I know that, on the built-in pipeline I could use MaterialPropertyBlocks to change some properties without having to create an entire new material for that.
     
  4. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    467
    You can handle the raycast problem by casting against multiple layers, including the "outline" layer. If you have a limited set of colors/types of outlines, you could also add multiple "render objects" features, each filtering for a different layer mask and each with a different override material.

    But your objections are perfectly valid. Working in this direction would become really clumsy and hard to extend. Concerning the general problem of outlines, I wish there was a solution provided by Unity that "just works". In the meantime, I'm creating my own solution by writing a ScriptableRenderFeature myself. Let's see if it gets to a state where I can share it :)
     
  5. Deive_Ex

    Deive_Ex

    Joined:
    Dec 30, 2014
    Posts:
    26
    I see... It does seem possible, but not very "clean"... I'm love how Unity is evolving and all, but it feels weird that a thing (the outline) that was rather simple to do before suddenly became almost impossible or very complicated...
    I did saw some stuff about Renderer Features when I was searching if it was even possible to do outlines on the new pipelines and I started looking at that a little, but it seemed like way too much work just to add a simple outline on some objects...
     
  6. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    467
    I case you’re interested, I can provide the sources for the outline system that I’m trying to implement.

    Apart from some hiccups that I’m still trying to figure out it’s also pretty straightforward.

    if you want to go the route as suggested in the video you posted, you can also adapt my code with a flip-normals-push-outwards-render-black-shader

    See this thread for more information:
    https://forum.unity.com/threads/birds-eye-clarification-of-rendering-terminology.822408/
     
  7. Deive_Ex

    Deive_Ex

    Joined:
    Dec 30, 2014
    Posts:
    26
    If you could, yes, I'm interested!
     
  8. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    467
    Here you go.

    The package doesn't contain instructions, so here they are:
    Install the package, go to your Pipeline Asset, find the Renderer Features list, click the "+". Select "Outline Feature" from the list.

    Now you can add the "Outlined" component to any GameObject
     

    Attached Files:

    BenLuker likes this.
  9. Gondophares

    Gondophares

    Joined:
    Mar 9, 2013
    Posts:
    28
    Agreed. This a long standing issue that doesn't so much have to do with URP itself as with Unity's tenacious one-layer-per-gameobject-for-all-uses system. It forces you to mix values for wholly unrelated systems (rendering, collision, raycasting, culling, post-processing and is in my opinion one of Unity's most persistently hindering architecture flaws. It's one of those relics from a much earlier version of the engine, but rather than being addressed, it somehow still manages to perpetuate itself to new features. I feel Unity could do some better internal communication about that, perhaps.

    To illustrate: URP seems to have a perfect, more featured, replacement for this already, but it was somehow forgotten about (?) during the development of the RenderObjects feature. At least Unity indicates they would like to add this soon. If I understand it correctly, that should fix your problem.
     
  10. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
  11. hkostic

    hkostic

    Joined:
    Jun 4, 2020
    Posts:
    3
    Hey all,
    URP outline Depth + normal ( layer base selection), perfect for interactions ;)
    working in VR single pass/multipass
    Get my repo : https://github.com/snakenjah/Selective-outline-URP

    I have build a repository with a good (and simple to study) outline for Universal Render Pipelines
    It's a depth + normal outline effect (edge + intern edge).
    2 Render features : The first feature "depthnormal" just generate depth and normal texture for the given Layer,
    the second "Outline" will allow you to setup and edit the outline material ( I have put a shadergraph version and a .shader too, to allow you to learn how simple it is)
    The outline effect will appear only on the "Outline" layer, and ofc, Layers are editable directly in the features (in the customforward render asset) so you can put the outline on all the layers if you want to.
    the color/alpha/thickness is editable too.

    Capture d’écran (126).png
    I have the exact same thing working in HDRP using custom pass system.
     
  12. hkostic

    hkostic

    Joined:
    Jun 4, 2020
    Posts:
    3
    Actually a good update of this could be a compare operation with the camera's depth texture, to allow you to hide the outine that is inside or behind another object, even on another layer that got no outline effect on.

    This for a unique color at the moment, for multiple (different) colors the best way should be to put some stencil information in the scene's objects shader (add stencil props into the lit shader like in Lux(lwrp)), then the depth generation pass can use (read?) stencil as a "mask" into the render buffer to filter it for every color it need, it become easy to create a buch of color into the shader :)
     
  13. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    I have just used this way with stencil, but by generating a special mask texture, using cmd.DrawMesh, following this thread:
    https://forum.unity.com/threads/app...yer-using-stencil-solved.841150/#post-5558896
    demo_0000133.jpg
    without using the stencil mask texture I kept on getting these outlines always on top.

    I have also found an interesting solution here:
    https://alexanderameye.github.io/outlineshader.html.
    - and tested it on the image below. The per object outline uses just only single depth normal feature, no stencils, and then the outline is added at the object material level. The drawback of this simple approach is that the outer edges are of half width of the inner edges.
    demo_0000134.jpg
     

    Attached Files:

  14. kovstasalex

    kovstasalex

    Joined:
    Sep 12, 2017
    Posts:
    1
    Can you share your solution ?
     
  15. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    You can find this solution in this asset: https://assetstore.unity.com/packages/vfx/shaders/crosssection-93478, but with a special support for the mesh backfaces. (The latest update contains a small error resulting in wrong outline render order in urp, currently I am going to check one more thing and reupdate it). Possibly I could also find it isolated somewhere, but it would take me some time.
     
    Last edited: Mar 12, 2021
  16. Naomi_A_Virtual

    Naomi_A_Virtual

    Joined:
    Jul 25, 2019
    Posts:
    2
    Interested to find out also! Thanks
     
  17. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Im trying to get this to work in unity 2021.3.8 URP https://github.com/snakenjah/Selective-outline-URP , it works well in 2019 but I just cant see whats change that stops it working in the 2021.3.8 URP any help or advice would be very much apprenticed, many many hours have been spent trying to figure out why most of these examples no longer work after 2019 and got now where. Thank you to every one that has provided there examples and hopefully Unity/ some one with much more experience than myself can help.

    The screen is a nice pink colour and there are errors in the outline shader.

    invalid condition expression : 25
    invalid subscript 'sh' D3D varinyings.hlsl :180
    implicit truncation of vector type outline.hsll :51

    I no nothing about shader graph and as hard as I try just cant understand shaders syntax at all so again any help would be greatly appreciated

    *I would be happy to pay for some tuition/help with this.
     
    Last edited: Aug 26, 2022
  18. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    Yo
    u can try to use my solution from this asset: https://assetstore.unity.com/packages/vfx/shaders/crosssection-93478.
    image_017_0000.png combined.png

    I also remember having some difficulties in getting this to work in 2020.x, but now it works in 2021.x as well as in 2022.x
     
  19. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Thank you for you replay, you asset look fantastic but I want a simple outline shader/effect that is as performant as is possible ( there is potentially alot of geometry to select/outline. Is this something you also have available? it needs to be able to outline selected geometry not using layers (it can use render layers and needs to be able to overlap and keep the outline) Like in the unity editor itself.

    I had a good solution but the URP broke it. There is allot of stuff out there for this but nothing that seems to be fast simple and quite work and im just not skilled enough to do something like this (things seemed to have got really complicated with the URP as well?)
     
  20. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    Basically this: https://github.com/snakenjah/Selective-outline-URP - works in similar way as outlines in my asset. The outlined objects are located on a separate layer and a separate depth-normal texture is being rendered for that layer. Then the screen-space outline shader uses this texture to render outlines.
    The object outlines within the outline layer get hidden (a closer object hides the further object), but are not hidden by objects outside the outline layer.

    The errors thrown come from the Outline shader. You can find a plenty of other outline shaders on the web with codes much simpler than this. I would replace this with one of them, making it to work on this separate depth-normal texture. The outline shader I use in my asset is much simpler.

    (In my asset I am using a simple mask texture for the front- and back-faces so the outlines are rendered on the masked areas only and the further objects are hidden by closer objects.)

    You can also use this, which is maintained to work with latest Unity version:
    https://forum.unity.com/threads/screen-space-outline-effect-for-unity-free.836908/

    Update
    Zrzut ekranu 2022-08-27 095724.png

    Works the same, but with other outline shader/material.
    I have adapted the shader from my asset, just by removing the redundant code from that.
     

    Attached Files:

    Last edited: Aug 27, 2022
    OrbitalDuck likes this.
  21. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Thankyou tomekki you explanation and your effort on getting the package working it is very helpfull, have taken your advice and purchased your fantastic asset, it is definitely something I can use in the very near future for one of my projects. I really want to learn how to do at least some of the easier type of shaders and renderpass type work. Currently asway form my work pc but will get working on this when im home. Once again thankyou for your help and talking the time to do this. It is very much appreciated and I look forward to having a go with your asset!
     
    tomekkie2 likes this.
  22. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    Thank you very much. But I did not wan to induce to buy my asset. Once I have shared the shader you will not need this asset to get your outlines to work. I hope you will have an opportunity to use it somewhere else.
    You can also try and compare this shader with the previous one in the 2019.x project.
     
  23. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Cross sections was something I had as a planed feature for a project I'm working, its an engineering type project so your asset could get used in the near future and should do the job so it no prob, and hopefully I will be able to learn some things from it to. I have the outline working ok using the renderingLayers instead of layers and confident I can change these in code for the objects.... but the outlines don't work on transparent materials. This will be because the transparent don't get drawn into the z buffer? how best to deal with this, any help would be very much apprenticed (almost there!) I tried setting Zwrite On but there was an error in the shader( really have no clue ). Once again thank you for you help.
     
    tomekkie2 likes this.
  24. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Has anybody got any example or ideas on how to do this? maybe the unity engineers know how the URP can do this? I haven't found much online and it should be possible, maybe an extra pas is required? is it a feature that needs to be built in.

    Many thanks
     
  25. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    973
    This is a matter of RenderFeature setup, specifically RenderPassEvent, RenderQueueRange, SortingCriteria and DepthNormals shader.
    You can take a look at my asset, possibly the online demos and notice that the outlines there work on both opaque and transparent materials.
    And again, you can follow the solution from my asset: Zrzut ekranu 2022-09-01 060706.png
    - and use the depth normals RenderFeature and its settings from there.
    My version of RenderFeature has shader property exposed, so you can use any chosen depth normals shader with it, the default is Unity built-in depth normals shader.
    You can make a simple URP depth normal shader by taking - for example - unlit URP shader and deleting all the passes, but leaving only the depth-normals.
     
    OrbitalDuck likes this.
  26. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Tomekki, once again thank you for you help and explanations, I really do apprentice it and am learning a bit more about render features. I exposed the shader settings so I could set the look of the outline so have made a bit of progress. Will have a look at how you handle the sorting ect to the get transparency working this setting when I get back from work and hopefully post my results.
     
    tomekkie2 likes this.
  27. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    Here is a simple outline based on https://github.com/snakenjah/Selective-outline-URP and Tomekkis outline shader and using his depth pass as a guide too make a simple one. I've added a simple script called Outline.cs that you attach to your gameObject. It uses rendering layers so wont interfere with the layering system. It works in 2021.3.8 URP

    1) Set URP-Default as you Current Render Setup
    2) Attach Outline.cs to you gameObject.
    3) Outline.Set = true to outline

    Once again the help has been very much appreciated thank you.
     

    Attached Files:

    tomekkie2 likes this.
  28. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    140

    Hi Sorry to jump in here. I see in your post you are good with understanding the render pass.

    I see you use layers in your logic

    I am trying to pixelate just one layer from the normal layers

    But only managed to do everything the camera sees.

    My I ask your help please. I you want please have a look here.

    https://forum.unity.com/threads/fil...criptable-render-pass-render-feature.1338947/

    Again Sorry for the high jacking of the thread. Have a good day
     
  29. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    I would like to be able to help but my understanding of the render feature is still only at a basic level.

    I can explain how to work with the layers though, in DepthNormalFeature.cs you will see :

    Code (CSharp):
    1.  public DepthNormalsPass(RenderQueueRange renderQueueRange, int targetId, int layerMask, Material material)
    2.         {
    3.             renderTargetId = targetId;
    4.  
    5.            [U] m_FilteringSettings = new FilteringSettings(renderQueueRange, -1, (uint)(1 << layerMask ));[/U]
    6.             depthNormalsMaterial = material;
    7.             shaderTagIds.Add(new ShaderTagId("UniversalForward"));
    8.             shaderTagIds.Add(new ShaderTagId("UniversalForwardOnly"));
    9.         }
    if you want to use the standard layer system replace

    Code (CSharp):
    1. new FilteringSettings(renderQueueRange, -1, (uint)(1 << layerMask ));
    with

    Code (CSharp):
    1. new FilteringSettings(renderQueueRange, 1 << layerMask ));
    not sure if this will help any though, and haven't tested it
     
    Dark_Seth likes this.
  30. Dark_Seth

    Dark_Seth

    Joined:
    May 28, 2014
    Posts:
    140
    Thanks any info on this is good info!!
     
  31. OrbitalDuck

    OrbitalDuck

    Joined:
    Oct 26, 2013
    Posts:
    60
    back here again with URP 14.07..... trying to upgrade the simpleoutline.unity package to the latest version of unity and having a tough time with it. I have made a start but getting null reference for the RT handles and a black screen. Any help would be very much appreciated.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. public class OutlineFeature : ScriptableRendererFeature
    5. {
    6.     OutlinePass outlinePass;
    7.     RTHandle outlineTexture;
    8.  
    9.     [SerializeField] Material outlineMaterial = null;
    10.     [SerializeField] Color EdgeColour = Color.white;
    11.  
    12.     [Range(0, 4)]
    13.     [SerializeField] float EdgeThickness = 1;
    14.     [Space]
    15.     [Range(0, 1)]
    16.     [SerializeField] float DepthSensitivity = 0;
    17.     [Range(0, 10)]
    18.     [SerializeField] float NormalsSensitivity = 0;
    19.     [Range(0, 10)]
    20.     [SerializeField] float ColorSensitivity = 0;
    21.  
    22.     public override void Create()
    23.     {
    24.         if (outlineMaterial == null) return;
    25.         outlineMaterial.SetColor("_edgeColor", EdgeColour);
    26.         outlineMaterial.SetFloat("_outlineThickness", EdgeThickness);
    27.         outlineMaterial.SetFloat("_depthSensitivity", DepthSensitivity);
    28.         outlineMaterial.SetFloat("_colorSensitivity", ColorSensitivity);
    29.         outlineMaterial.SetFloat("_normalsSensitivity", NormalsSensitivity);
    30.  
    31.         outlinePass = new OutlinePass(outlineMaterial);
    32.         outlinePass.renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
    33.         //  outlineTexture.Init("_OutlineTexture");
    34.         outlineTexture = RTHandles.Alloc("_OutlineTexture", "_OutlineTexture");
    35.     }
    36.  
    37.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    38.     {
    39.         renderer.EnqueuePass(outlinePass);
    40.     }
    41.  
    42.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    43.     {
    44.         outlinePass.Setup(renderer.cameraColorTargetHandle);
    45.     }
    46.  
    47.     class OutlinePass : ScriptableRenderPass
    48.     {
    49.  
    50.        public Material outlineMaterial = null;
    51.        RTHandle temporaryColorTexture;
    52.            
    53.        RTHandle source;
    54.        RTHandle destination;
    55.  
    56.         public OutlinePass(Material outlineMaterial)
    57.         {          
    58.             this.outlineMaterial = outlineMaterial;
    59.         }
    60.  
    61.         public void Setup(RTHandle source)
    62.         {
    63.             this.source = source;
    64.         }
    65.  
    66.         public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    67.         {
    68.             RenderTextureDescriptor desc = renderingData.cameraData.cameraTargetDescriptor;
    69.             desc.depthBufferBits = 0; // Color and depth cannot be combined in RTHandles
    70.             RenderingUtils.ReAllocateIfNeeded(ref temporaryColorTexture, desc, FilterMode.Point, TextureWrapMode.Clamp, name: "_OutlineTexture");
    71.         }
    72.  
    73.  
    74.         public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    75.         {
    76.             CommandBuffer cmd = CommandBufferPool.Get();
    77.  
    78.             RenderTextureDescriptor opaqueDescriptor = renderingData.cameraData.cameraTargetDescriptor;
    79.             opaqueDescriptor.depthBufferBits = 0;
    80.  
    81.             CoreUtils.SetRenderTarget(cmd, source, temporaryColorTexture, clearFlag, clearColor);
    82.  
    83.           //  RenderingUtils.ReAllocateIfNeeded(ref temporaryColorTexture, opaqueDescriptor, FilterMode.Point);
    84.             Blitter.BlitCameraTexture(cmd, source, temporaryColorTexture, outlineMaterial, 0);
    85.             Blitter.BlitCameraTexture(cmd, temporaryColorTexture, source);
    86.             // ...
    87.             context.ExecuteCommandBuffer(cmd);
    88.             CommandBufferPool.Release(cmd);
    89.         }
    90.  
    91.         public override void OnCameraCleanup(CommandBuffer cmd)
    92.         {
    93.             source = null;
    94.             destination = null;
    95.         }
    96.     }
     
    Nith666 likes this.