273 lines
9.4 KiB
GLSL
273 lines
9.4 KiB
GLSL
Shader "UI/CRTOverlayEffect"
|
|
{
|
|
Properties
|
|
{
|
|
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
|
_Color ("Tint", Color) = (1,1,1,1)
|
|
|
|
[Header(Scanlines)]
|
|
_ScanlineIntensity ("Scanline Intensity", Range(0, 1)) = 0.3
|
|
_ScanlineCount ("Scanline Count", Range(50, 800)) = 300
|
|
_ScanlineSpeed ("Scanline Speed", Range(0, 5)) = 0.5
|
|
|
|
[Header(Noise)]
|
|
_NoiseIntensity ("Noise Intensity", Range(0, 1)) = 0.15
|
|
_NoiseSpeed ("Noise Speed", Range(0, 50)) = 15
|
|
_NoiseScale ("Noise Scale", Range(1, 100)) = 50
|
|
|
|
[Header(Chromatic Aberration)]
|
|
_ChromaticAberration ("Chromatic Aberration", Range(0, 0.02)) = 0.003
|
|
|
|
[Header(Vignette)]
|
|
_VignetteIntensity ("Vignette Intensity", Range(0, 1)) = 0.3
|
|
_VignetteSmoothness ("Vignette Smoothness", Range(0.01, 1)) = 0.4
|
|
|
|
[Header(Screen Curvature)]
|
|
_CurvatureAmount ("Curvature Amount", Range(0, 0.1)) = 0.02
|
|
|
|
[Header(Flicker)]
|
|
_FlickerIntensity ("Flicker Intensity", Range(0, 0.1)) = 0.02
|
|
_FlickerSpeed ("Flicker Speed", Range(0, 30)) = 8
|
|
|
|
[Header(Glow)]
|
|
_GlowIntensity ("Glow Intensity", Range(0, 1)) = 0.1
|
|
_GlowColor ("Glow Color", Color) = (0.2, 0.8, 1, 1)
|
|
|
|
// 用于控制 stencil 等 UI 功能
|
|
_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
|
|
}
|
|
|
|
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 "CRTOverlay"
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma target 3.0
|
|
|
|
#include "UnityCG.cginc"
|
|
#include "UnityUI.cginc"
|
|
|
|
struct appdata
|
|
{
|
|
float4 vertex : POSITION;
|
|
float4 color : COLOR;
|
|
float2 uv : TEXCOORD0;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float4 vertex : SV_POSITION;
|
|
fixed4 color : COLOR;
|
|
float2 uv : TEXCOORD0;
|
|
float4 worldPosition : TEXCOORD1;
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
sampler2D _MainTex;
|
|
float4 _MainTex_ST;
|
|
fixed4 _Color;
|
|
float4 _ClipRect;
|
|
|
|
// Effect parameters
|
|
float _ScanlineIntensity;
|
|
float _ScanlineCount;
|
|
float _ScanlineSpeed;
|
|
float _NoiseIntensity;
|
|
float _NoiseSpeed;
|
|
float _NoiseScale;
|
|
float _ChromaticAberration;
|
|
float _VignetteIntensity;
|
|
float _VignetteSmoothness;
|
|
float _CurvatureAmount;
|
|
float _FlickerIntensity;
|
|
float _FlickerSpeed;
|
|
float _GlowIntensity;
|
|
fixed4 _GlowColor;
|
|
|
|
// 简单的噪点函数
|
|
float random(float2 st)
|
|
{
|
|
return frac(sin(dot(st.xy, float2(12.9898, 78.233))) * 43758.5453123);
|
|
}
|
|
|
|
// 2D噪点
|
|
float noise(float2 st)
|
|
{
|
|
float2 i = floor(st);
|
|
float2 f = frac(st);
|
|
|
|
float a = random(i);
|
|
float b = random(i + float2(1.0, 0.0));
|
|
float c = random(i + float2(0.0, 1.0));
|
|
float d = random(i + float2(1.0, 1.0));
|
|
|
|
float2 u = f * f * (3.0 - 2.0 * f);
|
|
|
|
return lerp(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
|
|
}
|
|
|
|
v2f vert(appdata v)
|
|
{
|
|
v2f o;
|
|
UNITY_SETUP_INSTANCE_ID(v);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
|
|
|
o.worldPosition = v.vertex;
|
|
o.vertex = UnityObjectToClipPos(v.vertex);
|
|
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
|
o.color = v.color * _Color;
|
|
|
|
return o;
|
|
}
|
|
|
|
fixed4 frag(v2f i) : SV_Target
|
|
{
|
|
float2 uv = i.uv;
|
|
float time = _Time.y;
|
|
|
|
// 1. 屏幕弯曲效果
|
|
float2 curvedUV = uv;
|
|
if (_CurvatureAmount > 0)
|
|
{
|
|
float2 centered = uv - 0.5;
|
|
float dist = dot(centered, centered);
|
|
curvedUV = uv + centered * dist * _CurvatureAmount;
|
|
}
|
|
|
|
// 检查是否超出边界
|
|
if (curvedUV.x < 0 || curvedUV.x > 1 || curvedUV.y < 0 || curvedUV.y > 1)
|
|
{
|
|
return fixed4(0, 0, 0, 0);
|
|
}
|
|
|
|
// 2. 采样基础颜色 (带色差)
|
|
fixed4 col = fixed4(0, 0, 0, 0);
|
|
|
|
if (_ChromaticAberration > 0)
|
|
{
|
|
float2 dir = normalize(curvedUV - 0.5);
|
|
float dist = length(curvedUV - 0.5);
|
|
float aberration = _ChromaticAberration * dist;
|
|
|
|
col.r = tex2D(_MainTex, curvedUV + dir * aberration).r;
|
|
col.g = tex2D(_MainTex, curvedUV).g;
|
|
col.b = tex2D(_MainTex, curvedUV - dir * aberration).b;
|
|
col.a = tex2D(_MainTex, curvedUV).a;
|
|
}
|
|
else
|
|
{
|
|
col = tex2D(_MainTex, curvedUV);
|
|
}
|
|
|
|
col *= i.color;
|
|
|
|
// 3. 扫描线
|
|
if (_ScanlineIntensity > 0)
|
|
{
|
|
float scanline = sin((curvedUV.y + time * _ScanlineSpeed * 0.1) * _ScanlineCount * 3.14159) * 0.5 + 0.5;
|
|
scanline = pow(scanline, 1.5);
|
|
col.rgb *= 1.0 - (_ScanlineIntensity * (1.0 - scanline));
|
|
|
|
// 添加水平扫描线移动效果
|
|
float movingScanline = sin((curvedUV.y - time * 0.2) * 20.0) * 0.5 + 0.5;
|
|
movingScanline = step(0.99, movingScanline);
|
|
col.rgb += movingScanline * 0.03;
|
|
}
|
|
|
|
// 4. 噪点
|
|
if (_NoiseIntensity > 0)
|
|
{
|
|
float2 noiseUV = curvedUV * _NoiseScale;
|
|
float n = noise(noiseUV + time * _NoiseSpeed);
|
|
n = n * 2.0 - 1.0; // 转换到 -1 到 1 范围
|
|
col.rgb += n * _NoiseIntensity;
|
|
|
|
// 添加一些随机的小噪点/颗粒
|
|
float grain = random(curvedUV * 1000.0 + time * 100.0);
|
|
grain = (grain - 0.5) * _NoiseIntensity * 0.5;
|
|
col.rgb += grain;
|
|
}
|
|
|
|
// 5. 闪烁
|
|
if (_FlickerIntensity > 0)
|
|
{
|
|
float flicker = 1.0 + sin(time * _FlickerSpeed) * _FlickerIntensity;
|
|
flicker *= 1.0 + random(float2(time * 0.1, 0)) * _FlickerIntensity * 0.5;
|
|
col.rgb *= flicker;
|
|
}
|
|
|
|
// 6. 暗角
|
|
if (_VignetteIntensity > 0)
|
|
{
|
|
float2 vignetteUV = curvedUV * (1.0 - curvedUV);
|
|
float vignette = vignetteUV.x * vignetteUV.y * 15.0;
|
|
vignette = pow(vignette, _VignetteSmoothness);
|
|
vignette = saturate(vignette);
|
|
col.rgb *= lerp(1.0 - _VignetteIntensity, 1.0, vignette);
|
|
}
|
|
|
|
// 7. 发光效果
|
|
if (_GlowIntensity > 0)
|
|
{
|
|
col.rgb += _GlowColor.rgb * _GlowIntensity * col.a;
|
|
}
|
|
|
|
// 8. 添加一些RGB分离的条纹效果 (模拟CRT的RGB像素)
|
|
float rgbStripe = frac(curvedUV.x * 300.0);
|
|
float3 rgbMask = float3(
|
|
step(rgbStripe, 0.33),
|
|
step(0.33, rgbStripe) * step(rgbStripe, 0.66),
|
|
step(0.66, rgbStripe)
|
|
);
|
|
// 轻微的RGB条纹效果
|
|
col.rgb = lerp(col.rgb, col.rgb * (0.8 + rgbMask * 0.4), 0.05);
|
|
|
|
// 应用 UI 裁剪
|
|
col.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
|
|
|
|
#ifdef UNITY_UI_ALPHACLIP
|
|
clip(col.a - 0.001);
|
|
#endif
|
|
|
|
return col;
|
|
}
|
|
ENDCG
|
|
}
|
|
}
|
|
}
|