Search Unity

UI shader: Stencil and additive

Discussion in 'Shaders' started by laurentlavigne, Jan 21, 2017.

  1. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,362
    Guys, how do we turn the default UI image shader into additive?
    I presume it's UI-Default.shader and trying to do this by changing Blend to One One results in a console error - why? I tries soft additive "Blend OneMinusDstColor One" and stencil works but now the image set in the Image component doesn't appear, I get a rectangle instead.
    The doc states that "All following properties are valid for both SrcFactor & DstFactor in the Blend command" but my guess is this is only true with Unity stuff like shaderlab and surface shader, not the CG stuff that's in the built-in shaders.
    Can someone explain how the stuff works behind the scene and ... how to make an additive shader for UI that works and that gets masked?
    Cheers
     
    max29497696 likes this.
  2. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    I am currently trying to get additive to be masked in the UI. So I would like to know as well. I am a total newb when it comes to shaders. I grabbed some shader code from somewhere and have this:
    Code (CSharp):
    1. Shader "Sprites/Additive"
    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.         _StencilComp("Stencil Comparison", Float) = 8
    10.         _Stencil("Stencil ID", Float) = 0
    11.         _StencilOp("Stencil Operation", Float) = 0
    12.         _StencilWriteMask("Stencil Write Mask", Float) = 255
    13.         _StencilReadMask("Stencil Read Mask", Float) = 255
    14.         _ColorMask("Color Mask", Float) = 15
    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.         Stencil
    29.     {
    30.         Ref[_Stencil]
    31.         Comp[_StencilComp]
    32.         Pass[_StencilOp]
    33.         ReadMask[_StencilReadMask]
    34.         WriteMask[_StencilWriteMask]
    35.     }
    36.         ColorMask[_ColorMask]
    37.  
    38.         Cull Off
    39.         Lighting Off
    40.         ZWrite Off
    41.         Fog{ Mode Off }
    42.         Blend SrcAlpha One
    43.         //AlphaTest Greater .01
    44.  
    45.         Pass
    46.     {
    47.         CGPROGRAM
    48. #pragma vertex vert
    49. #pragma fragment frag
    50. #pragma multi_compile DUMMY PIXELSNAP_ON
    51. #include "UnityCG.cginc"
    52.  
    53.     struct appdata_t
    54.     {
    55.         float4 vertex   : POSITION;
    56.         float4 color    : COLOR;
    57.         float2 texcoord : TEXCOORD0;
    58.     };
    59.  
    60.     struct v2f
    61.     {
    62.         float4 vertex   : SV_POSITION;
    63.         fixed4 color : COLOR;
    64.         half2 texcoord  : TEXCOORD0;
    65.     };
    66.  
    67.     fixed4 _Color;
    68.  
    69.     v2f vert(appdata_t IN)
    70.     {
    71.         v2f OUT;
    72.         OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
    73.         OUT.texcoord = IN.texcoord;
    74.         OUT.color = IN.color * _Color;
    75. #ifdef PIXELSNAP_ON
    76.         OUT.vertex = UnityPixelSnap(OUT.vertex);
    77. #endif
    78.  
    79.         return OUT;
    80.     }
    81.  
    82.     sampler2D _MainTex;
    83.  
    84.     fixed4 frag(v2f IN) : COLOR
    85.     {
    86.         return 2.0f * tex2D(_MainTex, IN.texcoord) * IN.color;
    87.     }
    88.         ENDCG
    89.     }
    90.     }
    91. }
    It works but doesn't get masked.
     
  3. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    Do you have a solution for this? I was using "Particle-Additive" Shader, but it doestn't get masked.

    Code (csharp):
    1.  
    2. Material particleadditive doesn't have _Stencil property
    3. UnityEngine.Canvas:SendWillRenderCanvases()
    4.  
     
  4. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    579
    Anyone got additive masked shader?
     
  5. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Here is a performant ui version (without masking) with an additive blend mode:
    Code (CSharp):
    1. // ----------------------------------------------------------------------------
    2. // <copyright file="FastAdditive.shader" company="Supyrb">
    3. //   Copyright (c) 2017 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <author>
    6. //   Johannes Deml
    7. //   send@johannesdeml.com
    8. // </author>
    9. // ----------------------------------------------------------------------------
    10.  
    11. Shader "UI/Fast-Additive"
    12. {
    13.     Properties
    14.     {
    15.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    16.         _Color ("Tint", Color) = (1,1,1,1)
    17.     }
    18.  
    19.     CGINCLUDE
    20.     #include "UnityCG.cginc"
    21.     #include "UnityUI.cginc"
    22.  
    23.     fixed4 _Color;
    24.     fixed4 _TextureSampleAdd;
    25.  
    26.     struct appdata_t
    27.     {
    28.         float4 vertex   : POSITION;
    29.         float4 color    : COLOR;
    30.         float2 texcoord : TEXCOORD0;
    31.     };
    32.  
    33.     struct v2f
    34.     {
    35.         float4 vertex   : SV_POSITION;
    36.         fixed4 color    : COLOR;
    37.         half2 texcoord  : TEXCOORD0;
    38.     };
    39.  
    40.     v2f vert(appdata_t IN)
    41.     {
    42.         v2f OUT;
    43.         OUT.vertex = UnityObjectToClipPos(IN.vertex);
    44.  
    45.         OUT.texcoord = IN.texcoord;
    46.      
    47.         #ifdef UNITY_HALF_TEXEL_OFFSET
    48.         OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
    49.         #endif
    50.      
    51.         OUT.color = IN.color * _Color;
    52.         return OUT;
    53.     }
    54.  
    55.     sampler2D _MainTex;
    56.     fixed4 frag(v2f IN) : SV_Target
    57.     {
    58.         return (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
    59.     }
    60.     ENDCG
    61.  
    62.     SubShader
    63.     {
    64.         Tags
    65.         {
    66.             "Queue"="Transparent"
    67.             "IgnoreProjector"="True"
    68.             "RenderType"="Transparent"
    69.             "PreviewType"="Plane"
    70.             "CanUseSpriteAtlas"="True"
    71.         }
    72.  
    73.         Cull Off
    74.         Lighting Off
    75.         ZWrite Off
    76.         ZTest [unity_GUIZTestMode]
    77.         Blend SrcAlpha One
    78.  
    79.         Pass
    80.         {
    81.         CGPROGRAM
    82.             #pragma vertex vert
    83.             #pragma fragment frag
    84.         ENDCG
    85.         }
    86.     }
    87. }
     
    Last edited: Sep 4, 2017
    prettymcuh likes this.
  6. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    Does this work with masking?

    Edit: Tested and no it doesn't.
     
    Last edited: Sep 1, 2017
  7. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Ah, I missed the requirement for masking. There you go:

    Code (CSharp):
    1. // ----------------------------------------------------------------------------
    2. // <copyright file="AdditiveUI.shader" company="Unity Technologies / Supyrb">
    3. //   Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    4. //   Copyright (c) 2017 Supyrb. All rights reserved.
    5. // </copyright>
    6. // <author>
    7. //   Johannes Deml
    8. //   send@johannesdeml.com
    9. // </author>
    10. // ----------------------------------------------------------------------------
    11.  
    12. Shader "UI/Additive"
    13. {
    14.     Properties
    15.     {
    16.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    17.         _Color ("Tint", Color) = (1,1,1,1)
    18.      
    19.         _StencilComp ("Stencil Comparison", Float) = 8
    20.         _Stencil ("Stencil ID", Float) = 0
    21.         _StencilOp ("Stencil Operation", Float) = 0
    22.         _StencilWriteMask ("Stencil Write Mask", Float) = 255
    23.         _StencilReadMask ("Stencil Read Mask", Float) = 255
    24.  
    25.         _ColorMask ("Color Mask", Float) = 15
    26.  
    27.         [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    28.     }
    29.  
    30.     SubShader
    31.     {
    32.         Tags
    33.         {
    34.             "Queue"="Transparent"
    35.             "IgnoreProjector"="True"
    36.             "RenderType"="Transparent"
    37.             "PreviewType"="Plane"
    38.             "CanUseSpriteAtlas"="True"
    39.         }
    40.      
    41.         Stencil
    42.         {
    43.             Ref [_Stencil]
    44.             Comp [_StencilComp]
    45.             Pass [_StencilOp]
    46.             ReadMask [_StencilReadMask]
    47.             WriteMask [_StencilWriteMask]
    48.         }
    49.  
    50.         Cull Off
    51.         Lighting Off
    52.         ZWrite Off
    53.         ZTest [unity_GUIZTestMode]
    54.         Blend SrcAlpha One
    55.         ColorMask [_ColorMask]
    56.  
    57.         Pass
    58.         {
    59.             Name "Default"
    60.         CGPROGRAM
    61.             #pragma vertex vert
    62.             #pragma fragment frag
    63.             #pragma target 2.0
    64.  
    65.             #include "UnityCG.cginc"
    66.             #include "UnityUI.cginc"
    67.  
    68.             #pragma multi_compile __ UNITY_UI_ALPHACLIP
    69.          
    70.             struct appdata_t
    71.             {
    72.                 float4 vertex   : POSITION;
    73.                 float4 color    : COLOR;
    74.                 float2 texcoord : TEXCOORD0;
    75.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    76.             };
    77.  
    78.             struct v2f
    79.             {
    80.                 float4 vertex   : SV_POSITION;
    81.                 fixed4 color    : COLOR;
    82.                 float2 texcoord  : TEXCOORD0;
    83.                 float4 worldPosition : TEXCOORD1;
    84.                 UNITY_VERTEX_OUTPUT_STEREO
    85.             };
    86.          
    87.             fixed4 _Color;
    88.             fixed4 _TextureSampleAdd;
    89.             float4 _ClipRect;
    90.  
    91.             v2f vert(appdata_t IN)
    92.             {
    93.                 v2f OUT;
    94.                 UNITY_SETUP_INSTANCE_ID(IN);
    95.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
    96.                 OUT.worldPosition = IN.vertex;
    97.                 OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
    98.  
    99.                 OUT.texcoord = IN.texcoord;
    100.              
    101.                 OUT.color = IN.color * _Color;
    102.                 return OUT;
    103.             }
    104.  
    105.             sampler2D _MainTex;
    106.  
    107.             fixed4 frag(v2f IN) : SV_Target
    108.             {
    109.                 half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
    110.              
    111.                 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
    112.              
    113.                 #ifdef UNITY_UI_ALPHACLIP
    114.                 clip (color.a - 0.001);
    115.                 #endif
    116.  
    117.                 return color;
    118.             }
    119.         ENDCG
    120.         }
    121.     }
    122. }
    123.  
    It is the default ui shader just set to additive blend mode. If you need no masking the first one is more performant :)
     
    Last edited: Sep 5, 2017
  8. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    Thank you so very much. Had a few UI elements that couldn't get masked due to needed to be additive. Now it looks much better. I have no idea how shaders work and was just slapping things together to see what works.
     
  9. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    You're welcome :)
     
  10. HonoraryBob

    HonoraryBob

    Joined:
    May 26, 2011
    Posts:
    1,214

    Thank you for the code, but I couldn't get it to compile - it said it couldn't find UnityUI.cginc, and a Google search didn't find any place to download the file or copy the source. Where can we find UnityUI.cginc? Or is it only for newer versions (I'm using 5.0.1) ?
     
  11. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hmmm, very strange. I would have thought that Unity 5 has included it in every version, but I checked and apprently you're right, in 5.0.1 there is no UnityUI.cginc. You can download all unity shaders that are included in the versions here:
    https://unity3d.com/unity/qa/patch-releases
    (Just expand a release and search for the "Built in Shaders" Link).
    I would recommend downloading the last version of the 5 cycle:
    https://beta.unity3d.com/download/10861494ddb7/builtin_shaders-5.6.5p4.zip

    I can't guarantee that it will work if you include the file, never tried that. You would need to place the UnityUI.cginc in the same folder as the shader or in the root Assets folder in order to be detected by the shader.
     
    HonoraryBob likes this.
  12. HonoraryBob

    HonoraryBob

    Joined:
    May 26, 2011
    Posts:
    1,214

    Thank you. I'll try that, although I'm wondering if there's a simpler way to do what I'm trying to do. I currently have a rounded square UI sprite that I'm using to make the usual window background, and I'd like to have an image within that shape (hence I was thinking of making a custom shader that includes a texture). Is there a built-in way to do that? I suppose I could just have another image behind the window background, slightly smaller so that it doesn't stick out beyond the rounded corners.
     
  13. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Oh I see, I guess then the shader is totally irrelevant to you. Just take a look at masks: https://docs.unity3d.com/Manual/script-Mask.html
     
    HonoraryBob likes this.
  14. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Upon request I added an option to set the shader blending through the material:
    upload_2018-11-13_13-47-52.png

    With the blending options you can define how the shader behaves. Here are a few Examples:
    Source: SrcAlpha
    Destination: OneMinusSrcAlpha
    Result: Normal blending

    Source: SrcAlpha
    Destination: One
    Result: Additive

    Source: One
    Destination: OneMinusSrcAlpha
    Result: Additive when transparent, Normal blending when Opaque (Diablo 3 BlendAdd)

    I documented possible different modes on the wiki.

    You can find the most recent version of the shader here
    Complete Repository

    Code (CSharp):
    1. // --------------------------------------------------------------------------------------------------------------------
    2. // <copyright file="ConfigurableRendering.shader" company="Supyrb">
    3. //   Copyright (c) 2018 Supyrb. All rights reserved.
    4. // </copyright>
    5. // <repository>
    6. //   https://github.com/supyrb/ConfigurableShaders
    7. // </repository>
    8. // <author>
    9. //   Johannes Deml
    10. //   send@johannesdeml.com
    11. // </author>
    12. // <documentation>
    13. //   Wiki: https://github.com/supyrb/ConfigurableShaders/wiki/Blending
    14. //   Blending examples: https://wiki.popcornfx.com/index.php/Particle_tutorial_smoke#Setting_up_the_billboard_renderer
    15. // </documentation>
    16. // --------------------------------------------------------------------------------------------------------------------
    17.  
    18. Shader "ConfigurableShaders/UI"
    19. {
    20.     Properties
    21.     {
    22.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    23.         _Color ("Tint", Color) = (1,1,1,1)
    24.    
    25.         [Header(Blending)]
    26.         [Enum(UnityEngine.Rendering.BlendMode)] _BlendSrc ("Blend mode Source", Int) = 5
    27.         [Enum(UnityEngine.Rendering.BlendMode)] _BlendDst ("Blend mode Destination", Int) = 10
    28.    
    29.         [Header(Stencil)]
    30.         _StencilComp ("Stencil Comparison", Float) = 8
    31.         _Stencil ("Stencil ID", Float) = 0
    32.         _StencilOp ("Stencil Operation", Float) = 0
    33.         _StencilWriteMask ("Stencil Write Mask", Float) = 255
    34.         _StencilReadMask ("Stencil Read Mask", Float) = 255
    35.         [Header(Rendering)]
    36.         _ColorMask ("Color Mask", Float) = 15
    37.         [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    38.     }
    39.  
    40.     CGINCLUDE
    41.     #include "UnityCG.cginc"
    42.     #include "UnityUI.cginc"
    43.  
    44.     fixed4 _Color;
    45.     fixed4 _TextureSampleAdd;
    46.     float4 _ClipRect;
    47.  
    48.     struct appdata_t
    49.     {
    50.         float4 vertex    : POSITION;
    51.         float4 color    : COLOR;
    52.         float2 texcoord : TEXCOORD0;
    53.         UNITY_VERTEX_INPUT_INSTANCE_ID
    54.     };
    55.  
    56.     struct v2f
    57.     {
    58.         float4 vertex    : SV_POSITION;
    59.         fixed4 color    : COLOR;
    60.         float2 texcoord     : TEXCOORD0;
    61.         float4 worldPosition : TEXCOORD1;
    62.         UNITY_VERTEX_OUTPUT_STEREO
    63.     };
    64.  
    65.     v2f vert(appdata_t IN)
    66.     {
    67.         v2f OUT;
    68.         UNITY_SETUP_INSTANCE_ID(IN);
    69.         UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
    70.         OUT.worldPosition = IN.vertex;
    71.         OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
    72.  
    73.         OUT.texcoord = IN.texcoord;
    74.  
    75.         OUT.color = IN.color * _Color;
    76.         return OUT;
    77.     }
    78.  
    79.     sampler2D _MainTex;
    80.  
    81.     fixed4 frag(v2f IN) : SV_Target
    82.     {
    83.         half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
    84.  
    85.         color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
    86.  
    87.         #ifdef UNITY_UI_ALPHACLIP
    88.         clip (color.a - 0.001);
    89.         #endif
    90.  
    91.         return color;
    92.     }
    93.     ENDCG
    94.  
    95.     SubShader
    96.     {
    97.         Tags
    98.         {
    99.             "Queue"="Transparent"
    100.             "IgnoreProjector"="True"
    101.             "RenderType"="Transparent"
    102.             "PreviewType"="Plane"
    103.             "CanUseSpriteAtlas"="True"
    104.         }
    105.    
    106.         Stencil
    107.         {
    108.             Ref [_Stencil]
    109.             Comp [_StencilComp]
    110.             Pass [_StencilOp]
    111.             ReadMask [_StencilReadMask]
    112.             WriteMask [_StencilWriteMask]
    113.         }
    114.         Cull Off
    115.         Lighting Off
    116.         ZWrite Off
    117.         ZTest [unity_GUIZTestMode]
    118.         Blend [_BlendSrc] [_BlendDst]
    119.         ColorMask [_ColorMask]
    120.    
    121.         Pass
    122.         {
    123.    
    124.             CGPROGRAM
    125.             #pragma vertex vert
    126.             #pragma fragment frag
    127.             #pragma multi_compile __ UNITY_UI_ALPHACLIP
    128.             ENDCG
    129.         }
    130.     }
    131. }
     

    Attached Files:

    Last edited: Jun 3, 2019
  15. ScareFire200

    ScareFire200

    Joined:
    May 16, 2020
    Posts:
    4
    If I may woke up this thread, I'm trying to do something similar but just a bit different:

    I'm trying to make a UI material/shader in Unity 2021 that would have my text/image be hidden by mask

    but it would also
    only be visible from the front
    (meaning for example that it would be invisible when observed from the back)

    I understand that I'm gonna have to use the stencil option here, but I don't know how to implement this second feature.