Search Unity

Per object render queue in instanced rendering

Discussion in 'General Graphics' started by TJHeuvel-net, Mar 5, 2019.

  1. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    We're drawing all our minimap items in a single instanced drawcall. They have transparency so we cannot easily do z-testing.

    How would i go about making sure one icon is drawn before another? I really just need to be able to set a renderQueue per MaterialProperty, but there doesnt seem to be a way to do this.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    A single instanced draw call of multiple objects requires all objects to be using the same material. Instanced properties are float / int values that can be stored in an array that's passed to the material and accessed by instanced id rather than directly. Nothing else can be modified and still allow for instancing. This includes the render queue. Two objects with a different queue will not be batched as it's possible that they won't be getting rendered at the same time.

    If you're using DrawMeshInstanced to draw your items, and thus creating the array yourself, it's up to you to sort the arrays yourself in the order you want.

    If you're using in-place game objects and relying on Unity's own instanced batching and sorting, you could try using the Renderer.sortingOrder setting. This is something exposed on sprite renderers, but hidden on all others, but does in fact work on mesh and skinned mesh renderers! For sprites the sorting order is used during batching, but I do not know if it breaks instancing or not as I've always drawn objects manually in cases where I want to ensure the order.
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [ExecuteInEditMode]
    4. public class RendererSortingOrder : MonoBehaviour
    5. {
    6.     [SerializeField] int sortingOrder = 0;
    7.     private Renderer rend;
    8.  
    9.     private void Awake()
    10.     {
    11. #if UNITY_EDITOR
    12.         if (rend == null)
    13.             rend = GetComponent<Renderer>();
    14.         if (rend == null)
    15.             return;
    16. #endif
    17.         rend.sortingOrder = sortingOrder;
    18.     }
    19.  
    20. #if UNITY_EDITOR
    21.     void Update()
    22.     {
    23.         if (rend != null)
    24.             Awake();
    25.     }
    26. #endif
    27. }
    BTW, setting a render target, view & projection matrix, and then drawing meshes manually via a command buffer, instanced or otherwise, is sometimes thousands of times faster than using a second camera and relying on layers and Unity's sorting to accomplish this. For Falcon Age our minimap was taking >3 milliseconds using a second camera. After refactoring and handling drawing manually (not even using instancing!) it's down to microseconds. There's a lot of time Unity wastes to culling and "does anything in view need x feature?" tests that you can skip by doing it manually.
     
    TJHeuvel-net and teutonicus like this.
  3. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Thanks for the detailed answer! Right now we are just using objects, not drawing them by hand per se. I'll definitely check this sorting order out, and otherwise will create a command buffer for them.

    Thank you again for the great answer.
     
  4. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    It appears like the renderPriority is not used, we'll have to use some custom rendering.
     
    bgolus likes this.