Search Unity

How to control the shader pass order in the built-in pipeline?

Discussion in 'General Graphics' started by ViniciusGraciano, Oct 6, 2019.

  1. ViniciusGraciano

    ViniciusGraciano

    Joined:
    May 19, 2013
    Posts:
    13
    Hello!

    When using the geometry queue and multiple passes, the built-in pipeline renders all objects using pass #1, then all objects using pass #2, and so on. When using the transparent queue, it renders all passes consecutively for each object.

    To make things more clear, here is some pseudo-code (using a single shader):

    Code (CSharp):
    1. Executes frustum culling;
    2.  
    3. // Geometry queue
    4. Sort Opaque Objects Front to Back;
    5. foreach (pass in shader)
    6. {
    7.     foreach(opaque obj in frustrum)
    8.        Render opaque obj using pass
    9. }
    10.  
    11. // Transparent queue
    12. Sort Transparent Objects Back to Front;
    13. foreach(transparent obj in frustrum)
    14. {
    15.     foreach (pass in shader)
    16.        Render transparent object using pass
    17. }
    I am writing a very specific algorithm that needs the front-to-back sorting of the geometry queue, but the shader pass order of the transparent queue. That is, i need each object to be rendered in front-to-back order and to execute all passes consecutively per object.

    I cannot write a custom pipeline because this is a project that is already released and running on the built-in pipeline. Is there any way of tricking the engine to get what I need?

    Thanks!
     
  2. ViniciusGraciano

    ViniciusGraciano

    Joined:
    May 19, 2013
    Posts:
    13
    Well... I guess not.
     
  3. ZenTeapot

    ZenTeapot

    Joined:
    Oct 19, 2014
    Posts:
    65
    This is important information, but Unity does not seem to have clear documentation on this, in 2021...
     
    mabulous likes this.
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The answer is ... no, you cannot control the order.

    Unity always renders things in the order described by the OP... except when it chooses not to, which it'll do at it's own whim for opaque objects or due to bugs.

    If you need an explicit order of multiple passes, you need to use multiple materials with each using a shader with 1 pass and then make use of material queues, multiple duplicate meshes with their sortingOrder set from script, or render objects manually with command buffers.

    You can also replicate the transparency pass order of each pass for each individual object by making every object use a unique material.
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    And the sorting can be different by GPU, depending on what Unity chooses, just in case that extra undocumented pleasure accosts thee.
     
    NotaNaN and bgolus like this.
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Sorting between objects, yes. Sorting between passes should be the same, at least for the transparent queue stuff ... except for bugs.

    Opaque object sorting is disabled on TBDR mobile GPUs since they automatically do the sorting in hardware.
     
    hippocoder likes this.
  7. mabulous

    mabulous

    Joined:
    Jan 4, 2013
    Posts:
    198
    You mentioned "except for bugs" twice. Are you aware of any? I render all my objects in transparent (2500+) render queues and the order of multiple passes in a subshader does not seem to remain consistent
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yes.

    The bug is sometimes multi-pass shaders in the transparent queue render the passes out of order.
     
  9. mabulous

    mabulous

    Joined:
    Jan 4, 2013
    Posts:
    198
    Meh :/ Any fix for this other than splitting into multiple materials with different renderQueue values?
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yes! Use multiple materials and multiple renderer components and use sorting groups and the renderer.sortingOrder to manually control it!

    Yes, I know, that's even more work. But otherwise no, I don't know of any fixes or even why it happens. I just know sometimes Unity gets it so wrong it'll occasionally render the Forward Add pass before the Forward Base pass, sometimes with other objects in between. It does usually seem to be related to having point lights in the scene, but I haven't tracked it down too thoroughly.
     
  11. mabulous

    mabulous

    Joined:
    Jan 4, 2013
    Posts:
    198
    thanks! Is there any difference between using multiple renderer components and using one renderer component with multiple materials (if there is only a single submesh)?
     
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yes. Using multiple renderer components is way slower because it requires multiple game objects meaning they get individually culled and rendered, and more annoying to use because it requires custom script components to access the sorting order for most renderers.:(

    But the render order stuff is rock solid and I know of no bugs with it, hence why it's a work around.

    Multiple materials on a renderer with mesh that only has a single submesh seems to work pretty well, but you can run out of valid range for the material queue fairly quickly on complex scenes. You only have between 2501 and 3999 to work with as you need each object to have a unique set of materials and queue range.


    Technically there is one other work around, which is to do all your rendering manually via command buffers.
     
    mabulous likes this.