Search Unity

Stencil buffer

Discussion in 'Shaders' started by Petey09, Sep 21, 2016.

  1. Petey09

    Petey09

    Joined:
    Sep 21, 2016
    Posts:
    2
    Hello everyone,

    I'm having a little trouble with shader and stencil buffers lately and I was wondering if anyone could help me resolve it.

    Basically, what I'm trying to do is set up one viewport inside another using stencil buffers. I already have a main shader that fills the stencil buffer with a predetermined value like this :

    Code (csharp):
    1. Stencil
    2. {                
    3.     Ref [_Stencil]                
    4.     Comp always                
    5.     Pass replace            
    6. }
    I now need a second shader that would fill the stencil buffer with a new value only when the buffer corresponds to the old one. The expected result would be something like this :

    stencil.png
    I need to be able to dynamically change the reference of each view inside as they will be added/deleted freely. The only way I could achieve something close to my need is to use IncrSat in the second shader :

    Code (csharp):
    1. Stencil
    2. {                
    3.     Ref [_Stencil]                
    4.     Comp equal
    5.     Pass IncrSat
    6. }
    This will increase the reference in the buffer, but it'll not support more than one 1 viewport inside the main one. Each "inside" viewport would collide with the others and they are not suppose to show the same content.

    So my question is : is there an alternative way I could replace the values in the stencil buffer that would allow me to achievement more than one "inside" viewport?

    Thanks in advance!

    P.S. sorry for my english, I'm french.
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Why not use the comparison "GEqual" instead of "Equal" for the second block? I'm not sure I fully understand what you're trying to do.
     
  3. Petey09

    Petey09

    Joined:
    Sep 21, 2016
    Posts:
    2
    Thanks for your answer Gambit!

    I'll try my best to explain what the goal is.

    The first viewport (Ref 1) represents a windows with a scroller where the content should not be drawn outside of the frame. All other viewports (Ref 2 & 3) are contained inside the scroller so they should only appear inside the first viewport (Ref 1). Their content is therefore only rendered if it is intersecting with the main viewport and their own viewport.

    The way I was hoping to achieve this was to fill the stencil buffer with the first viewport (Ref 1) hence the first block. Then, for each viewport inside the main one, the second shader would compare the values in the stencil and it would switch it with its own value (any value as long as it is unique to each viewport) when it matches to first viewport value. That way, I could have multiple viewport inside the main one without their content rendering in each other since their ref value wouldn't be the same.

    The problem with the second block is that IncrSat would only increment the value in the stencil buffer for each internal viewport meaning that they all have the same reference value. Because of that, their content are not isolated and could render in any of the internal viewport, not just their designated one.

    Gequal wouldn't do the trick since the comparison is not the issue. The issue is really that the Pass only either switch for the reference, increment/decrement or switch for 0.

    By looking at the doc, I don`t think stencil buffer support what I'm trying to do. I was just hoping maybe I missed something or that somebody with a similar issue had a alternative for me.

    Thanks again!
     
  4. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Ahh, I see, so the big limiting issue here seems to be that the you can't use "replace" in the second block because you use the reference value for comparison?

    I've never actually done this, so this is all a bit of a guess. There are read/write masks for stencilling, so maybe you could use that. After you have your first block write a "1" to the stencil buffer, have the second block use an even-number stencil ref, "replace" on pass, a "NEqual" comp, and a read mask of "1". With that read mask, you will only be able to write where a "1" was put in the stencil buffer, and you will not be able to write there again because the 1 will go away when you replace it with an even number (with a readmask of 1, even numbers are 0).

    If you're doing this in UI, this could all be done super easily without stencilling if you use the "mask" component
     
  5. Seyed_Morteza_Kamaly

    Seyed_Morteza_Kamaly

    Joined:
    Nov 18, 2015
    Posts:
    80
    https://computergraphics.stackexcha...overlapping-semi-transparent-shapes/6053#6053