Files
aibis-dream/Assets/Shader/Shader/MemoryTuningSprite.shader
T

294 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}
}