Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Preventing Unlimited Transparency Sampling

Discussion in 'Shaders' started by PancakeMan, May 6, 2018.

  1. PancakeMan

    PancakeMan

    Joined:
    May 6, 2018
    Posts:
    5
    Hey everyone, I have this simple transparency shader and I was wondering if it is possible for a shader to draw itself as opaque if there are 3 or more objects in front of it.



    In the image, the area where all three orange blocks overlap isn't completely opaque but it might as well be. I'm hoping I can save a little on performance if I can prevent rendering anything that is behind 3 levels deep of transparency.

    This is the shader I am currently using.

    Code (Boo):
    1. Shader "SimpleTransparent"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    6.     }
    7.  
    8.     Category
    9.     {
    10.         Tags{ "Queue" = "Transparent" }
    11.         Lighting Off
    12.         BindChannels
    13.         {
    14.             Bind "Color", color
    15.             Bind "Vertex", vertex
    16.             Bind "TexCoord", texcoord
    17.         }
    18.  
    19.         Blend SrcAlpha OneMinusSrcAlpha
    20.  
    21.         SubShader
    22.         {
    23.             Pass
    24.             {
    25.                 SetTexture[_MainTex]
    26.                 {
    27.                     Combine texture * primary
    28.                 }
    29.             }
    30.         }
    31.     }
    32. }
    I was looking at ZTest but from the examples I've seen it looks like if it is just a single object in front. I'm still very new to shaders.

    Thanks.
     
    IgorAherne likes this.
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,836
    It's not a very easy thing to achieve. You can look into order-independent transparency, but I don't think it's a thing for people very new to shaders :)
    When you're rendering something, the shader has no information of what's behind or in the front of the pixel being rendered.
     
    PancakeMan likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    One thing to understand is transparent objects render back to front. That is the objects further away render first. This is to ensure the correct draw order of transparent objects. Think of it like putting down stickers on a piece of paper; you have to put down the ones in the "back" first because you can't put stickers behind them afterwards with out ripping them off and damaging the paper or the sticker. So you can't make the transparent object in the back opaque based on stuff that's in front since what's in front hasn't been rendered yet.

    Now it is possible to render front to back transparency and to use stencils to cull drawing after enough layers have rendered. But to do that requires rendering all transparencies to an off screen buffer and using destination alpha and the scene depth buffer to composite. Then using an incrementing stencil to skip rendering after some threshold. Then composite that buffer back into the main frame buffer. This is a technique I believe the RedLynx Trials games used on their early titles, but I don't believe they use anymore.

    If the above paragraph sounds like gibberish to you, it is not something I would recommend you get into yet.
     
    PancakeMan likes this.
  4. Seyed_Morteza_Kamaly

    Seyed_Morteza_Kamaly

    Joined:
    Nov 18, 2015
    Posts:
    80
  5. PancakeMan

    PancakeMan

    Joined:
    May 6, 2018
    Posts:
    5
    Thank you for the swift responses!

    Thanks for the explanations. The first part was familiar, things I've forgotten.
    Front to back rendering sounds like a fun thing to try but perhaps an experiment for another time. The effort involved to avoid overdraw sounds like it won't be practical to venture into and may not even save the performance I'm looking for.

    Much thanks.
     
  6. Seyed_Morteza_Kamaly

    Seyed_Morteza_Kamaly

    Joined:
    Nov 18, 2015
    Posts:
    80


    In the left configuration, the red glass doesn't look transparent at all. Why is that so? The render order of the objects is red then green then blue. When red is rendered, the Z-values in the depth buffer are set and no fragment from another triangle with a farther away Z-value will be rendered at all. So there is no chance to blend green and blue because their fragments are discarded before blending.

    In the center configuration, depth testing has been artificially turned off. First red is rendered with nothing to blend it with since it is the first thing rendered. Then green is rendered and blended and blue is rendered and blended. Each time the new object will take 50% of itself and 50% from the already rendered objects, so at the time blue is rendered, only 25% of red will be left.

    In the right configuration, depth testing has been re-enabled but the rendering order has been changed to back to front: First blue then green then red. When red is rendered, it takes 50% of itself and 50% of the already rendered objects which creates the correct effect.

    http://www.ventuz.com/support/help/v3_01/RealtimeRendering.html
     
    PancakeMan likes this.
  7. PancakeMan

    PancakeMan

    Joined:
    May 6, 2018
    Posts:
    5
    Nice visual representation Seyed, it looks like Front to Back as presented wouldn't be desirable in my case either. Which brings even more clarity to me about the technique bgolus was referring to.

    I also looked at order-independent transparency but that didn't quite look like what I would need.

    If only I could know how many things there are waiting to be rendered over the same pixel and how many have already been to save on performance when I have 10 transparent objects overlapping each other so all 10 wouldn't have to blend.
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Actually, the advanced technique I was describing would look exactly like back to front sorting, but use front to back. Unfortunately the presentation I remember it being detailed in was difficult to find last time I looked a few years ago, and has now completely disappeared from the web as far as I can tell. I had a copy of it on my old work computer at my last job, but I forgot to grab it before I left.

    However, I did find this post which describes a similar base technique:
    http://hacksoflife.blogspot.com/2010/02/alpha-blending-back-to-front-front-to.html

    Augment that technique with using the stencil buffer like this:
    Code (csharp):
    1. Stencil {
    2.     Ref 255
    3.     Comp NotEqual
    4.     Pass IncrSat
    5. }
    Change 255 to any value between 1 and 255 to set the number of layers to render before skipping.
     
    Prodigga and PancakeMan like this.
  9. PancakeMan

    PancakeMan

    Joined:
    May 6, 2018
    Posts:
    5
    Cool, that's what I thought. What I was trying to say was normal front-to-back wouldn't be right but that plus stencils might. (I also thought stencil was a metaphor :D)

    That stencil thing is pretty sweet. Even with testing normal back to front I can see how it prevents rendering and blending of additional surfaces.
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Yeah, it's an interesting technique. But it comes at the cost of needing a second framebuffer with a full fat depth buffer since only 24 bit depth buffers have a stencil, and you can't use the stencil buffer for anything else.

    Usually it's easier and more efficient to just avoid that much overdraw manually or possibly use some kind of two pass technique. For the case you presented of solid color polygons you'll need a lot of overdraw before it's really an issue.
     
  11. PancakeMan

    PancakeMan

    Joined:
    May 6, 2018
    Posts:
    5
    Unfortunately for me, my game is pretty much nothing but overdraw. It runs pretty well for the most part thanks to simple geometry but there are some instances were it chugs.

    Perhaps I can save on performance by using a solid material for objects that are far away from the player and then switching the material when the player gets close enough. Hopefully I can avoid it looking weird if I also apply the transparency over time instead of just hot swapping it out.
     
  12. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You could look into rendering to a buffer that's smaller, this should save you a ton of performance at cost of being lower resolution. Primitive, but always works well. Jason Booth has an asset on asset store for this for free.
     
    bgolus and PancakeMan like this.