Search Unity

Question How to render a transparent object on top of a transparent object?

Discussion in 'Shaders' started by unfa, Nov 28, 2022.

  1. unfa

    unfa

    Joined:
    Oct 10, 2019
    Posts:
    13
    I am working in Unity 2021.3.0f1 using HDRP 12.1.6

    I am creating objects comprised of multiple transparent parts.
    However Unity only renders one (nearest to camera) layer of transparency, and anything more between it and solid materials behind is ignored.
    I have been searching high and low to find a solution, to no avail - I see that people are doing things like that, but in my project it seems impossible. I suspect there's some secret HDRP setting that controls this, but I could not find it.

    upload_2022-11-28_15-31-0.png
    Here with the middle sphere using a refractive orange material:
    upload_2022-11-28_15-35-7.png

    As you can see the front-most sphere ignores the middle one and the furthest one is rendered as if nothing was between the two.

    I have tested everything I could. Depth Test, Back Then Front Rendering...

    The *only* think that allowed me to have two layers of transparency is putting the front-most object into "Low Resolution" render pass. It is unfortunately not an acceptable solution, plus it breaks when the object on Low Resolution pass is in the back:

    upload_2022-11-28_15-40-56.png
    As you can see here the refraction is ignoring the transparent object behind:
    upload_2022-11-28_15-41-7.png

    How can I achieve multiple layers of alpha blended transparency?

    upload_2022-11-28_15-42-6.png

    These materials use HDRP Lit shader, but I have exactly the same problems using ShaderGraph instead.
     
    Last edited: Nov 28, 2022
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Multiple transparent materials are visible through each other by default.
    upload_2022-11-28_12-51-56.png

    However there are two options that will prevent this. Enabling Transparent Depth Prepass, or enabling Refraction of any kind will prevent other transparencies from being visible behind that object, unless the other transparent objects are both not using refraction and set to render before refraction (like the green sphere below).
    upload_2022-11-28_12-57-48.png

    But similar to your "low resolution fix" above, it means that green sphere will always be rendered "behind" those using refraction, and they'll appear in that refraction similar to opaque objects that are in front of refractive materials.
    upload_2022-11-28_13-0-4.png

    The fix is ... there isn't one*. This is kind of a fundamental limitation of rasterization due to the fact the "refraction" is entirely faked by taking a copy of the screen at some point in the rendering pipeline and distorting it. You can do this multiple times in the pipeline, but each time you do it adds a significant cost. The built in rendering path allows you to do this for every individual transparent object if you wished, but that came with that afore mentioned cost. It was very easy to completely shoot yourself in the foot performance wise like this. So Unity made the intentional decision with both the URP and HDRP to limit this to a single time, either after opaques, or after opaques and any explicitly set transparencies (those set to Render Before Refraction).




    * Though, I lied. There is actually one solution. Raytracing.

    You need to enable DXR raytracing on the HDRP asset (use the Wizard to make this faster). Then you need to enable recursive rendering on the scene's volume, and on each of the transparent objects' materials. Then you'll get real refraction, and multiple refracting objects will be visible through eachother.
    upload_2022-11-28_13-14-47.png

    This of course will also be very, very expensive. But this is one of the things raytracing allows for.
     

    Attached Files:

  3. unfa

    unfa

    Joined:
    Oct 10, 2019
    Posts:
    13
    Thank you for this detailed explanation!

    It seems that my problem was caused by something different still - "Recieve SSR Transparent".

    On the left is HDRP Lit without"Recieve SSR Transparent" and on the right is one with:

    upload_2022-11-29_15-23-16.png

    Here also Surface Options for these two materials (Both using HDRP Lit shader):

    upload_2022-11-29_15-23-55.png

    I have discovered this by accident as I have created a simple transparent material and realized that transparency works as expected in it, but not with the other ones I have been working on. I analyzed the differences and found the culprit.

    I assume "Recive SSR transparent" forces Depth Prepass (or Postpass?) because it needs normals and depth pass to render SSR... I did not know about this limitation and have shot myself in the foot not even realizing that.
    I guess Unity editor could have a warning shown when enabling this with something like "Enabling this option will make transparent objects behind this material invisible" or something...

    Anyway - thank you!

    BTW - I had no idea it's possible to have "real" refraction - does that require a raytracing-capable GPU or is it done in a different way?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    I wouldn't be surprised if there were multiple things that can cause transparency overlapping to "break" beyond what I knew of and this one. I haven't looked into why, but your guess is probably pretty close.

    It requires a GPU with raytracing hardware and DXR (DirectX Raytracing) support.
     
  5. ashtorak

    ashtorak

    Joined:
    Feb 19, 2014
    Posts:
    53
    Did you do any more research on this?
    Is there some way around this limitation?
    Because as it stands now, it's not possible to have glass windows with reflections when you have other transparent stuff like water behind it or is there another way to do this?
     
  6. unfa

    unfa

    Joined:
    Oct 10, 2019
    Posts:
    13
    It would seem so. I guess the only solution would be to render the transparent object behind it in one pass, and then the reflective glass in front in another pass. I am not familiar with Unity enough to have an idea on how to do it, but I assume the Scriptable Rendering Pipeline is capable of doing that. Maybe a realtime updated cubemap or other reflection probe would also work? No idea.
     
    ashtorak likes this.