Search Unity

[Feature request] 9 slice support for sprite masks

Discussion in '2D' started by DoctorShinobi, Dec 13, 2020.

  1. DoctorShinobi

    DoctorShinobi

    Joined:
    Oct 5, 2012
    Posts:
    219
    Hey!
    I've stumbled upon what feels like missing functionality in sprite masks. When using sprite masks the mask won't respect sprites that are meant to be used as 9 slice sprites.

    Here's an example where I needed this feature: I created a 2D platform and wanted to decorate it with things that are only meant to render inside the platform itself. The platform is 9 slice, but the mask itself isn't. This means that no matter what I couldn't synchronize the mask to sit properly on the platform's sprite renderer.

    I eventually did find a workaround using URP render features. But this caused a bunch of other issues that could have been avoided if sprite masks supported 9 slice.
     
    lawlietsnow and MousePods like this.
  2. MousePods

    MousePods

    Joined:
    Jul 19, 2012
    Posts:
    811
    +1

    I also had to do not so nice workarounds when I learned this wasn’t a feature.
     
  3. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    Hi, we will add this to our backlog for consideration. If you have other feature requests related to Sprite Mask, such as masking other Renderers like TilemapRenderer/SpriteShapeRenderer or feathered masking, do let us know! Hearing multiple voices about this does help us in deciding which features to work on!
     
    Notian, MousePods and DoctorShinobi like this.
  4. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    436
    Thanks for the feedback. Would it be possible also to share some visuals or a sample project to confirm our understanding on what you are looking for?

    Happy Holidays!
     
  5. DoctorShinobi

    DoctorShinobi

    Joined:
    Oct 5, 2012
    Posts:
    219
    Sure. Here's what I needed it for:
    upload_2020-12-16_11-1-49.png

    These pink platforms are made of a 9 sliced sprite renderer defining the shape(square with round edges) and base colors. It masks two types of elements within in:
    - White stripes, which I need to keep proportional no matter the size of the platform. They also need to seamlesly connect when putting platforms next to eachother. These two requirements mean that the white stripes can't be part of the base sprite. By masking a large repeating stripes sprite I was able to achieve both of these requirements easily.
    - The second masked element within each platform is a bunch of shadows that are attached to the sides and bottom of the platform. Here's an example of what I'm talking about:
    upload_2020-12-16_11-12-42.png

    The reason these shades can't be part of the base sprite is that I wanted to be able to individually turn off shades in specific sides.
    Take this platform as an example:
    upload_2020-12-16_11-16-31.png

    It's actually made out of 2 platforms merged together
    upload_2020-12-16_11-16-53.png

    I was able to merge them so easily because the stripes are just one big repeating renderer that is masked within the platforms, and because the shades can be individually resized and turned off.

    Doing all of this is unfortunately impossible using Sprite Mask:
    upload_2020-12-16_11-19-13.png

    As seen above, the mask's size doesn't match the base renderer due to the lack of support for 9 slice. It's impossible to make it fit exactly, even if you manually scale the mask to fit its parent size.

    My workaround was to use URP render features to do some stencil magic, but this takes some more advanced knowledge about rendering than using sprite masks. It also caused me a bunch of render order issues which took me a couple of hours to solve using nasty hacks. I'm talking about the kind of hacks that make Santa personally put a rock in your shoe and beat you up with it for ruining Christmas.

    Now I may not survive next Christmas, but maybe one day a future generation of developers will wake on up Christmas day and discover a 9 sliced sprite mask inside their little gift.

    Thank you.
     
    Last edited: Dec 16, 2020
  6. cdr9042

    cdr9042

    Joined:
    Apr 22, 2018
    Posts:
    173
    Bump

    I'm making an object with 3 component: a square picture, a border that goes on top, and a mask to shape the square picture into the rounded square shape of the border

    upload_2021-6-3_15-46-57.png

    The border can be sliced to keep the rounded corner the same size.
    But the mask could not be sliced.
    So if I scale them up, this happens. The rounded corner is not the same anymore

    upload_2021-6-3_15-49-36.png
     
    MousePods and DoctorShinobi like this.
  7. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    436
    We are aware of this and we have it in our backlog. I am reaching out within the team to see if there might be a workaround for this.
     
    MousePods and DoctorShinobi like this.
  8. Long2904

    Long2904

    Joined:
    May 13, 2019
    Posts:
    81
    I have this exact problem, too. How did you solve this? What workaround did you use?
     
  9. cdr9042

    cdr9042

    Joined:
    Apr 22, 2018
    Posts:
    173
    I had no workaround. I resorted to using full size texture and regular scaling
     
  10. vizgl

    vizgl

    Joined:
    Nov 4, 2014
    Posts:
    61
    Need this feature!
     
    DoctorShinobi likes this.
  11. DoctorShinobi

    DoctorShinobi

    Joined:
    Oct 5, 2012
    Posts:
    219
    @ChuanXin @Leo-Yaik Seems like multiple people need this. Any plans for this to ever leave the backlog?
     
  12. ChuanXin

    ChuanXin

    Unity Technologies

    Joined:
    Apr 7, 2015
    Posts:
    1,068
    This is currently under development and not in the backlog.
     
  13. DoctorShinobi

    DoctorShinobi

    Joined:
    Oct 5, 2012
    Posts:
    219
    Good to know! Thank you
     
  14. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Hi, any ETA for this feature, or maybe an alternative way of doing it ?
     
    lawlietsnow likes this.
  15. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Just saw :
    • 2D: Added Sprite/SpriteShape/TilemapRenderer as mask sources for SpriteMask.
    In the 2023.1.0 alpha release notes !
    Any chances to see this backported in an earlier version ? 2021.3LTS or maybe 2022.x ?
     
  16. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Hi, just make some shaders to have it work in case someone is interested:
    There is a shader for the mask and an other for the masked object:
    Here is the code for URP:

    The mask:
    Code (CSharp):
    1. Shader "custom/StencilMask"
    2. {
    3.     Properties
    4.     {
    5.         [IntRange] _StencilID ("Stencil ID", Range(0, 255)) = 0
    6.         _MainTex ("Sprite Texture", 2D) = "white" {}
    7.         _Color ("Tint", Color) = (1,1,1,1)
    8.         _AlphaCutoff ( "Alpha Cutoff", Range( 0.01, 1.0 ) ) = 0.1
    9.  
    10.         // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
    11.         [HideInInspector] PixelSnap ("Pixel snap", Float) = 0
    12.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    13.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    14.         [HideInInspector] _AlphaTex ("External Alpha", 2D) = "white" {}
    15.         [HideInInspector] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    16.     }
    17.  
    18.     SubShader
    19.     {
    20.         Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" }
    21.  
    22.         Blend SrcAlpha OneMinusSrcAlpha
    23.         Cull Off
    24.         ZWrite Off
    25.  
    26.         Pass
    27.         {
    28.             Tags { "LightMode" = "Universal2D" }
    29.  
    30.             Blend Zero One
    31.          
    32.             Stencil
    33.             {
    34.                 Ref [_StencilID]
    35.                 Comp Always
    36.                 Pass Replace
    37.                 //Fail Keep
    38.                 Fail Replace
    39.             }
    40.  
    41.             HLSLPROGRAM
    42.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    43.             #if defined(DEBUG_DISPLAY)
    44.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/InputData2D.hlsl"
    45.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/SurfaceData2D.hlsl"
    46.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
    47.             #endif
    48.  
    49.             #pragma vertex UnlitVertex
    50.             #pragma fragment UnlitFragment
    51.  
    52.             #pragma multi_compile _ DEBUG_DISPLAY
    53.  
    54.             struct Attributes
    55.             {
    56.                 float3 positionOS   : POSITION;
    57.                 float4 color        : COLOR;
    58.                 float2 uv           : TEXCOORD0;
    59.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    60.             };
    61.  
    62.             struct Varyings
    63.             {
    64.                 float4  positionCS  : SV_POSITION;
    65.                 half4   color       : COLOR;
    66.                 float2  uv          : TEXCOORD0;
    67.                 #if defined(DEBUG_DISPLAY)
    68.                 float3  positionWS  : TEXCOORD2;
    69.                 #endif
    70.                 UNITY_VERTEX_OUTPUT_STEREO
    71.             };
    72.  
    73.             TEXTURE2D(_MainTex);
    74.             SAMPLER(sampler_MainTex);
    75.             half4 _MainTex_ST;
    76.             half _AlphaCutoff;
    77.  
    78.             Varyings UnlitVertex(Attributes v)
    79.             {
    80.                 Varyings o = (Varyings)0;
    81.                 UNITY_SETUP_INSTANCE_ID(v);
    82.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    83.  
    84.                 o.positionCS = TransformObjectToHClip(v.positionOS);
    85.                 #if defined(DEBUG_DISPLAY)
    86.                 o.positionWS = TransformObjectToWorld(v.positionOS);
    87.                 #endif
    88.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    89.                 o.color = v.color;
    90.                 return o;
    91.             }
    92.  
    93.             half4 UnlitFragment(Varyings i) : SV_Target
    94.             {
    95.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    96.  
    97.                 #if defined(DEBUG_DISPLAY)
    98.                 SurfaceData2D surfaceData;
    99.                 InputData2D inputData;
    100.                 half4 debugColor = 0;
    101.  
    102.                 InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
    103.                 InitializeInputData(i.uv, inputData);
    104.                 SETUP_DEBUG_DATA_2D(inputData, i.positionWS);
    105.  
    106.                 if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
    107.                 {
    108.                     return debugColor;
    109.                 }
    110.                 #endif
    111.  
    112.                 clip( mainTex.a - _AlphaCutoff );
    113.              
    114.                 if( mainTex.a < 0.1 )
    115.                     return float4(0, 0, 0, 0);
    116.              
    117.                 return mainTex;
    118.             }
    119.             ENDHLSL
    120.         }
    121.  
    122.         Pass
    123.         {
    124.             Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}
    125.  
    126.             Blend Zero One
    127.             /*ZWrite Off*/
    128.          
    129.             Stencil
    130.             {
    131.                 Ref [_StencilID]
    132.                 Comp Always
    133.                 Pass Replace
    134.                 //Fail Keep
    135.                 Fail Keep
    136.             }
    137.          
    138.             HLSLPROGRAM
    139.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    140.             #if defined(DEBUG_DISPLAY)
    141.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/InputData2D.hlsl"
    142.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/SurfaceData2D.hlsl"
    143.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
    144.             #endif
    145.  
    146.             #pragma vertex UnlitVertex
    147.             #pragma fragment UnlitFragment
    148.  
    149.             #pragma multi_compile_fragment _ DEBUG_DISPLAY
    150.  
    151.             struct Attributes
    152.             {
    153.                 float3 positionOS   : POSITION;
    154.                 float4 color        : COLOR;
    155.                 float2 uv           : TEXCOORD0;
    156.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    157.             };
    158.  
    159.             struct Varyings
    160.             {
    161.                 float4  positionCS      : SV_POSITION;
    162.                 float4  color           : COLOR;
    163.                 float2  uv              : TEXCOORD0;
    164.                 #if defined(DEBUG_DISPLAY)
    165.                 float3  positionWS      : TEXCOORD2;
    166.                 #endif
    167.                 UNITY_VERTEX_OUTPUT_STEREO
    168.             };
    169.  
    170.             TEXTURE2D(_MainTex);
    171.             SAMPLER(sampler_MainTex);
    172.             float4 _MainTex_ST;
    173.             half _AlphaCutoff;
    174.  
    175.             Varyings UnlitVertex(Attributes attributes)
    176.             {
    177.                 Varyings o = (Varyings)0;
    178.                 UNITY_SETUP_INSTANCE_ID(attributes);
    179.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    180.  
    181.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    182.                 #if defined(DEBUG_DISPLAY)
    183.                 o.positionWS = TransformObjectToWorld(attributes.positionOS);
    184.                 #endif
    185.                 o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
    186.                 o.color = attributes.color;
    187.                 return o;
    188.             }
    189.  
    190.             float4 UnlitFragment(Varyings i) : SV_Target
    191.             {
    192.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    193.  
    194.                 #if defined(DEBUG_DISPLAY)
    195.                 SurfaceData2D surfaceData;
    196.                 InputData2D inputData;
    197.                 half4 debugColor = 0;
    198.  
    199.                 InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
    200.                 InitializeInputData(i.uv, inputData);
    201.                 SETUP_DEBUG_DATA_2D(inputData, i.positionWS);
    202.  
    203.                 if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
    204.                 {
    205.                     return debugColor;
    206.                 }
    207.                 #endif
    208.  
    209.                 clip( mainTex.a - _AlphaCutoff );
    210.              
    211.                 if( mainTex.a < 0.1 )
    212.                     return float4(0, 0, 0, 0);
    213.              
    214.                 return mainTex;
    215.             }
    216.             ENDHLSL
    217.         }
    218.     }
    219.  
    220.     Fallback "Sprites/Default"
    221. }

    The masked:
    Code (CSharp):
    1. Shader "custom/StencilMasked"
    2. {
    3.     Properties
    4.     {
    5.         [IntRange] _StencilID ("Stencil ID", Range(0, 255)) = 0
    6.         _MainTex ("Sprite Texture", 2D) = "white" {}
    7.         _Color ("Tint", Color) = (1,1,1,1)
    8.  
    9.         // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
    10.         [HideInInspector] PixelSnap ("Pixel snap", Float) = 0
    11.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    12.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    13.         [HideInInspector] _AlphaTex ("External Alpha", 2D) = "white" {}
    14.         [HideInInspector] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    15.     }
    16.  
    17.     SubShader
    18.     {
    19.         Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" }
    20.  
    21.         Blend SrcAlpha OneMinusSrcAlpha
    22.         Cull Off
    23.         ZWrite Off
    24.  
    25.         Pass
    26.         {
    27.             Tags { "LightMode" = "Universal2D" }
    28.  
    29.             Stencil
    30.             {
    31.                 Ref [_StencilID]
    32.                 Comp Equal
    33.                 /*Pass Replace
    34.                 Fail Keep*/
    35.             }
    36.          
    37.             HLSLPROGRAM
    38.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    39.             #if defined(DEBUG_DISPLAY)
    40.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/InputData2D.hlsl"
    41.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/SurfaceData2D.hlsl"
    42.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
    43.             #endif
    44.  
    45.             #pragma vertex UnlitVertex
    46.             #pragma fragment UnlitFragment
    47.  
    48.             #pragma multi_compile _ DEBUG_DISPLAY
    49.  
    50.             struct Attributes
    51.             {
    52.                 float3 positionOS   : POSITION;
    53.                 float4 color        : COLOR;
    54.                 float2 uv           : TEXCOORD0;
    55.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    56.             };
    57.  
    58.             struct Varyings
    59.             {
    60.                 float4  positionCS  : SV_POSITION;
    61.                 half4   color       : COLOR;
    62.                 float2  uv          : TEXCOORD0;
    63.                 #if defined(DEBUG_DISPLAY)
    64.                 float3  positionWS  : TEXCOORD2;
    65.                 #endif
    66.                 UNITY_VERTEX_OUTPUT_STEREO
    67.             };
    68.  
    69.             TEXTURE2D(_MainTex);
    70.             SAMPLER(sampler_MainTex);
    71.             half4 _MainTex_ST;
    72.  
    73.             Varyings UnlitVertex(Attributes v)
    74.             {
    75.                 Varyings o = (Varyings)0;
    76.                 UNITY_SETUP_INSTANCE_ID(v);
    77.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    78.  
    79.                 o.positionCS = TransformObjectToHClip(v.positionOS);
    80.                 #if defined(DEBUG_DISPLAY)
    81.                 o.positionWS = TransformObjectToWorld(v.positionOS);
    82.                 #endif
    83.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    84.                 o.color = v.color;
    85.                 return o;
    86.             }
    87.  
    88.             half4 UnlitFragment(Varyings i) : SV_Target
    89.             {
    90.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    91.  
    92.                 #if defined(DEBUG_DISPLAY)
    93.                 SurfaceData2D surfaceData;
    94.                 InputData2D inputData;
    95.                 half4 debugColor = 0;
    96.  
    97.                 InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
    98.                 InitializeInputData(i.uv, inputData);
    99.                 SETUP_DEBUG_DATA_2D(inputData, i.positionWS);
    100.  
    101.                 if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
    102.                 {
    103.                     return debugColor;
    104.                 }
    105.                 #endif
    106.  
    107.                 return mainTex;
    108.             }
    109.             ENDHLSL
    110.         }
    111.  
    112.         Pass
    113.         {
    114.             Tags { "LightMode" = "UniversalForward" "Queue"="Transparent" "RenderType"="Transparent"}
    115.  
    116.             Stencil
    117.             {
    118.                 Ref [_StencilID]
    119.                 Comp Equal
    120.             }
    121.          
    122.             HLSLPROGRAM
    123.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    124.             #if defined(DEBUG_DISPLAY)
    125.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/InputData2D.hlsl"
    126.             #include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/SurfaceData2D.hlsl"
    127.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/Debugging2D.hlsl"
    128.             #endif
    129.  
    130.             #pragma vertex UnlitVertex
    131.             #pragma fragment UnlitFragment
    132.  
    133.             #pragma multi_compile_fragment _ DEBUG_DISPLAY
    134.  
    135.             struct Attributes
    136.             {
    137.                 float3 positionOS   : POSITION;
    138.                 float4 color        : COLOR;
    139.                 float2 uv           : TEXCOORD0;
    140.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    141.             };
    142.  
    143.             struct Varyings
    144.             {
    145.                 float4  positionCS      : SV_POSITION;
    146.                 float4  color           : COLOR;
    147.                 float2  uv              : TEXCOORD0;
    148.                 #if defined(DEBUG_DISPLAY)
    149.                 float3  positionWS      : TEXCOORD2;
    150.                 #endif
    151.                 UNITY_VERTEX_OUTPUT_STEREO
    152.             };
    153.  
    154.             TEXTURE2D(_MainTex);
    155.             SAMPLER(sampler_MainTex);
    156.             float4 _MainTex_ST;
    157.  
    158.             Varyings UnlitVertex(Attributes attributes)
    159.             {
    160.                 Varyings o = (Varyings)0;
    161.                 UNITY_SETUP_INSTANCE_ID(attributes);
    162.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    163.  
    164.                 o.positionCS = TransformObjectToHClip(attributes.positionOS);
    165.                 #if defined(DEBUG_DISPLAY)
    166.                 o.positionWS = TransformObjectToWorld(attributes.positionOS);
    167.                 #endif
    168.                 o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
    169.                 o.color = attributes.color;
    170.                 return o;
    171.             }
    172.  
    173.             float4 UnlitFragment(Varyings i) : SV_Target
    174.             {
    175.                 float4 mainTex = i.color * SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
    176.  
    177.                 #if defined(DEBUG_DISPLAY)
    178.                 SurfaceData2D surfaceData;
    179.                 InputData2D inputData;
    180.                 half4 debugColor = 0;
    181.  
    182.                 InitializeSurfaceData(mainTex.rgb, mainTex.a, surfaceData);
    183.                 InitializeInputData(i.uv, inputData);
    184.                 SETUP_DEBUG_DATA_2D(inputData, i.positionWS);
    185.  
    186.                 if(CanDebugOverrideOutputColor(surfaceData, inputData, debugColor))
    187.                 {
    188.                     return debugColor;
    189.                 }
    190.                 #endif
    191.  
    192.                 return mainTex;
    193.             }
    194.             ENDHLSL
    195.         }
    196.     }
    197.  
    198.     Fallback "Sprites/Default"
    199. }

    This works with stencil so no alpha masking support.
    Make sure to set the stencil ID for the mask and the masked object at the same value ;)
     
    cdr9042 and DoctorShinobi like this.
  17. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Here is the non URP version:

    Code (CSharp):
    1. Shader "custom/builtin/StencilMask"
    2. {
    3.     Properties
    4.     {
    5.         [IntRange] _StencilID ("Stencil ID", Range(0, 255)) = 0
    6.         _AlphaCutoff ( "Alpha Cutoff", Range( 0.01, 1.0 ) ) = 0.1
    7.        
    8.          [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    9.         _Color ("Tint", Color) = (1,1,1,1)
    10.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    11.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    12.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    13.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    14.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    15.     }
    16.  
    17.     SubShader
    18.     {
    19.         Tags
    20.         {
    21.             "Queue"="Transparent"
    22.             "IgnoreProjector"="True"
    23.             "RenderType"="Transparent"
    24.             "PreviewType"="Plane"
    25.             "CanUseSpriteAtlas"="True"
    26.         }
    27.  
    28.        
    29.         Cull Off
    30.         Lighting Off
    31.         ZWrite Off
    32.         Blend One OneMinusSrcAlpha
    33.  
    34.         Pass
    35.         {
    36.             Blend Zero One
    37.            
    38.             Stencil
    39.             {
    40.                 Ref [_StencilID]
    41.                 Comp Always
    42.                 Pass Replace
    43.                 //Fail Keep
    44.                 Fail Replace
    45.             }
    46.            
    47.             CGPROGRAM
    48.             #pragma vertex SpriteVert
    49.             #pragma fragment SpriteFrag
    50.             #pragma target 2.0
    51.             #pragma multi_compile_instancing
    52.             #pragma multi_compile_local _ PIXELSNAP_ON
    53.             #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    54.             #include "MaskUnitySprite.cginc"
    55.             ENDCG
    56.         }
    57.     }
    58. }


    Code (CSharp):
    1. Shader "custom/builtin/StencilMasked"
    2. {
    3.     Properties
    4.     {
    5.         [IntRange] _StencilID ("Stencil ID", Range(0, 255)) = 0
    6.          [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    7.         _Color ("Tint", Color) = (1,1,1,1)
    8.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    9.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    10.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    11.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    12.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    13.     }
    14.  
    15.     SubShader
    16.     {
    17.         Tags
    18.         {
    19.             "Queue"="Transparent"
    20.             "IgnoreProjector"="True"
    21.             "RenderType"="Transparent"
    22.             "PreviewType"="Plane"
    23.             "CanUseSpriteAtlas"="True"
    24.         }
    25.  
    26.         Cull Off
    27.         Lighting Off
    28.         ZWrite Off
    29.         Blend One OneMinusSrcAlpha
    30.  
    31.         Pass
    32.         {
    33.             Stencil
    34.             {
    35.                 Ref [_StencilID]
    36.                 Comp Equal
    37.             }
    38.            
    39.             CGPROGRAM
    40.             #pragma vertex SpriteVert
    41.             #pragma fragment SpriteFrag
    42.             #pragma target 2.0
    43.             #pragma multi_compile_instancing
    44.             #pragma multi_compile_local _ PIXELSNAP_ON
    45.             #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    46.             #include "UnitySprites.cginc"
    47.             ENDCG
    48.         }
    49.     }
    50. }
     
    cdr9042 and DoctorShinobi like this.
  18. OneManEscapePlan

    OneManEscapePlan

    Joined:
    Oct 14, 2015
    Posts:
    222
    The shader doesn't do any good without the "UnitySprites.cginc" file.

    EDIT: Whoops, that was a typo - meant to write "MaskUnitySprite.cginc"
     
    Last edited: Nov 3, 2023
  19. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Hi, "UnitySprites.cginc" should be in the "Editor\Data\CGIncludes\UnitySprites.cginc" and available in your project to use. But effectively the "MaskUnitySprite.cginc" is missing.

    Here is "MaskUnitySprite.cginc" content:

    Code (CSharp):
    1. #ifndef UNITY_SPRITES_INCLUDED
    2. #define UNITY_SPRITES_INCLUDED
    3.  
    4. #include "UnityCG.cginc"
    5.  
    6. #ifdef UNITY_INSTANCING_ENABLED
    7.  
    8.     UNITY_INSTANCING_BUFFER_START(PerDrawSprite)
    9.         // SpriteRenderer.Color while Non-Batched/Instanced.
    10.         UNITY_DEFINE_INSTANCED_PROP(fixed4, unity_SpriteRendererColorArray)
    11.         // this could be smaller but that's how bit each entry is regardless of type
    12.         UNITY_DEFINE_INSTANCED_PROP(fixed2, unity_SpriteFlipArray)
    13.     UNITY_INSTANCING_BUFFER_END(PerDrawSprite)
    14.  
    15.     #define _RendererColor  UNITY_ACCESS_INSTANCED_PROP(PerDrawSprite, unity_SpriteRendererColorArray)
    16.     #define _Flip           UNITY_ACCESS_INSTANCED_PROP(PerDrawSprite, unity_SpriteFlipArray)
    17.  
    18. #endif // instancing
    19.  
    20. CBUFFER_START(UnityPerDrawSprite)
    21. #ifndef UNITY_INSTANCING_ENABLED
    22.     fixed4 _RendererColor;
    23.     fixed2 _Flip;
    24. #endif
    25.     float _EnableExternalAlpha;
    26. CBUFFER_END
    27.  
    28. // Material Color.
    29. fixed4 _Color;
    30.  
    31. struct appdata_t
    32. {
    33.     float4 vertex   : POSITION;
    34.     float4 color    : COLOR;
    35.     float2 texcoord : TEXCOORD0;
    36.     UNITY_VERTEX_INPUT_INSTANCE_ID
    37. };
    38.  
    39. struct v2f
    40. {
    41.     float4 vertex   : SV_POSITION;
    42.     fixed4 color    : COLOR;
    43.     float2 texcoord : TEXCOORD0;
    44.     UNITY_VERTEX_OUTPUT_STEREO
    45. };
    46.  
    47. inline float4 UnityFlipSprite(in float3 pos, in fixed2 flip)
    48. {
    49.     return float4(pos.xy * flip, pos.z, 1.0);
    50. }
    51.  
    52. v2f SpriteVert(appdata_t IN)
    53. {
    54.     v2f OUT;
    55.  
    56.     UNITY_SETUP_INSTANCE_ID (IN);
    57.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
    58.  
    59.     OUT.vertex = UnityFlipSprite(IN.vertex, _Flip);
    60.     OUT.vertex = UnityObjectToClipPos(OUT.vertex);
    61.     OUT.texcoord = IN.texcoord;
    62.     OUT.color = IN.color * _Color * _RendererColor;
    63.  
    64.     #ifdef PIXELSNAP_ON
    65.     OUT.vertex = UnityPixelSnap (OUT.vertex);
    66.     #endif
    67.  
    68.     return OUT;
    69. }
    70.  
    71. sampler2D _MainTex;
    72. sampler2D _AlphaTex;
    73. float _Grayscale;
    74. float _AlphaCutoff;
    75.  
    76. fixed4 SampleSpriteTexture (float2 uv)
    77. {
    78.     fixed4 color = tex2D (_MainTex, uv);
    79.  
    80. #if ETC1_EXTERNAL_ALPHA
    81.     fixed4 alpha = tex2D (_AlphaTex, uv);
    82.     color.a = lerp (color.a, alpha.r, _EnableExternalAlpha);
    83. #endif
    84.  
    85.     return color;
    86. }
    87.  
    88. fixed4 SpriteFrag(v2f IN) : SV_Target
    89. {
    90.     fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
    91.  
    92.     //c.rgb *= c.a;
    93.  
    94.     clip( c.a - _AlphaCutoff );
    95.                
    96.     if( c.a < 0.1 )
    97.         return float4(0, 0, 0, 0);
    98.    
    99.     return c;
    100. }
    101.  
    102. #endif // UNITY_SPRITES_INCLUDED
    103.  

    Note that I use this shaders on Unity 2021.3 and I never tested them on an older version.
     
  20. OneManEscapePlan

    OneManEscapePlan

    Joined:
    Oct 14, 2015
    Posts:
    222
    Whoops, that was a typo. Thanks!
     
  21. OneManEscapePlan

    OneManEscapePlan

    Joined:
    Oct 14, 2015
    Posts:
    222
    I'm also using 2021.3. Some notes about how these shaders work
    1. Any Sprite Renderer which uses the default sprite material and has its "Mask Interaction" setting set to "Visible Inside Mask" or "Visible Outside Mask" will be masked by the Mask Shader (as specified by the Mask Interaction setting) if it is sorted higher than the sprite with the Mask Shader. If the sorting order is equal to the mask, it arbitrarily may or may not be masked.
    2. For Sprite Renderers that use a material with the "Masked Shader", the "Stencil ID" in the material is ignored if the "Mask Interaction" setting is set to "Visible Inside Mask" or "Visible Outside Mask" (in which case the Sprite Renderer behaves exactly the same as it would with the default sprite material)
     
    Last edited: Nov 3, 2023
  22. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Exact, mixing this shaders with Mask Interaction feature is not supported.
    Note that I've done this shaders for my specific use case and I don't mix them with the native Mask Interaction feature in my projects.
     
  23. Vaitaliy

    Vaitaliy

    Joined:
    Jan 10, 2019
    Posts:
    11
  24. Vaitaliy

    Vaitaliy

    Joined:
    Jan 10, 2019
    Posts:
    11

    I can see Alpha Cutoff property, but you said that there is no alpha masking support. Can I get this mask to include alpha of the sprite? Unfortunately, having just a square mask is not going to solve my problem.
    upload_2023-12-1_15-27-43.png
     
  25. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Yes the alpha of the image is supported but it's 0 or 1, there is no alpha fade.