Search Unity

Question Why do masks stop working if an image has a material

Discussion in 'Shaders' started by Feliperpv, Sep 18, 2022.

  1. Feliperpv

    Feliperpv

    Joined:
    Mar 12, 2021
    Posts:
    3
    Hi!
    I need to do something that I thought would be simple: a half-transparent button that blurs everything behind it. The big problem? This button has rounded corners.

    I have this image with rounded corners and a mask applied on top. I added a child element to it and painted it red so we can see that the mask is working as intended:
    upload_2022-9-18_15-21-57.png

    But the moment I add a material to the image (the Blur shader I'm using), Unity goes crazy and completely ignores the mask:
    upload_2022-9-18_15-23-23.png

    Is there any way to accomplish this? I really wanted to add this shader to the image, but it must blur only the areas where the mask was supposed to be showing, not blurring everything in the rectangle.
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    The custom shader likely doesn't have the stencil code used for masking. It would have to be modified to include and utilize it.
     
    Feliperpv likes this.
  3. Feliperpv

    Feliperpv

    Joined:
    Mar 12, 2021
    Posts:
    3
    Oh, I didn't know about stencil code, I added it and it's now working as I wanted. Thank you!

    I'll leave my blur shader here with the stencil code in case anyone needs it:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "Custom/BLUR" {
    4.     Properties {
    5.         _Color ("Main Color", Color) = (1,1,1,1)
    6.         _BumpAmt  ("Distortion", Range (0,128)) = 10
    7.         _MainTex ("Tint Color (RGB)", 2D) = "white" {}
    8.         _BumpMap ("Normalmap", 2D) = "bump" {}
    9.         _Size ("Size", Range(0, 20)) = 1
    10.  
    11.          // required for UI.Mask
    12.          _StencilComp ("Stencil Comparison", Float) = 8
    13.          _Stencil ("Stencil ID", Float) = 0
    14.          _StencilOp ("Stencil Operation", Float) = 0
    15.          _StencilWriteMask ("Stencil Write Mask", Float) = 255
    16.          _StencilReadMask ("Stencil Read Mask", Float) = 255
    17.          _ColorMask ("Color Mask", Float) = 15
    18.     }
    19.     Category {
    20.  
    21.         Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" }
    22.         SubShader {
    23.    
    24.             GrabPass {                  
    25.                 Tags { "LightMode" = "Always" }
    26.             }
    27.  
    28.              // required for UI.Mask
    29.              Stencil
    30.              {
    31.                  Ref [_Stencil]
    32.                  Comp [_StencilComp]
    33.                  Pass [_StencilOp]
    34.                  ReadMask [_StencilReadMask]
    35.                  WriteMask [_StencilWriteMask]
    36.              }
    37.               ColorMask [_ColorMask]
    38.  
    39.  
    40.             Pass {
    41.                 Tags { "LightMode" = "Always" }
    42.            
    43.                 CGPROGRAM
    44.                 #pragma vertex vert
    45.                 #pragma fragment frag
    46.                 #pragma fragmentoption ARB_precision_hint_fastest
    47.                 #include "UnityCG.cginc"
    48.            
    49.                 struct appdata_t {
    50.                     float4 vertex : POSITION;
    51.                     float2 texcoord: TEXCOORD0;
    52.                 };
    53.            
    54.                 struct v2f {
    55.                     float4 vertex : POSITION;
    56.                     float4 uvgrab : TEXCOORD0;
    57.                 };
    58.            
    59.                 v2f vert (appdata_t v) {
    60.                     v2f o;
    61.                     o.vertex = UnityObjectToClipPos(v.vertex);
    62.                     #if UNITY_UV_STARTS_AT_TOP
    63.                     float scale = -1.0;
    64.                     #else
    65.                     float scale = 1.0;
    66.                     #endif
    67.                     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    68.                     o.uvgrab.zw = o.vertex.zw;
    69.                     return o;
    70.                 }
    71.            
    72.                 sampler2D _GrabTexture;
    73.                 float4 _GrabTexture_TexelSize;
    74.                 float _Size;
    75.            
    76.                 half4 frag( v2f i ) : COLOR {
    77.                
    78.                     half4 sum = half4(0,0,0,0);
    79.                     #define GRABPIXEL(weight,kernelx) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx*_Size, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight
    80.                     sum += GRABPIXEL(0.05, -4.0);
    81.                     sum += GRABPIXEL(0.09, -3.0);
    82.                     sum += GRABPIXEL(0.12, -2.0);
    83.                     sum += GRABPIXEL(0.15, -1.0);
    84.                     sum += GRABPIXEL(0.18,  0.0);
    85.                     sum += GRABPIXEL(0.15, +1.0);
    86.                     sum += GRABPIXEL(0.12, +2.0);
    87.                     sum += GRABPIXEL(0.09, +3.0);
    88.                     sum += GRABPIXEL(0.05, +4.0);
    89.                
    90.                     return sum;
    91.                 }
    92.                 ENDCG
    93.             }
    94.  
    95.             GrabPass {                      
    96.                 Tags { "LightMode" = "Always" }
    97.             }
    98.             Pass {
    99.                 Tags { "LightMode" = "Always" }
    100.            
    101.                 CGPROGRAM
    102.                 #pragma vertex vert
    103.                 #pragma fragment frag
    104.                 #pragma fragmentoption ARB_precision_hint_fastest
    105.                 #include "UnityCG.cginc"
    106.            
    107.                 struct appdata_t {
    108.                     float4 vertex : POSITION;
    109.                     float2 texcoord: TEXCOORD0;
    110.                 };
    111.            
    112.                 struct v2f {
    113.                     float4 vertex : POSITION;
    114.                     float4 uvgrab : TEXCOORD0;
    115.                 };
    116.            
    117.                 v2f vert (appdata_t v) {
    118.                     v2f o;
    119.                     o.vertex = UnityObjectToClipPos(v.vertex);
    120.                     #if UNITY_UV_STARTS_AT_TOP
    121.                     float scale = -1.0;
    122.                     #else
    123.                     float scale = 1.0;
    124.                     #endif
    125.                     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    126.                     o.uvgrab.zw = o.vertex.zw;
    127.                     return o;
    128.                 }
    129.            
    130.                 sampler2D _GrabTexture;
    131.                 float4 _GrabTexture_TexelSize;
    132.                 float _Size;
    133.            
    134.                 half4 frag( v2f i ) : COLOR {
    135.                
    136.                     half4 sum = half4(0,0,0,0);
    137.                     #define GRABPIXEL(weight,kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely*_Size, i.uvgrab.z, i.uvgrab.w))) * weight
    138.                
    139.                     sum += GRABPIXEL(0.05, -4.0);
    140.                     sum += GRABPIXEL(0.09, -3.0);
    141.                     sum += GRABPIXEL(0.12, -2.0);
    142.                     sum += GRABPIXEL(0.15, -1.0);
    143.                     sum += GRABPIXEL(0.18,  0.0);
    144.                     sum += GRABPIXEL(0.15, +1.0);
    145.                     sum += GRABPIXEL(0.12, +2.0);
    146.                     sum += GRABPIXEL(0.09, +3.0);
    147.                     sum += GRABPIXEL(0.05, +4.0);
    148.                
    149.                     return sum;
    150.                 }
    151.                 ENDCG
    152.             }
    153.        
    154.             GrabPass {                      
    155.                 Tags { "LightMode" = "Always" }
    156.             }
    157.             Pass {
    158.                 Tags { "LightMode" = "Always" }
    159.            
    160.                 CGPROGRAM
    161.                 #pragma vertex vert
    162.                 #pragma fragment frag
    163.                 #pragma fragmentoption ARB_precision_hint_fastest
    164.                 #include "UnityCG.cginc"
    165.            
    166.                 struct appdata_t {
    167.                     float4 vertex : POSITION;
    168.                     float2 texcoord: TEXCOORD0;
    169.                 };
    170.            
    171.                 struct v2f {
    172.                     float4 vertex : POSITION;
    173.                     float4 uvgrab : TEXCOORD0;
    174.                     float2 uvbump : TEXCOORD1;
    175.                     float2 uvmain : TEXCOORD2;
    176.                 };
    177.            
    178.                 float _BumpAmt;
    179.                 float4 _BumpMap_ST;
    180.                 float4 _MainTex_ST;
    181.            
    182.                 v2f vert (appdata_t v) {
    183.                     v2f o;
    184.                     o.vertex = UnityObjectToClipPos(v.vertex);
    185.                     #if UNITY_UV_STARTS_AT_TOP
    186.                     float scale = -1.0;
    187.                     #else
    188.                     float scale = 1.0;
    189.                     #endif
    190.                     o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
    191.                     o.uvgrab.zw = o.vertex.zw;
    192.                     o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
    193.                     o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
    194.                     return o;
    195.                 }
    196.            
    197.                 fixed4 _Color;
    198.                 sampler2D _GrabTexture;
    199.                 float4 _GrabTexture_TexelSize;
    200.                 sampler2D _BumpMap;
    201.                 sampler2D _MainTex;
    202.            
    203.                 half4 frag( v2f i ) : COLOR {
    204.            
    205.                     half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg;
    206.                     float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
    207.                     i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;
    208.                
    209.                     half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
    210.                     half4 tint = tex2D( _MainTex, i.uvmain ) * _Color;
    211.                
    212.                     return col * tint;
    213.                 }
    214.                 ENDCG
    215.             }
    216.         }
    217.     }
    218. }
    The way I'm using it is:
    - Shape (blank image on the shape of the button with really low opacity + mask component)
    - Blur (only the blur shader, no color)
    - Color (Image of the actual button)

    Added code came from this link: https://answers.unity.com/questions/980924/ui-mask-with-shader.html
     
    Last edited: Sep 19, 2022
    uterian and Invertex like this.