294 lines
13 KiB
Plaintext
294 lines
13 KiB
Plaintext
Shader "AibisDream/MemoryTuningSprite"
|
||
{
|
||
Properties
|
||
{
|
||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||
_Color ("Tint", Color) = (1,1,1,1)
|
||
_RendererColor ("Renderer Color", Color) = (1,1,1,1)
|
||
_ClarityTuning ("Clarity Tuning", Range(0,1)) = 0
|
||
_FrequencyTuning ("Frequency Tuning", Range(0,1)) = 0
|
||
_DirectionalDistortionFade ("Directional Distortion Fade", Range(-15,1)) = -15
|
||
_PixelMin ("Pixel Min", Range(8,64)) = 18
|
||
_PixelMax ("Pixel Max", Range(32,256)) = 128
|
||
_BlurStep ("Blur Step", Range(0,0.01)) = 0.0025
|
||
_DistortStrength ("Distort Strength", Range(0,0.08)) = 0.035
|
||
_ChromaticStrength ("Chromatic Strength", Range(0,0.03)) = 0.008
|
||
_FadeDistortStrength ("Fade Distort Strength", Range(0,0.2)) = 0.12
|
||
_PixelateFade ("Pixelate Fade", Range(0,1)) = 0
|
||
_PixelatePixelDensity ("Pixelate Pixel Density", Range(6,160)) = 96
|
||
_GaussianBlurFade ("Gaussian Blur Fade", Range(0,1)) = 0
|
||
_GaussianBlurOffset ("Gaussian Blur Offset", Range(0,1)) = 0.05
|
||
_UVDistortFade ("UV Distort Fade", Range(0,1)) = 0
|
||
_MemoryGrayscale ("Memory Grayscale", Range(0,1)) = 0
|
||
_MemoryContrast ("Memory Contrast", Range(0,3)) = 1
|
||
_ColorEraseWidth ("Color Erase Width", Range(0.05,2)) = 0.5
|
||
_ColorEraseNoiseScale ("Color Erase Noise Scale", Range(1,64)) = 9
|
||
_ColorEraseNoiseFactor ("Color Erase Noise Factor", Range(0,2)) = 0.2
|
||
_ColorEraseBias ("Color Erase Bias", Range(0,2)) = 0.6
|
||
_ColorEraseContrast ("Color Erase Gray Contrast", Range(0,3)) = 1.8
|
||
_ColorEraseEdgeGlow ("Color Erase Edge Glow", Range(0,3)) = 1.1
|
||
_ColorEraseEdgeWobble ("Color Erase Edge Wobble", Range(0,0.05)) = 0.006
|
||
_ColorEraseSpan ("Color Erase Sweep Span", Range(1,15)) = 7
|
||
_ColorEraseEdgeSharp ("Color Erase Edge Sharpness", Range(1,10)) = 4
|
||
_ColorEraseGlitch ("Color Erase Glitch", Range(0,1)) = 0.35
|
||
|
||
[HideInInspector] _StencilComp ("Stencil Comparison", Float) = 8
|
||
[HideInInspector] _Stencil ("Stencil ID", Float) = 0
|
||
[HideInInspector] _StencilOp ("Stencil Operation", Float) = 0
|
||
[HideInInspector] _StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||
[HideInInspector] _StencilReadMask ("Stencil Read Mask", Float) = 255
|
||
[HideInInspector] _ColorMask ("Color Mask", Float) = 15
|
||
}
|
||
|
||
SubShader
|
||
{
|
||
Tags
|
||
{
|
||
"Queue" = "Transparent"
|
||
"RenderType" = "Transparent"
|
||
"RenderPipeline" = "UniversalPipeline"
|
||
"IgnoreProjector" = "True"
|
||
"CanUseSpriteAtlas" = "True"
|
||
}
|
||
|
||
Cull Off
|
||
Lighting Off
|
||
ZWrite Off
|
||
ZTest [unity_GUIZTestMode]
|
||
Blend SrcAlpha OneMinusSrcAlpha
|
||
ColorMask [_ColorMask]
|
||
|
||
Stencil
|
||
{
|
||
Ref [_Stencil]
|
||
Comp [_StencilComp]
|
||
Pass [_StencilOp]
|
||
ReadMask [_StencilReadMask]
|
||
WriteMask [_StencilWriteMask]
|
||
}
|
||
|
||
Pass
|
||
{
|
||
HLSLPROGRAM
|
||
#pragma vertex vert
|
||
#pragma fragment frag
|
||
#pragma multi_compile_instancing
|
||
|
||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||
|
||
struct Attributes
|
||
{
|
||
float4 positionOS : POSITION;
|
||
float4 color : COLOR;
|
||
float2 uv : TEXCOORD0;
|
||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||
};
|
||
|
||
struct Varyings
|
||
{
|
||
float4 positionHCS : SV_POSITION;
|
||
half4 color : COLOR;
|
||
float2 uv : TEXCOORD0;
|
||
UNITY_VERTEX_OUTPUT_STEREO
|
||
};
|
||
|
||
TEXTURE2D(_MainTex);
|
||
SAMPLER(sampler_MainTex);
|
||
float4 _MainTex_TexelSize;
|
||
|
||
CBUFFER_START(UnityPerMaterial)
|
||
half4 _Color;
|
||
half4 _RendererColor;
|
||
half _ClarityTuning;
|
||
half _FrequencyTuning;
|
||
half _DirectionalDistortionFade;
|
||
half _PixelMin;
|
||
half _PixelMax;
|
||
half _BlurStep;
|
||
half _DistortStrength;
|
||
half _ChromaticStrength;
|
||
half _FadeDistortStrength;
|
||
half _PixelateFade;
|
||
half _PixelatePixelDensity;
|
||
half _GaussianBlurFade;
|
||
half _GaussianBlurOffset;
|
||
half _UVDistortFade;
|
||
half _MemoryGrayscale;
|
||
half _MemoryContrast;
|
||
half _ColorEraseWidth;
|
||
half _ColorEraseNoiseScale;
|
||
half _ColorEraseNoiseFactor;
|
||
half _ColorEraseBias;
|
||
half _ColorEraseContrast;
|
||
half _ColorEraseEdgeGlow;
|
||
half _ColorEraseEdgeWobble;
|
||
half _ColorEraseSpan;
|
||
half _ColorEraseEdgeSharp;
|
||
half _ColorEraseGlitch;
|
||
CBUFFER_END
|
||
|
||
float Hash21(float2 p)
|
||
{
|
||
p = frac(p * float2(127.1, 311.7));
|
||
p += dot(p, p + 19.19);
|
||
return frac(p.x * p.y);
|
||
}
|
||
|
||
float ValueNoise(float2 p)
|
||
{
|
||
float2 i = floor(p);
|
||
float2 f = frac(p);
|
||
f = f * f * (3.0 - 2.0 * f);
|
||
float a = Hash21(i);
|
||
float b = Hash21(i + float2(1.0, 0.0));
|
||
float c = Hash21(i + float2(0.0, 1.0));
|
||
float d = Hash21(i + float2(1.0, 1.0));
|
||
return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y);
|
||
}
|
||
|
||
Varyings vert(Attributes input)
|
||
{
|
||
Varyings output;
|
||
UNITY_SETUP_INSTANCE_ID(input);
|
||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||
|
||
output.positionHCS = TransformObjectToHClip(input.positionOS.xyz);
|
||
output.uv = input.uv;
|
||
output.color = input.color * _Color * _RendererColor;
|
||
return output;
|
||
}
|
||
|
||
half4 SampleSprite(float2 uv)
|
||
{
|
||
half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, saturate(uv));
|
||
half luma = dot(col.rgb, half3(0.299, 0.587, 0.114));
|
||
col.rgb = lerp(col.rgb, half3(luma, luma, luma), saturate(_MemoryGrayscale));
|
||
col.rgb = saturate(lerp(half3(0.5, 0.5, 0.5), col.rgb, _MemoryContrast));
|
||
return col;
|
||
}
|
||
|
||
float2 PixelSnap(float2 uv, half strength, half density)
|
||
{
|
||
half pixels = max(1.0, lerp(_PixelMax, _PixelMin, strength));
|
||
pixels = lerp(pixels, max(1.0, density), step(0.001, density));
|
||
float texW = max(1.0, _MainTex_TexelSize.z);
|
||
float texH = max(1.0, abs(_MainTex_TexelSize.w));
|
||
float2 aspectPixels = float2(pixels, max(1.0, pixels * texW / texH));
|
||
return round((uv - 0.5) * aspectPixels) / aspectPixels + 0.5;
|
||
}
|
||
|
||
float2 DistortUv(float2 uv, half strength)
|
||
{
|
||
float angle = radians(130.0);
|
||
float2 dir = float2(cos(angle), sin(angle));
|
||
float2 side = float2(-sin(angle), cos(angle));
|
||
float2 edge = smoothstep(0.0, 0.07, uv) * smoothstep(0.0, 0.07, 1.0 - uv);
|
||
float edgeMask = edge.x * edge.y;
|
||
float wave = sin(dot(uv - 0.5, dir) * 27.2 + _Time.y * 2.15);
|
||
float volFxStrength = lerp(_DistortStrength * 0.55, _DistortStrength, saturate(_UVDistortFade)) * strength;
|
||
return uv + side * wave * volFxStrength * edgeMask;
|
||
}
|
||
|
||
// 仅模糊 RGB;alpha 由调用方取自中心采样,避免图集透明边被混进导致整图变透明(移动端常见)。
|
||
half3 BlurRgb(float2 uv, half strength)
|
||
{
|
||
float angle = radians(111.0);
|
||
float radial = distance(uv, 0.5) * 0.0026;
|
||
float stepSize = (0.014 + radial + _GaussianBlurOffset * 0.004) * strength;
|
||
float2 stepDir = normalize(float2(sin(angle), cos(angle)));
|
||
float2 stepUv = stepDir * stepSize;
|
||
|
||
#if defined(SHADER_API_MOBILE)
|
||
half3 rgb = SampleSprite(uv).rgb * 0.34;
|
||
rgb += SampleSprite(uv + stepUv).rgb * 0.33;
|
||
rgb += SampleSprite(uv - stepUv).rgb * 0.33;
|
||
#else
|
||
half3 rgb = SampleSprite(uv).rgb * 0.18;
|
||
rgb += SampleSprite(uv + stepUv).rgb * 0.15;
|
||
rgb += SampleSprite(uv - stepUv).rgb * 0.15;
|
||
rgb += SampleSprite(uv + stepUv * 2.0).rgb * 0.12;
|
||
rgb += SampleSprite(uv - stepUv * 2.0).rgb * 0.12;
|
||
rgb += SampleSprite(uv + stepUv * 3.0).rgb * 0.09;
|
||
rgb += SampleSprite(uv - stepUv * 3.0).rgb * 0.09;
|
||
rgb += SampleSprite(uv + stepUv * 4.0).rgb * 0.05;
|
||
rgb += SampleSprite(uv - stepUv * 4.0).rgb * 0.05;
|
||
#endif
|
||
return rgb;
|
||
}
|
||
|
||
half4 ChromaticSample(float2 uv, half4 source, half strength)
|
||
{
|
||
float aspect = max(0.001, abs(_MainTex_TexelSize.z) / max(1.0, abs(_MainTex_TexelSize.w)));
|
||
float angle = 0.496 * 6.2831853;
|
||
float2 dirA = float2(cos(angle) / aspect, sin(angle));
|
||
float2 dirB = -dirA;
|
||
float response = pow(saturate(strength), 0.75);
|
||
float mov = (0.07 + pow(distance(float2(0.5, 0.5), uv), 3.0) * 0.644) * response;
|
||
|
||
half4 colA = SampleSprite(uv + dirA * mov) * half4(1.0, 0.9888, 0.705, 1.0);
|
||
half4 colB = SampleSprite(uv + dirB * mov) * half4(0.705, 0.729, 1.0, 1.0);
|
||
half3 splitRgb = (colA.rgb + colB.rgb) * 0.5865;
|
||
half splitAlpha = max(max(colA.a, colB.a), source.a);
|
||
half4 splitCol = half4(splitRgb, splitAlpha);
|
||
half4 result = lerp(source, splitCol, 0.85 * response);
|
||
result.a = source.a;
|
||
return result;
|
||
}
|
||
|
||
half4 frag(Varyings input) : SV_Target
|
||
{
|
||
half clarity = saturate(_ClarityTuning);
|
||
half frequency = saturate(_FrequencyTuning);
|
||
half pixelate = pow(max(frequency, saturate(_PixelateFade)), 0.75);
|
||
half blur = pow(max(frequency, saturate(_GaussianBlurFade)), 0.75);
|
||
half distortion = pow(max(clarity, saturate(_UVDistortFade)), 0.85);
|
||
|
||
// 复刻旧版 SSU Directional Distortion 消融:_DirectionalDistortionFade 由 -15 拉到 0,
|
||
// 前沿自上而下扫过——一条细的发亮边+极轻微扰动+一点 glitch,其余按方向纯溶解替换为黑白。
|
||
// Span 越大,前沿在整段 fade 里铺得越开,溶解看起来越慢、发光带也越细。
|
||
float eraseNoise = ValueNoise(input.uv * _ColorEraseNoiseScale);
|
||
half eraseMask = saturate(
|
||
(input.uv.y * _ColorEraseSpan + _DirectionalDistortionFade + _ColorEraseBias
|
||
+ eraseNoise * _ColorEraseNoiseFactor) / max(_ColorEraseWidth, 0.001));
|
||
// 前沿带:mask 在 0~1 过渡处最亮;用指数把发光带收细
|
||
half eraseBand = saturate(eraseMask * (1.0 - eraseMask) * 4.0);
|
||
half glowBand = pow(eraseBand, _ColorEraseEdgeSharp);
|
||
|
||
float2 uv = input.uv;
|
||
// 前沿极轻微横向摆动(发丝级)
|
||
uv.x += sin(input.uv.y * 42.0 + _Time.y * 1.7) * _ColorEraseEdgeWobble * eraseBand;
|
||
// 一点 glitch:前沿附近偶发的水平错位切片
|
||
float glitchRow = floor(input.uv.y * 26.0);
|
||
float glitchRand = Hash21(float2(glitchRow, floor(_Time.y * 12.0)));
|
||
float glitchSlice = step(0.82, glitchRand) * (Hash21(float2(glitchRow, 7.3)) - 0.5) * 2.0;
|
||
uv.x += glitchSlice * 0.06 * _ColorEraseGlitch * eraseBand;
|
||
|
||
uv = DistortUv(uv, distortion);
|
||
float2 pixelUv = PixelSnap(uv, pixelate, _PixelatePixelDensity);
|
||
uv = lerp(uv, pixelUv, pixelate);
|
||
|
||
half4 sharp = SampleSprite(uv);
|
||
half3 rgb = lerp(sharp.rgb, BlurRgb(uv, blur), blur);
|
||
half4 col = half4(rgb, sharp.a);
|
||
col = ChromaticSample(uv, col, clarity);
|
||
if (eraseMask > 0.001)
|
||
{
|
||
// 已扫过区域:按方向纯溶解为黑白(等价旧版露出下层黑白图)
|
||
half eraseLuma = dot(col.rgb, half3(0.299, 0.587, 0.114));
|
||
half3 eraseGray = saturate(lerp(
|
||
half3(0.5, 0.5, 0.5),
|
||
half3(eraseLuma, eraseLuma, eraseLuma),
|
||
_ColorEraseContrast));
|
||
col.rgb = lerp(col.rgb, eraseGray, eraseMask);
|
||
}
|
||
// 前沿细的发亮边
|
||
col.rgb += glowBand * _ColorEraseEdgeGlow;
|
||
col.a *= input.color.a;
|
||
col.rgb *= input.color.rgb;
|
||
return col;
|
||
}
|
||
ENDHLSL
|
||
}
|
||
}
|
||
}
|