Search Unity

Is It Possible To Clip a Sprite With Another Sprite?

Discussion in 'Shaders' started by Angry-Water, Jun 27, 2014.

Thread Status:
Not open for further replies.
  1. Angry-Water

    Angry-Water

    Joined:
    Sep 11, 2012
    Posts:
    58
    Hi, Pals,

    I am not familiar with ShaderLab or CG Hardware, so I am not sure if this is possible?

    I wanna to clip a Sprite (or particles, something else, too) with another Sprite, such as:


    for [Portal]

    and this



    for hide.

    I want the result to be like this:



    I have referred these 2 articles to do some test:

    http://forum.unity3d.com/threads/clip-texture-based-on-depth-buffer.148379/

    and

    http://answers.unity3d.com/questions/590800/how-to-cullrender-to-through-a-window.html


    BUT, actually, the results are something like this:


    (It drew on the POLYGON shape, NOT PER PIXEL TEST.)

    Or if I try the BLEND op, it will be like that:


    (Actually, if there are something else drew before these two things, the result will be the same with the last picture.)

    I have tried to google Stencil Buffer, Alpha Blending things, but NO good luck, seems the hardware do NOT allow the Stencil Buffer writing base on Alpha Channel?

    I will be deeply appreciate your help if some Shader expert can tell me how to achieve my original goal with Shader --- Clip a Sprite (or Particles) with Another Sprite? Or please just let me know the CG hardware do not allow this kind of work in Unity3D.

    Thanks,
     
    Last edited: Jun 27, 2014
  2. mouurusai

    mouurusai

    Joined:
    Dec 2, 2011
    Posts:
    350
    <<I have tried to google Stencil Buffer, Alpha Blending things, but NO good luck, seems the hardware do NOT allow the Stencil Buffer writing base on Alpha Channel?>>
    You sholud use "discard" or "AlphaTest"
    upd
    For some reason it's doesn't work in DX11 and DX9 Deferred Lighting mode.

    Code (csharp):
    1.  
    2. Shader "Cg/ButtonsMask"{
    3. Properties
    4. {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6. }
    7.  
    8. SubShader
    9. {
    10.         Tags {"Queue"="Transparent+1" "IgnoreProjector"="True"}
    11.         ZWrite Off
    12.         AlphaTest Greater 0.5
    13.         ColorMask 0
    14.         ZTest Always
    15.  
    16.  
    17.         Stencil {
    18.                                 Ref 1
    19.                                 Comp always
    20.                                 Pass replace
    21.                         }
    22.  
    23.      
    24.         Pass
    25.         {
    26.                 CGPROGRAM
    27.                         #pragma vertex vert
    28.                         #pragma fragment frag
    29.                      
    30.                         #include "UnityCG.cginc"
    31.  
    32.                         struct appdata_t
    33.                         {
    34.                                 float4 vertex : POSITION;
    35.                                 float2 texcoord : TEXCOORD0;
    36.                         };
    37.  
    38.                         struct v2f
    39.                         {
    40.                                 float4 vertex : SV_POSITION;
    41.                                 half2 texcoord : TEXCOORD0;
    42.                         };
    43.  
    44.                         sampler2D _MainTex;
    45.                         float4 _MainTex_ST;
    46.                      
    47.                         v2f vert (appdata_t v)
    48.                         {
    49.                                 v2f o;
    50.                                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    51.                                 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
    52.                                 return o;
    53.                         }
    54.                      
    55.                         fixed4 frag (v2f i) : COLOR
    56.                         {
    57.                                 fixed4 col = tex2D(_MainTex, i.texcoord);
    58.                                 //if(col.a<0.1)discard;
    59.                                 return col;
    60.                         }
    61.                 ENDCG
    62.         }
    63. }
    64.  
    65. }
    66.  
    67.  
    Code (csharp):
    1.  
    2. Shader "Cg/Buttons"{
    3. Properties
    4. {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6. }
    7.  
    8. SubShader
    9. {
    10.         Tags {"Queue"="Transparent+2" "IgnoreProjector"="True" "RenderType"="Transparent"}
    11.         ZWrite Off
    12.         Blend SrcAlpha OneMinusSrcAlpha
    13.  
    14.         Stencil {
    15.                                 Ref 1
    16.                                 Comp Equal
    17.                         }
    18.      
    19.         Pass
    20.         {
    21.                 CGPROGRAM
    22.                         #pragma vertex vert
    23.                         #pragma fragment frag
    24.                      
    25.                         #include "UnityCG.cginc"
    26.  
    27.                         struct appdata_t
    28.                         {
    29.                                 float4 vertex : POSITION;
    30.                                 float2 texcoord : TEXCOORD0;
    31.                         };
    32.  
    33.                         struct v2f
    34.                         {
    35.                                 float4 vertex : SV_POSITION;
    36.                                 half2 texcoord : TEXCOORD0;
    37.                         };
    38.  
    39.                         sampler2D _MainTex;
    40.                         float4 _MainTex_ST;
    41.                      
    42.                         v2f vert (appdata_t v)
    43.                         {
    44.                                 v2f o;
    45.                                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    46.                                 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
    47.                                 return o;
    48.                         }
    49.                      
    50.                         fixed4 frag (v2f i) : COLOR
    51.                         {
    52.                                 fixed4 col = tex2D(_MainTex, i.texcoord);
    53.                                 return col;
    54.                         }
    55.                 ENDCG
    56.         }
    57. }
    58.  
    59. }
    60.  
    61.  
     
    Last edited: Jun 27, 2014
    Angry-Water likes this.
  3. Angry-Water

    Angry-Water

    Joined:
    Sep 11, 2012
    Posts:
    58

    WOOOOOW.....That's brilliant !!!! It's work !!!! (on Mac or iOS devices, "Discard" works, but "Alpha Test" is not working for my codes.)

    Many many many deep appreciation !!!!! :)

    In my situation, I am using 2D system of Unity3D, the codes are modified from the "Sprite-Default" offered by Unity3D 4.5.1 here:
    http://unity3d.com/unity/download/archive

    I set them as "Sprite/Stencil Mask" and "Sprite/Stencil Draw In Mask".

    Mask:
    Code (CSharp):
    1. Shader "Sprites/Stencil Mask"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent"
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ZWrite Off
    24.         Fog { Mode Off }
    25.         Blend One OneMinusSrcAlpha
    26.  
    27.         Pass
    28.         {
    29.             Stencil
    30.             {
    31.                 Ref 1
    32.                 Comp always
    33.                 Pass replace
    34.             }
    35.      
    36.         CGPROGRAM
    37.             #pragma vertex vert
    38.             #pragma fragment frag
    39.             #pragma multi_compile DUMMY PIXELSNAP_ON
    40.             #include "UnityCG.cginc"
    41.      
    42.             struct appdata_t
    43.             {
    44.                 float4 vertex   : POSITION;
    45.                 float4 color    : COLOR;
    46.                 float2 texcoord : TEXCOORD0;
    47.             };
    48.  
    49.             struct v2f
    50.             {
    51.                 float4 vertex   : SV_POSITION;
    52.                 fixed4 color    : COLOR;
    53.                 half2 texcoord  : TEXCOORD0;
    54.             };
    55.      
    56.             fixed4 _Color;
    57.  
    58.             v2f vert(appdata_t IN)
    59.             {
    60.                 v2f OUT;
    61.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    62.                 OUT.texcoord = IN.texcoord;
    63.                 OUT.color = IN.color * _Color;
    64.                 #ifdef PIXELSNAP_ON
    65.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    66.                 #endif
    67.  
    68.                 return OUT;
    69.             }
    70.  
    71.             sampler2D _MainTex;
    72.  
    73.             fixed4 frag(v2f IN) : SV_Target
    74.             {
    75.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    76.                 if (c.a<0.1) discard;            //Most IMPORTANT working Code
    77.                 c.rgb *= c.a;
    78.                 return c;
    79.             }
    80.         ENDCG
    81.         }
    82.     }
    83. }
    84.  

    Draw In Stencil Mask:
    Code (CSharp):
    1. Shader "Sprites/Stencil Draw In Mask"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Tags
    13.         {
    14.             "Queue"="Transparent+1"              //DON'T FORGET this must be drew later to catch Stencil Ref value.
    15.             "IgnoreProjector"="True"
    16.             "RenderType"="Transparent"
    17.             "PreviewType"="Plane"
    18.             "CanUseSpriteAtlas"="True"
    19.         }
    20.  
    21.         Cull Off
    22.         Lighting Off
    23.         ZWrite Off
    24.         Fog { Mode Off }
    25.         Blend One OneMinusSrcAlpha
    26.  
    27.         Pass
    28.         {
    29.             Stencil
    30.             {
    31.                 Ref 1
    32.                 Comp Equal
    33.             }
    34.  
    35.         CGPROGRAM
    36.             #pragma vertex vert
    37.             #pragma fragment frag
    38.             #pragma multi_compile DUMMY PIXELSNAP_ON
    39.             #include "UnityCG.cginc"
    40.      
    41.             struct appdata_t
    42.             {
    43.                 float4 vertex   : POSITION;
    44.                 float4 color    : COLOR;
    45.                 float2 texcoord : TEXCOORD0;
    46.             };
    47.  
    48.             struct v2f
    49.             {
    50.                 float4 vertex   : SV_POSITION;
    51.                 fixed4 color    : COLOR;
    52.                 half2 texcoord  : TEXCOORD0;
    53.             };
    54.      
    55.             fixed4 _Color;
    56.  
    57.             v2f vert(appdata_t IN)
    58.             {
    59.                 v2f OUT;
    60.                 OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    61.                 OUT.texcoord = IN.texcoord;
    62.                 OUT.color = IN.color * _Color;
    63.                 #ifdef PIXELSNAP_ON
    64.                 OUT.vertex = UnityPixelSnap (OUT.vertex);
    65.                 #endif
    66.  
    67.                 return OUT;
    68.             }
    69.  
    70.             sampler2D _MainTex;
    71.  
    72.             fixed4 frag(v2f IN) : SV_Target
    73.             {
    74.                 fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
    75.                 c.rgb *= c.a;
    76.                 return c;
    77.             }
    78.         ENDCG
    79.         }
    80.     }
    81. }
    82.  
    I am trying to set a changeable "Ref" value for different type of objects.

    Anyway, the codes above work for the same stencil "Ref" value, for other guys who need it. ;)
     
    Last edited: Jun 28, 2014
  4. vegenarie

    vegenarie

    Joined:
    Jan 5, 2011
    Posts:
    287
    I think just editing the image in Unity and enable the option to use just alpha as transparent, cause discard is expensive.
     
    rakkarage likes this.
  5. Angry-Water

    Angry-Water

    Joined:
    Sep 11, 2012
    Posts:
    58
    I don't know, just remembered didn't work last time I tried alpha as transparent.

    Have you tried that and have good luck?

    Since these codes are modified from official Sprite-Default, it seems always writing stencil buffer whether the alpha value is, except the discard function.
     
  6. Angry-Water

    Angry-Water

    Joined:
    Sep 11, 2012
    Posts:
    58
    I've tried it again, as I said, it doesn't work using any Alpha testing things, but except the "discard" command. Since any test still writing an alpha value with stencil ref value to buffers, so it became NON-PIXEL detail.
     
  7. esco1979

    esco1979

    Joined:
    Mar 18, 2014
    Posts:
    138
    Hate to ask, but how can I use the above 2 shaders in unity? I basically want to use the shader to take a gradient sprite and place it over another solid color sprite.
     
    Gamba04 likes this.
  8. Angry-Water

    Angry-Water

    Joined:
    Sep 11, 2012
    Posts:
    58
    Why hate? Post it for sharing, just take it, please.
     
  9. esco1979

    esco1979

    Joined:
    Mar 18, 2014
    Posts:
    138
    Lol, no, no you misunderstood. I was asking how (step by step) to use your amazing shader in Unity. I am completely new to them. I was saying I HATE TO ASK HOW TO USE IT, because I know it is such a n00b question. :)

    I am making a 2d game, and I could use this shader for multiple overlay effects
     
    Last edited: Jul 7, 2014
    Gamba04 likes this.
  10. CarpetHead

    CarpetHead

    Joined:
    Nov 22, 2013
    Posts:
    20
    I tried to use this, because it sounds awesome - but when i apply each shader to a material, and put one on one sprite, and one on the other nothing happens - both of them render normally.

    Do you know why this is or how to get it working?
     
  11. meteory.liu

    meteory.liu

    Joined:
    Jul 25, 2014
    Posts:
    2
     
  12. EMinorDream

    EMinorDream

    Joined:
    Nov 4, 2014
    Posts:
    1
    Hi, I'm new to Unity 2D development and I'd also really like to be able to clip sprites like this. I've taken your shaders, applied them to materials, and assigned those materials in the sprite renderer, but the sprites render normally. Is there something more I need to do?

    This would be such a useful bit of functionality for making 2D animations. I hope eventually there is a built in way to handle it.
     
    rakkarage likes this.
  13. itsa

    itsa

    Joined:
    Feb 4, 2014
    Posts:
    10
    Does anybody know how to get the texture of the mask to render?
     
  14. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Greatly appreciated!! You should upload the shaders in the asset store to make some money :).
     
  15. Broni

    Broni

    Joined:
    Oct 28, 2013
    Posts:
    2
    Hi, sorry for my Engleesh)
    For all this to work, you need to add one line after 32 line in "Stencil Draw In Mask". It is:
    Pass Keep
    Maybe it will help someone
     
  16. PoL231

    PoL231

    Joined:
    Jun 27, 2014
    Posts:
    148
  17. Aedous

    Aedous

    Joined:
    Jun 20, 2009
    Posts:
    244
    Any chance of getting it to work with sorting layers and order in layer ?
     
    Last edited: Mar 9, 2015
  18. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    If you change "Queue"="Transparent+1" to "Queue"="Transparent" in the Stencil Draw In Mask shader will do the trick. It will render the shader with all the other shaders in that queue. It does the trick on my computer, however i never wrote any shader before so just make sure it works on your target platform.
     
  19. trul

    trul

    Joined:
    Nov 15, 2013
    Posts:
    9
    Thanks a lot! It works great!
    What if the mask sprite has transparency values?
    Is it possible to use transparency levels as mask too?
     
    Oruji, kuchaku and Tomer-Barkan like this.
  20. vladpazych

    vladpazych

    Joined:
    Aug 26, 2015
    Posts:
    6
    I have the same question. Trying to make effect like 2D fog of war.

    Did you found the answer?
     
  21. Deleted User

    Deleted User

    Guest

    Any answer to this last question ? (just posted a thread about that... sorry.)
     
  22. samifruit514

    samifruit514

    Joined:
    Mar 27, 2015
    Posts:
    30
    Someone can explain this line?:
    if (c.a<0.1) discard; //Most IMPORTANT working Code

    Im asking this because the masking does not work as expected. The alpha on the edges where the mask and the "in-mask" collides seems to be full colored. There is no "semi-transparency" so its looking a bit weird. I have the feeling that this "discard" line is not the good way to do with my transparency.

    To reproduce:
    - Add a 2D sprite
    - Affect stencil mask shader to this sprite
    - Add another 2d sprite inside the previous one with "stencil in mask" shader
    - Zoom the edge of the mask where its colliding with the "stencil mask"

    Expected:
    The mask (first sprite)'s alpha should be the same as the original alpha (like if you open the png in gimp)

    Actual:
    instead of a smooth line, you get weird bumps.
     
  23. Oruji

    Oruji

    Joined:
    Nov 5, 2012
    Posts:
    14
    Bumping this thread in hope that someone has the answer to trul's question about the alpha blend.
     
  24. hitelite

    hitelite

    Joined:
    Mar 7, 2016
    Posts:
    1
    I'd like to know this too if anyone has the answer. I'm sure it's pretty simple but I'm pretty new to all this.
     
    Last edited: Feb 23, 2020
  25. rengelbert

    rengelbert

    Joined:
    Jul 13, 2015
    Posts:
    2
    The one information missing in the thread, unless my eyes deceive me, is that the Sprite Renderer "Order in Layer" property must be different. The mask will have a lower value than the masked sprite, so for example 0 for the mask and 1 for the masked sprite.
    Oh hell... here are the steps:
    - create two sprites in the scene, one is the mask and the other is the masked
    - create two materials in your project (right click inside Assets and Create Material)
    - call the material something like Mask and Masked.
    - Create two shaders with Create-Shader, and call them MaskShader and MaskedShader or whatever
    - Open the each shader and copy and paste the code for the two shaders given in this post (thanks for all responsible for those, btw) Stencil Mask is the the mask and the draw one is for Masked sprites
    - Change the Shader in the materials you created, the mask material will have the mask shader, and the masked material will have the masked shader
    - Change the material in each of the sprites you created, inside their Sprite Renderer component. The mask sprite renderer will have the mask material and a Order in Layer value of 0. the masked sprite will have the makes material and an Order In Layer of 1
    Boom. done. Hope that helps.
    But how can I make the mask invisible?
     
  26. rengelbert

    rengelbert

    Joined:
    Jul 13, 2015
    Posts:
    2
    Uhmmm...
    Changing the alpha threshold does it (the hiding the mask thing)...
    As a matter of fact if I remove this line from the stencil mask shader:
    if (c.a<0.1) discard; //Most IMPORTANT working Code
    Instead of just using a ridiculously low value for alpha I get what I want... but I'm guessing it won't work on mobiles or something? based on my general luck... anyway... time to test it.
     
  27. rendermouse

    rendermouse

    Joined:
    Dec 9, 2015
    Posts:
    8
    Well, I definitely needed it. :) The Stencil Mask and Stencil Draw In Mask shaders worked PERFECTLY for me.

    All I needed was a way to have one rect clip all sprites in the scene, and work on Android (which Depth Mask did NOT).

    I created one plane using the Stencil Mask shader, and set all sprites to use the Stencil Draw In Mask shader, and everything worked beautifully.

    Thank you all for sharing this solution! It really made my day.
     
  28. Schminitz

    Schminitz

    Joined:
    Nov 15, 2013
    Posts:
    16
    Just wanted to thank you, you saved me a lot of hours here!
     
  29. asry

    asry

    Joined:
    Jul 13, 2015
    Posts:
    1
    i have problem

    1panel(Ngui Panel)
    -sprite(mask depth0)
    -sprite(draw in mask depth1)

    if no panel this shader good!!!! awesome!!!! its work!!

    but in panel didnt work..

    another question

    scene
    -sprite1(mask depth0)
    -sprite2(draw in mask depth1)
    -sprite3(mask depth2)
    -sprite4(draw in mask depth3)

    sprite2 and 4 visible through sprite1 and sprite3!!

    thank you
     
Thread Status:
Not open for further replies.