Search Unity

Bug Render Queue not working with URP

Discussion in 'Universal Render Pipeline' started by ShavSkelet, Jul 25, 2022.

  1. ShavSkelet

    ShavSkelet

    Joined:
    Nov 29, 2017
    Posts:
    29
    I'm trying to make an object render behind everything (the stars in the sky) so I'm setting the material with the Unlit transparent shader and setting the render queue a low value (0~100) This works if the Scriptable renderer pipelines settings is set to nothing, but when i use the UniversalRP-HighQuality (Universal Render Pipeline Asset) in the Graphics settings the render queue doesnt work.
    Am I missing something on the URP Asset?

    The object's material shader is Unlit/Transparent and the render queue is set to 0. The cube object is in front of the other object.

    With the URP-High Quality asset setting the render queue below 2500 makes the object invisible
    c1.png

    But when I set the Scriptable renderer pipelines settings to none every works fine: c2.png


    Solution--------------------------------------------------------------------------------------------------------------
    I somehow managed to solve the problem but if you have a lot of materials in your project, you may not like the solution...
    I make a new shader with the shader graph (a simple one replicating the simple lit from the URP materials) applied this shader to a material and this one now has the render queue property (the simple lit from URP doesn't have it) Set the render queue from the opaque object to 3000 and the object that i want behind everything to 2502 and there you have it.

    cap.png
     
    Last edited: Jul 26, 2022
  2. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    URP needs the DepthOnly Pass defined correctly in the shader for meshes drawn as opaque otherwise it does not draw depth and the skybox (which is drawn between queue id 2500 and 2501) overwrites your mesh.

    It's weird that it works for you in built-in, might just be for the scene view actually, because above should be true there as well. Anything that is drawn before the skybox and does not write depth will be drawn over with the skybox.
     
    sarahnorthway likes this.
  3. ShavSkelet

    ShavSkelet

    Joined:
    Nov 29, 2017
    Posts:
    29
    So maybe... setting the render queue of the opaque materials to something like 3000 and then setting the "behind all" material to 2502 should work?
     
  4. marcospgp

    marcospgp

    Joined:
    Jun 11, 2018
    Posts:
    194
    Where would one be able to get this kind of information? Seems quite hard to find technical details for render queues just by googling :/

    Edit: I was able to also figure this out by moving an object in the render queue until it displayed over the Skybox (with depth write set to force disabled). It only displayed over starting at render queue value 2501. Note I first had to apply the fix I posted below of disabling depth priming.
     
    Last edited: Dec 14, 2023
  5. marcospgp

    marcospgp

    Joined:
    Jun 11, 2018
    Posts:
    194
    I have new information - have you tried disabling depth priming in the URP renderer settings?

    This made depth write/depth test start being respected for my material. Possibly render queues were also affected. Just posted this as a bug in this forum.
     
  6. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    @marcospgp
    depth priming is really messing with giving a simple answer to this problem xD

    so what depth priming does in the end is forcing a depth pre-pass in the game view (scene view does this always anyway) and then when the game renders the opaque queue it changes the depth test from LessEqual to just Equal. Since depth has already been resolved in the pre-pass we get zero fragment overdraw from the main-pass.

    with priming disabled depth is copied from the main framebuffer.


    as to where to find infos on that .. I got to admit.. it's mostly picked up knowledge from this forum.. even knowing what I was looking for it took more than one attempt to find the manual page
    https://docs.unity3d.com/Manual/built-in-rendering-order.html



    So the situation becomes this

    opaque objects should be drawn before 2500 because afterwards depth will not be written and the sorting order changes from back to front - and now:
    if priming enabled or scene view -> configure queue correctly + have a valid depthOnly pass defined in shader + depth write enabled -> to have the object show up
    if priming disabled and game view -> configure queue correctly + depth write enabled -> to have the object show up

    but don't skip defining the depthOnly pass, disconnecting scene and game view will just lead to problems and confuse everyone.

    another interesting side note. A shader with compilation errors (usually 100% magenta) will not show up at all when depth priming is enabled except if the mesh is placed exactly on another (and then it will z-fight) because it can not write in the depth pre pass.

    tbh I think it could be that if you write the depth only pass manually (i.e. not shadergraph) it probably is even possible to create a shader which be included in the depth pre pass but would not write depth if priming was not enabled but that would again be utterly wrong and confusing.
     
    Last edited: Dec 15, 2023
  7. marcospgp

    marcospgp

    Joined:
    Jun 11, 2018
    Posts:
    194
    @fleity I could reproduce all issues in both scene and game views regarding depth priming, so I'm not sure there is that much difference - at least when it comes to affecting the z-buffer and render queues.

    By disabling depth priming I was able to render something behind everything else by not writing to z-buffer in the material and giving it a lower render queue value.

    The issue is if I add a skybox material, because it has a higher render queue, it will draw over the object (as the z-buffer doesn't know about it).

    What I would really need is a way to draw something in a render queue after the skybox, but only on skybox pixels (unset z-buffer values perhaps). This would avoid overdraw for the same reason that the skybox is also in a higher render queue.

    This might only be possible with something like a custom scriptable render pipeline, in order to modify the z-buffer check logic with a new condition (that checks for unset/skybox depth values).

    A workaround is to place this logic in the fragment shader, which obviously does not avoid having to run the fragment shader for skybox objects, but could still check the z-buffer and draw on top of the skybox.

    Or maybe I could just not have a skybox material and make the skybox just another object with this "render behind everything else" material.

    Update: Figured out how to only draw over skybox, first by setting material's render queue to 2501 (just after skybox which is drawn between 2500 and 2501), then using shader graph to set alpha based on depth buffer:

    upload_2023-12-15_23-25-7.png
     
    Last edited: Dec 15, 2023
    fleity likes this.
  8. fleity

    fleity

    Joined:
    Oct 13, 2015
    Posts:
    345
    @marcospgp Looks like a reasonable solution.
    If you want to avoid the scene depth sample (because Idk maybe depth texture is evil on target platform) you could also set the vertex z-position in clip space to 99% of the far plane. That would even work for opaque objects rendered before the skybox. But it will result in "wrong" depth values (actually utterly correct very far away depth values).