find-object-bundle-builder/pipeline_Profile/build_profile_package/Assets/AssetRaw/shader/TextScanEffect.shader

185 lines
7.2 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 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
}
}
}