Is It Possible To Clip a Sprite With Another Sprite?

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:

and

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,

<<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.

Shader "Cg/ButtonsMask"{
Properties
{
        _MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader
{
        Tags {"Queue"="Transparent+1" "IgnoreProjector"="True"}
        ZWrite Off
        AlphaTest Greater 0.5
        ColorMask 0
        ZTest Always


        Stencil {
                                Ref 1
                                Comp always
                                Pass replace
                        }

     
        Pass
        {
                CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                     
                        #include "UnityCG.cginc"

                        struct appdata_t
                        {
                                float4 vertex : POSITION;
                                float2 texcoord : TEXCOORD0;
                        };

                        struct v2f
                        {
                                float4 vertex : SV_POSITION;
                                half2 texcoord : TEXCOORD0;
                        };

                        sampler2D _MainTex;
                        float4 _MainTex_ST;
                     
                        v2f vert (appdata_t v)
                        {
                                v2f o;
                                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                                return o;
                        }
                     
                        fixed4 frag (v2f i) : COLOR
                        {
                                fixed4 col = tex2D(_MainTex, i.texcoord);
                                //if(col.a<0.1)discard;
                                return col;
                        }
                ENDCG
        }
}

}
Shader "Cg/Buttons"{
Properties
{
        _MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader
{
        Tags {"Queue"="Transparent+2" "IgnoreProjector"="True" "RenderType"="Transparent"}
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        Stencil {
                                Ref 1
                                Comp Equal
                        }
     
        Pass
        {
                CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                     
                        #include "UnityCG.cginc"

                        struct appdata_t
                        {
                                float4 vertex : POSITION;
                                float2 texcoord : TEXCOORD0;
                        };

                        struct v2f
                        {
                                float4 vertex : SV_POSITION;
                                half2 texcoord : TEXCOORD0;
                        };

                        sampler2D _MainTex;
                        float4 _MainTex_ST;
                     
                        v2f vert (appdata_t v)
                        {
                                v2f o;
                                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                                return o;
                        }
                     
                        fixed4 frag (v2f i) : COLOR
                        {
                                fixed4 col = tex2D(_MainTex, i.texcoord);
                                return col;
                        }
                ENDCG
        }
}

}
1 Like

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 !!! :slight_smile:

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:

Shader "Sprites/Stencil Mask"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Fog { Mode Off }
        Blend One OneMinusSrcAlpha

        Pass
        {
            Stencil
            {
                Ref 1
                Comp always
                Pass replace
            }
      
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile DUMMY PIXELSNAP_ON
            #include "UnityCG.cginc"
      
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };
      
            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
                if (c.a<0.1) discard;            //Most IMPORTANT working Code
                c.rgb *= c.a;
                return c;
            }
        ENDCG
        }
    }
}

Draw In Stencil Mask:

Shader "Sprites/Stencil Draw In Mask"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent+1"              //DON'T FORGET this must be drew later to catch Stencil Ref value.
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Fog { Mode Off }
        Blend One OneMinusSrcAlpha

        Pass
        {
            Stencil
            {
                Ref 1
                Comp Equal
            }
  
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile DUMMY PIXELSNAP_ON
            #include "UnityCG.cginc"
      
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };
      
            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;

            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
                c.rgb *= c.a;
                return c;
            }
        ENDCG
        }
    }
}

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. :wink:

7 Likes

I think just editing the image in Unity and enable the option to use just alpha as transparent, cause discard is expensive.

1 Like

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.

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.

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.

1 Like

Why hate? Post it for sharing, just take it, please.

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. :slight_smile:

I am making a 2d game, and I could use this shader for multiple overlay effects

1 Like

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?

[QUOTE=
I am trying to set a changeable “Ref” value for different type of objects.
[/QUOTE]

is there any way to make ‘Ref’ changeable?[/QUOTE]

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.

1 Like

Does anybody know how to get the texture of the mask to render?

Greatly appreciated!! You should upload the shaders in the asset store to make some money :).

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

Hey there!

If any one is interested in a “out of the box” solution for sprite masking, than Sprite Mask is just that what you are looking for :).

Asset Store link: http://u3d.as/aYo

More into: [Released] Sprite Mask - masking system for Unity Sprite - Community Showcases - Unity Discussions

Any chance of getting it to work with sorting layers and order in layer ?

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.

Thanks a lot! It works great!
What if the mask sprite has transparency values?
Is it possible to use transparency levels as mask too?

3 Likes

I have the same question. Trying to make effect like 2D fog of war.

Did you found the answer?