Search Unity

UI Text Shine Effect

Discussion in 'UGUI & TextMesh Pro' started by ctalk, Apr 21, 2017.

  1. ctalk

    ctalk

    Joined:
    Apr 21, 2017
    Posts:
    12
    Hello everyone! I would like to make an effect similar to the one posted below on UIText, is it possible to achieve it with a shader? any guidelines to it would be great!

     
  2. katoun

    katoun

    Joined:
    Dec 26, 2012
    Posts:
    91
    Hello ctalk,
    Yes, you can do it with a shader.
    If you create an UI Image or UI Text, you will see it has an optional Material property.
    1. Create a new material and shader for your UI shine effect.
    2. Duplicate the default UI shader code inside you new shader and add the shine effect.
    3. Set the new shader the the new material and the new material to the desired UI elements.
    Each Unity version comes with a builtin shaders source code pack. From there you can have the source code for the default shader for UI.
    For the Unity 5.6 this is the link: http://download.unity3d.com/downloa....0f3.zip?_ga=1.109058438.223451705.1457538788
    Now, for the shine effect shader code, go about this way:
    - Add these properties to the Properties block:
    Code (CSharp):
    1. _ShineWidth("ShineWidth", Range(0, 1)) = 0.01
    2. _ShineLocation("ShineLocation", Range(0, 1)) = 0
    - Modify your final color of your fragment function to get the shine effect:
    Code (CSharp):
    1. fixed currentDistanceProjection = ((i.texcoord.x * 2) + i.texcoord.y) / 3;
    2.  
    3. fixed lowLevel = _ShineLocation - _ShineWidth;
    4. fixed highLevel = _ShineLocation + _ShineWidth;
    5. fixed shinePower = smoothstep(_ShineWidth, 0, abs(abs(clamp(currentDistanceProjection, lowLevel, highLevel) - _ShineLocation)));
    6.  
    7. color.rgb +=  color.a * (shinePower / 2);
    What this does is it computes an angled line using the 'currentDistanceProjection' and the '_ShineLocation'.
    Then it adds the shine taking into account the "_ShineWidth" to the left and the right of the '_ShineLocation'.

    - Last step is to create a Script that you attach to the dresirec UI element that manipulated the "_ShineLocation" of the shader with a coroutine:
    Code (CSharp):
    1.  
    2.         private Material spriteMaterial = null;
    3.         private float shinePositon = 0;
    4.         private Coroutine shineRoutine = null;
    5.  
    6.         void Start()
    7.         {
    8.             shineLocationParameterID = Shader.PropertyToID("_ShineLocation");
    9.  
    10.             spriteRenderer = GetComponent<SpriteRenderer>();
    11.  
    12.             spriteMaterial = spriteRenderer.material;
    13.         }
    14.  
    15.         public void StartShine(float delay)
    16.         {
    17.             if (shineRoutine != null)
    18.                 StopCoroutine(shineRoutine);
    19.             shineRoutine = StartCoroutine(StartShineCoroutine(delay));
    20.         }
    21.  
    22.         public void StopShine()
    23.         {
    24.             if (shineRoutine != null)
    25.                 StopCoroutine(shineRoutine);
    26.             shineRoutine = null;
    27.         }
    28.  
    29.         private float ShineCurve(float lerpProgress)
    30.         {
    31.             float newValue = lerpProgress * lerpProgress * lerpProgress * (lerpProgress * (6f * lerpProgress - 15f) + 10f);
    32.             return newValue;
    33.         }
    34.  
    35.         private IEnumerator StartShineCoroutine(float dealay)
    36.         {
    37.             yield return new WaitForSeconds(dealay);
    38.  
    39.             if (shineSpeed <= 0f)
    40.                 yield break;
    41.  
    42.             int count = loop ? 1 : shineRepeats;
    43.             while (count > 0)
    44.             {
    45.                 yield return new WaitForSeconds(shineWaitTime);
    46.  
    47.                 count = loop ? 1 : count - 1;
    48.  
    49.                 float startTime = Time.time;
    50.  
    51.                 while (Time.time < startTime + 1f / shineSpeed)
    52.                 {
    53.                     shinePositon = ShineCurve((Time.time - startTime) * shineSpeed);
    54.                     spriteMaterial.SetFloat(shineLocationParameterID, shinePositon);
    55.  
    56.                     yield return new WaitForEndOfFrame();
    57.                 }
    58.             }
    59.  
    60.             yield break;
    61.         }
    62.     }
    63.  
    There should be a way to eliminate the Script code, but I haven't tested that yet.
    In the Manual, in the Built-in shader variables, there are a number of variables for Time: '_Time', '_SinTime', '_CosTime' and 'unity_DeltaTime'. It should be possible to move the coroutine/update code to the shader code if you want the shine effect to be permanent and not controllable from the C# code side.

    For Text I think it gets a bit complicated because it's drawn from multiple quads and the effect works consistently on a single one. My approach would be create an overlay quad on the text, get the alpha mask from the text and feed it the shine shader that is set on that overlay quad and the rest is as described above.
     
    Last edited: Apr 21, 2017
    DenariiGames likes this.
  3. kwchin

    kwchin

    Joined:
    Aug 22, 2017
    Posts:
    1
    Hi,

    Sorry im new in writing shader.

    I am able to follow up to this step

    im not sure what is the fragment function, is it possible to explain alittle more in depth?

    Thanks in advance
     
  4. JbStudio425

    JbStudio425

    Joined:
    Nov 2, 2017
    Posts:
    5
    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "UI/ShineEffect"
    4. {
    5.     Properties
    6.     {
    7.    
    8.    
    9.         _ShineWidth("ShineWidth", Range(0, 1)) = 0.01
    10.         _ShineLocation("ShineLocation", Range(0, 1)) = 0
    11.    
    12.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    13.         _Color ("Tint", Color) = (1,1,1,1)
    14.        
    15.         _StencilComp ("Stencil Comparison", Float) = 8
    16.         _Stencil ("Stencil ID", Float) = 0
    17.         _StencilOp ("Stencil Operation", Float) = 0
    18.         _StencilWriteMask ("Stencil Write Mask", Float) = 255
    19.         _StencilReadMask ("Stencil Read Mask", Float) = 255
    20.  
    21.         _ColorMask ("Color Mask", Float) = 15
    22.  
    23.         [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    24.     }
    25.  
    26.     SubShader
    27.     {
    28.         Tags
    29.         {
    30.             "Queue"="Transparent"
    31.             "IgnoreProjector"="True"
    32.             "RenderType"="Transparent"
    33.             "PreviewType"="Plane"
    34.             "CanUseSpriteAtlas"="True"
    35.         }
    36.        
    37.         Stencil
    38.         {
    39.             Ref [_Stencil]
    40.             Comp [_StencilComp]
    41.             Pass [_StencilOp]
    42.             ReadMask [_StencilReadMask]
    43.             WriteMask [_StencilWriteMask]
    44.         }
    45.  
    46.         Cull Off
    47.         Lighting Off
    48.         ZWrite Off
    49.         ZTest [unity_GUIZTestMode]
    50.         Blend SrcAlpha OneMinusSrcAlpha
    51.         ColorMask [_ColorMask]
    52.  
    53.         Pass
    54.         {
    55.             Name "Default"
    56.         CGPROGRAM
    57.             #pragma vertex vert
    58.             #pragma fragment frag
    59.             #pragma target 2.0
    60.  
    61.             #include "UnityCG.cginc"
    62.             #include "UnityUI.cginc"
    63.  
    64.             #pragma multi_compile __ UNITY_UI_ALPHACLIP
    65.            
    66.             struct appdata_t
    67.             {
    68.                 float4 vertex   : POSITION;
    69.                 float4 color    : COLOR;
    70.                 float2 texcoord : TEXCOORD0;
    71.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    72.             };
    73.  
    74.             struct v2f
    75.             {
    76.                 float4 vertex   : SV_POSITION;
    77.                 fixed4 color    : COLOR;
    78.                 float2 texcoord  : TEXCOORD0;
    79.                 float4 worldPosition : TEXCOORD1;
    80.                 UNITY_VERTEX_OUTPUT_STEREO
    81.             };
    82.            
    83.             fixed4 _Color;
    84.             fixed4 _TextureSampleAdd;
    85.             float4 _ClipRect;
    86.            
    87.             Float _ShineLocation;
    88.             Float _ShineWidth;
    89.  
    90.             v2f vert(appdata_t IN)
    91.             {
    92.                 v2f OUT;
    93.                 UNITY_SETUP_INSTANCE_ID(IN);
    94.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
    95.                 OUT.worldPosition = IN.vertex;
    96.                 OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
    97.  
    98.                 OUT.texcoord = IN.texcoord;
    99.                
    100.                 OUT.color = IN.color * _Color;
    101.                 return OUT;
    102.             }
    103.  
    104.             sampler2D _MainTex;
    105.  
    106.             fixed4 frag(v2f IN) : SV_Target
    107.             {
    108.            
    109.            
    110.             half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
    111.                
    112.                 color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
    113.                
    114.                 #ifdef UNITY_UI_ALPHACLIP
    115.                 clip (color.a - 0.001);
    116.                 #endif
    117.            
    118.            
    119.             fixed currentDistanceProjection = ((IN.texcoord.x * 2) + IN.texcoord.y) / 3;
    120.             fixed lowLevel = _ShineLocation - _ShineWidth;
    121.             fixed highLevel = _ShineLocation + _ShineWidth;
    122.             fixed shinePower = smoothstep(_ShineWidth, 0, abs(abs(clamp(currentDistanceProjection, lowLevel, highLevel) - _ShineLocation)));
    123.             color.rgb +=  color.a * (shinePower / 2);
    124.            
    125.                
    126.  
    127.                 return color;
    128.             }
    129.         ENDCG
    130.         }
    131.     }
    132. }
    133.  
     
    Lay84 likes this.