// TextScanEffect.shader
// 文本扫光效果着色器，用于UI文本的动态扫光特效
// 功能：在文本上创建一个从左到右（或自定义角度）移动的扫光效果
// 优化：实现连续扫光，无间隔等待时间
Shader "Custom/TextScanEffect"
{
    Properties
    {
        [PerRendererData] _MainTex ("Font Texture", 2D) = "white" {}
        [PerRendererData] _Color ("Text Color", Color) = (1,1,1,1)
        
        // 扫光参数
        _ScanColor ("Scan Color", Color) = (1,0.8,0,1)    // 扫光颜色
        _ScanWidth ("Scan Width", Range(0, 0.5)) = 0.15   // 扫光宽度
        _ScanSpeed ("Scan Speed", Range(0, 50)) = 1.5     // 扫光速度
        _ScanIntensity ("Scan Intensity", Range(0, 5)) = 2 // 扫光强度
        [HideInInspector] _ScanInterval ("Scan Interval", Range(0, 0.1)) = 0.0 // 隐藏间隔参数，默认为0实现连续扫光
        _ScanAngle ("Scan Angle", Range(-45, 45)) = 30    // 扫光角度
        
        // 添加遮罩所需属性
        _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"
        }
        
        // 添加模板测试配置
        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
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            // 引入Unity UI所需的库
            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            // 启用UI裁剪和Alpha裁剪功能
            #pragma multi_compile_local _ UNITY_UI_CLIP_RECT
            #pragma multi_compile_local _ UNITY_UI_ALPHACLIP
            
            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 screenPos : TEXCOORD1;
                fixed4 color : COLOR;
                float4 worldPosition : TEXCOORD2;   // 添加世界坐标用于遮罩裁剪
            };

            // 着色器属性声明
            sampler2D _MainTex;         // 字体纹理
            fixed4 _Color;              // 文本颜色
            fixed4 _ScanColor;          // 扫光颜色
            float _ScanWidth;           // 扫光宽度
            float _ScanSpeed;           // 扫光速度
            float _ScanIntensity;       // 扫光强度
            float _ScanInterval;        // 扫光间隔（已隐藏，保留变量以兼容旧版本）
            float _ScanAngle;           // 扫光角度
            
            // UI遮罩所需变量
            float4 _ClipRect;           // 裁剪矩形

            // 顶点着色器
            v2f vert (appdata_t v)
            {
                v2f o;
                // 转换顶点到裁剪空间
                o.vertex = UnityObjectToClipPos(v.vertex);
                // 传递UV坐标
                o.uv = v.uv;
                // 计算屏幕空间位置（用于扫光效果）
                o.screenPos = ComputeScreenPos(o.vertex);
                // 计算颜色
                o.color = v.color * _Color;
                // 保存世界坐标用于UI遮罩裁剪
                o.worldPosition = v.vertex;
                return o;
            }

            // 片段着色器
            fixed4 frag (v2f i) : SV_Target
            {
                // 基础颜色计算 - 采样字体纹理并应用颜色
                fixed4 tex = tex2D(_MainTex, i.uv);
                fixed4 col = i.color;
                // 应用字体纹理的alpha通道
                col.a *= tex.a;

                // 屏幕空间计算
                float2 screenUV = i.screenPos.xy / i.screenPos.w;
                
                // 扫光方向计算
                float angle = radians(_ScanAngle);
                float2 dir = float2(cos(angle), sin(angle));
                
                // 时间参数计算（实现真正连续的双重扫光）
                float speed = max(_ScanSpeed, 0.01); // 防止除零错误
                
                // 计算三个错开的扫光时间，确保始终有扫光效果可见
                float time1 = fmod(_Time.y * speed * 0.5, 3.0); // 第一个扫光时间
                float time2 = fmod(_Time.y * speed * 0.5 + 1.0, 3.0); // 第二个扫光时间（错开1个单位）
                float time3 = fmod(_Time.y * speed * 0.5 + 2.0, 3.0); // 第二个扫光时间（错开1个单位）
                
                // 扫描带位置计算
                float scanPos = dot(screenUV, dir);
                
                // 计算三个扫光的位置
                // 扩大移动范围，确保扫光完全穿过屏幕
                float lightPos1 = time1 - 1.0; // 从-1.5移动到1.5
                float lightPos2 = time2 - 1.0; // 从-1.5移动到1.5
                float lightPos3 = time3 - 1.0; // 从-1.5移动到1.5
                
                // 计算三个扫光到当前像素的距离
                float distance1 = abs(scanPos - lightPos1);
                float distance2 = abs(scanPos - lightPos2);
                float distance3 = abs(scanPos - lightPos3);
                
                // 计算三个扫光的强度
                double width = max(_ScanWidth, 0.001);
                float scan1 = 1.0 - smoothstep(0, width, distance1);
                float scan2 = 1.0 - smoothstep(0, width, distance2);
                float scan3 = 1.0 - smoothstep(0, width, distance3);
                
                // 合并三个扫光效果（取最大值）
                float scan = max(max(scan1, scan2), scan3);
                
                // 将扫光效果叠加到原始颜色上
                // 使用alpha值确保透明区域不会显示扫光效果
                col.rgb += _ScanColor.rgb * scan * _ScanIntensity * col.a;
                
                // 应用UI遮罩裁剪
                #ifdef UNITY_UI_CLIP_RECT
                col.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
                #endif
                
                #ifdef UNITY_UI_ALPHACLIP
                clip(col.a - 0.001);
                #endif
                
                // 使用saturate确保颜色值在0-1范围内
                return saturate(col); // 等同于clamp(col, 0, 1)
            }
            ENDCG
        }
    }
}