Search Unity

Object behind is rendering through seemingly opaque object

Discussion in 'General Graphics' started by Lekret, Feb 1, 2021.

  1. Lekret

    Lekret

    Joined:
    Sep 10, 2020
    Posts:
    358
    I have two objects. Green quad and 9 grey cubes in front of it. Both have own materials with rendering mode set to "Transparent". Gray material's color is 255-255-255-255, but when you look from the specific angle the green quad is partially rendering in front of gray cubes. Video:


     
    Last edited: Feb 1, 2021
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Unfortunately, this is working as expected. Fast, accurate, and efficient sorting of real time transparency remains an unsolved problem. Maybe someday raytracing will get fast enough that we'll just be rendering everything with it, but for now it remains a problem.

    I've written about it here:
    https://forum.unity.com/threads/render-mode-transparent-doesnt-work-see-video.357853/#post-2315934

    And a little more thoroughly here:
    https://realtimevfx.com/t/transparency-issues-in-unity/4337/2

    In this specific case, Unity sorts transparent objects by the distance from the camera to the center of the renderer's spherical bounds. You have a single quad on the ground, which is sometimes closer to the camera than those back 3 cubes, so it renders first. Again, Unity is just sorting based on the spherical bounds, it doesn't know or care if the quad is aligned to the ground (like it is in your case) or aligned to face the camera (in which case it'd look a little better).

    Outside of manually sorting the objects yourself, there aren't really any perfect solutions. And as described in the above links, that's not actually perfect, just good enough for what you're trying to do above since there aren't any intersections and all your objects are convex. Perfectly correct sorting is referred to as Order Independent Transparency, and the only way that's possible is by sorting the individual transparent pixels after you finish rendering. That requires keeping a running list of the depth and blend of every transparent pixel rendered in a per pixel list, sorting them, and then combining them. This is possible, but I say it's not "perfect" because it requires an unbounded amount of memory and is excruciatingly slow in practice.

    Beyond that there are Approximate Order Independent Transparency options. The most popular options are some form of stochastic transparency (aka, random dithered alpha testing), depth peeling and weighted blending. The last two options someone made an example Unity project here:
    https://github.com/candycat1992/OIT_Lab
    Unfortunately, that project is 5 years old and doesn't necessarily work anymore with recent versions of Unity.

    Depth peeling is potentially 100% accurate, but only up to some fixed number of layers, with each layer you add significantly increasing the cost of the technique.

    The weighted blending technique is cheap and fast, but also has one rather significant limitation ... it utterly fails with nearly (or fully) opaque objects. It's also not really alpha blending, but more akin to a modified additive blend so it can be harder to tell which object is on top of another compared to real alpha blending with correct sorting.

    But these remain the state of the art for efficient approximate OIT, even with depth peeling being 12 years old and weighted blended transparency being 7 years old. There are some tweaks to the weighted blended that make it slightly better, but not a lot. And there are some newer techniques Intel has shown off but those only work on Intel integrated GPUs which mean they're kind of useless.
     
  3. Lekret

    Lekret

    Joined:
    Sep 10, 2020
    Posts:
    358
    Okay, thanks for such detailed answer. Will keep in mind next time.
     
  4. AndroidDoctorr

    AndroidDoctorr

    Joined:
    Jul 12, 2021
    Posts:
    1
    Thank you so much for this! I applied this logic to my situation and it worked.

    I have a hollow cylinder cut in half length-wise. One half is transparent and the other half is opaque. Inside is a particle system (plasma flowing through a conduit). Since the plasma extended out slightly further than the cylinder, Unity was rendering the PS first, so it looked like the plasma was outside the conduit. So I extended the model of the front half of the conduit out a little further and gave that piece a transparent material so it would have a slightly larger render radius without changing anything visually. That way it renders the front half of the conduit first, then the plasma.