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!
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): _ShineWidth("ShineWidth", Range(0, 1)) = 0.01 _ShineLocation("ShineLocation", Range(0, 1)) = 0 - Modify your final color of your fragment function to get the shine effect: Code (CSharp): fixed currentDistanceProjection = ((i.texcoord.x * 2) + i.texcoord.y) / 3; fixed lowLevel = _ShineLocation - _ShineWidth; fixed highLevel = _ShineLocation + _ShineWidth; fixed shinePower = smoothstep(_ShineWidth, 0, abs(abs(clamp(currentDistanceProjection, lowLevel, highLevel) - _ShineLocation))); 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): private Material spriteMaterial = null; private float shinePositon = 0; private Coroutine shineRoutine = null; void Start() { shineLocationParameterID = Shader.PropertyToID("_ShineLocation"); spriteRenderer = GetComponent<SpriteRenderer>(); spriteMaterial = spriteRenderer.material; } public void StartShine(float delay) { if (shineRoutine != null) StopCoroutine(shineRoutine); shineRoutine = StartCoroutine(StartShineCoroutine(delay)); } public void StopShine() { if (shineRoutine != null) StopCoroutine(shineRoutine); shineRoutine = null; } private float ShineCurve(float lerpProgress) { float newValue = lerpProgress * lerpProgress * lerpProgress * (lerpProgress * (6f * lerpProgress - 15f) + 10f); return newValue; } private IEnumerator StartShineCoroutine(float dealay) { yield return new WaitForSeconds(dealay); if (shineSpeed <= 0f) yield break; int count = loop ? 1 : shineRepeats; while (count > 0) { yield return new WaitForSeconds(shineWaitTime); count = loop ? 1 : count - 1; float startTime = Time.time; while (Time.time < startTime + 1f / shineSpeed) { shinePositon = ShineCurve((Time.time - startTime) * shineSpeed); spriteMaterial.SetFloat(shineLocationParameterID, shinePositon); yield return new WaitForEndOfFrame(); } } yield break; } } 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.
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
Code (CSharp): // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) Shader "UI/ShineEffect" { Properties { _ShineWidth("ShineWidth", Range(0, 1)) = 0.01 _ShineLocation("ShineLocation", Range(0, 1)) = 0 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) _StencilComp ("Stencil Comparison", Float) = 8 _Stencil ("Stencil ID", Float) = 0 _StencilOp ("Stencil Operation", Float) = 0 _StencilWriteMask ("Stencil Write Mask", Float) = 255 _StencilReadMask ("Stencil Read Mask", Float) = 255 _ColorMask ("Color Mask", Float) = 15 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Stencil { Ref [_Stencil] Comp [_StencilComp] Pass [_StencilOp] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] } Cull Off Lighting Off ZWrite Off ZTest [unity_GUIZTestMode] Blend SrcAlpha OneMinusSrcAlpha ColorMask [_ColorMask] Pass { Name "Default" CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc" #include "UnityUI.cginc" #pragma multi_compile __ UNITY_UI_ALPHACLIP struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPosition : TEXCOORD1; UNITY_VERTEX_OUTPUT_STEREO }; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; Float _ShineLocation; Float _ShineWidth; v2f vert(appdata_t IN) { v2f OUT; UNITY_SETUP_INSTANCE_ID(IN); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); OUT.worldPosition = IN.vertex; OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; return OUT; } sampler2D _MainTex; fixed4 frag(v2f IN) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); #ifdef UNITY_UI_ALPHACLIP clip (color.a - 0.001); #endif fixed currentDistanceProjection = ((IN.texcoord.x * 2) + IN.texcoord.y) / 3; fixed lowLevel = _ShineLocation - _ShineWidth; fixed highLevel = _ShineLocation + _ShineWidth; fixed shinePower = smoothstep(_ShineWidth, 0, abs(abs(clamp(currentDistanceProjection, lowLevel, highLevel) - _ShineLocation))); color.rgb += color.a * (shinePower / 2); return color; } ENDCG } } }