Unity UI.Image 六边形+流光 Shader

效果图

参考代码

Shader"Custom/HexFlowImage"
{
    Properties
    {
        [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

         /*六边形参数*/
        _HexLineSize("HexLineSize",Range(0.02,0.2)) = 0.05       //线条粗细
        _HexZoom("HexZoom",Range(5,50)) = 10                     //六边形缩放
 
        /*流光参数*/
        _Angle("Angle",Range(0,3.1415926))=0                     //坐标系旋转角度
        _LineStrength("LineStrength",Range(0.01,0.99))=0.1       //流光线条粗细
        _LineEdge("LineEdge",Range(0,0.1))=0.01                  //流光边界过度粗细
        _LineOffset("LineOffset",Range(0,1))=0.5                 //流光坐标偏移
        _LineSpeed("MoveSpeed",float) =1                         //流光移动速度
        _LineColor("Color",Color)=(1,1,1,1)                      //流光颜色

        [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 One
        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_local _ UNITY_UI_CLIP_RECT
            #pragma multi_compile_local _ UNITY_UI_ALPHACLIP
            #define aspec _ScreenParams.x/_ScreenParams.y                          /*屏幕长款比例*/                                   
            #define rot float2x2(cos(_Angle),sin(_Angle),-sin(_Angle),cos(_Angle)) /*旋转矩阵*/        
            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;
                   float4 mask : TEXCOORD2;
                   float2 viewTexcoord : TEXTCOORD3;   //屏幕坐标
                   UNITY_VERTEX_OUTPUT_STEREO
              };

               sampler2D _MainTex;
               fixed4 _Color;
               fixed4 _TextureSampleAdd;

               float4 _ClipRect;
               float4 _MainTex_ST;
               float _UIMaskSoftnessX;
               float _UIMaskSoftnessY;
               float _HexLineSize;
               float _HexZoom;

               float _Angle;
               float _LineStrength;
               float _LineEdge;
               float _LineOffset;
               float _LineSpeed;
               fixed4 _LineColor;

               float HexDist(fixed2 p)
               {
                   p = abs(p);
                   float c = dot(p, normalize(fixed2(1, 1.73)));
                   c = max(c, p.x);
                   return c;
               }

               fixed4 HexCoords(fixed2 uv)
               {
                   const fixed2 r = fixed2(1, 1.73);
                   const fixed2 h = r * .5;
                   fixed2 a = fmod(uv, r) - h;
                   fixed2 b = fmod(uv - h, r) - h;  
                   fixed2 gv = dot(a, a) < dot(b, b) ? a : b;
                   float x = atan2(gv.x, gv.y);
                   float y = .5 - HexDist(gv);
                   fixed2 id = uv - gv;
                   return fixed4(x, y, id.x, id.y);
               }

               v2f vert(appdata_t v)
               {
                   v2f OUT;
                   UNITY_SETUP_INSTANCE_ID(v);
                   UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                   float4 vPosition = UnityObjectToClipPos(v.vertex);
                   OUT.worldPosition = v.vertex;
                   OUT.vertex = vPosition;

                   float2 pixelSize = vPosition.w;
                   pixelSize /= float2(1, 1) * abs(mul((float2x2) UNITY_MATRIX_P, _ScreenParams.xy));

                   float4 clampedRect = clamp(_ClipRect, -2e10, 2e10);
                   float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy);
                   OUT.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex);
                   OUT.mask = float4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy)));

                   OUT.color = v.color;

                   //计算屏幕坐标
                   fixed4 vpos = ComputeScreenPos(OUT.vertex);
                   OUT.viewTexcoord = vpos.xy / vpos.w;
                   OUT.viewTexcoord.x *= aspec;
                   OUT.viewTexcoord += 0.5;
                   return OUT;
               }

               fixed4 frag(v2f IN) : SV_Target
               {
                   const half alphaPrecision = half(0xff);
                   const half invAlphaPrecision = half(1.0 / alphaPrecision);
                   IN.color.a = round(IN.color.a * alphaPrecision) * invAlphaPrecision;

                   //获取屏幕坐标 计算六边形像素
                   float2 uv1 = IN.viewTexcoord + float2(0, sin(IN.viewTexcoord.x * 5. + _Time.y) * 0.01);
                   half4 hex = smoothstep(_HexLineSize, .0, HexCoords(uv1 * _HexZoom).y) * IN.color.a;

                   //旋转屏幕坐标计算流光像素
                   float2 uv2 =   mul(rot,IN.viewTexcoord.xy);
                   uv2.x +=  _Time.y * _LineSpeed;
                   uv2.x = frac(uv2.x);
                   float d = smoothstep(_LineOffset,_LineOffset + _LineEdge,uv2.x) * smoothstep(_LineOffset + _LineStrength,_LineOffset + _LineStrength - _LineEdge,uv2.x);

                   //通过lerp函数进行差值融合 再与原始图像进行叠加
                   half4 color = lerp( IN.color * hex , hex  * _LineColor,d)+ tex2D(_MainTex, IN.texcoord);

#ifdef UNITY_UI_CLIP_RECT
                   half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw);
                   color.a *= m.x * m.y;
#endif

#ifdef UNITY_UI_ALPHACLIP
                   clip (color.a - 0.001);
#endif
                   color.rgb *= color.a;
                   return color;
               }
        ENDCG
        }
    }
}