Files
aibis-dream/Assets/Render/EyeUnifiedSprite.shader

251 lines
10 KiB
Plaintext

Shader "AIBIS/EyeUnifiedSprite"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1, 1, 1, 1)
_SpriteFade ("Sprite Fade", Range(0, 1)) = 1
[Header(Eye State)]
_ColorReveal ("Color Reveal", Range(0, 1)) = 1
_GrayAmount ("Gray Amount", Range(0, 1)) = 0
_RevealWidth ("Reveal Width", Range(0.001, 1)) = 0.18
_RevealRotation ("Reveal Rotation", Range(0, 6.28318)) = 0
_RevealNoise ("Reveal Noise", Range(0, 1)) = 0.08
_WrongColor ("Wrong Color", Color) = (1, 0.16, 0.08, 1)
_WrongColorAmount ("Wrong Color Amount", Range(0, 1)) = 0
[Header(Texture Effects)]
_BlurAmount ("Blur Amount", Range(0, 1)) = 0
_BlurSize ("Blur Size", Range(0, 0.02)) = 0.004
_DistortAmount ("Distort Amount", Range(0, 0.08)) = 0
_GlitchAmount ("Glitch Amount", Range(0, 1)) = 0
_HsvShift ("Hue Shift", Range(0, 360)) = 0
_HsvSaturation ("HSV Saturation", Range(0, 2)) = 1
_RoundWaveStrength ("Round Wave Strength", Range(0, 1)) = 0
[Header(UF Sprite FX)]
_AsciiAmount ("Ascii Amount", Range(0, 1)) = 0
_AsciiCellSize ("Ascii Cell Size", Range(12, 160)) = 64
_DreamAmount ("Dream Amount", Range(0, 1)) = 0
_MemoryAmount ("Memory Amount", Range(0, 1)) = 0
_ScanlineAmount ("Scanline Amount", Range(0, 1)) = 0
_PixelSteps ("Posterize Steps", Range(2, 32)) = 8
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Cull Off
Lighting Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_TexelSize;
fixed4 _Color;
float _SpriteFade;
float _ColorReveal;
float _GrayAmount;
float _RevealWidth;
float _RevealRotation;
float _RevealNoise;
fixed4 _WrongColor;
float _WrongColorAmount;
float _BlurAmount;
float _BlurSize;
float _DistortAmount;
float _GlitchAmount;
float _HsvShift;
float _HsvSaturation;
float _RoundWaveStrength;
float _AsciiAmount;
float _AsciiCellSize;
float _DreamAmount;
float _MemoryAmount;
float _ScanlineAmount;
float _PixelSteps;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color = v.color * _Color;
o.uv = v.uv;
o.screenPos = ComputeScreenPos(o.vertex);
return o;
}
float hash21(float2 p)
{
p = frac(p * float2(123.34, 456.21));
p += dot(p, p + 45.32);
return frac(p.x * p.y);
}
float3 hueShift(float3 color, float shiftDegrees)
{
float angle = shiftDegrees * 0.01745329252;
float s = sin(angle);
float c = cos(angle);
float3 weights = float3(0.299, 0.587, 0.114);
float3x3 mat = float3x3(
weights.x + (1 - weights.x) * c + 0.168 * s, weights.y - weights.y * c + 0.330 * s, weights.z - weights.z * c - 0.497 * s,
weights.x - weights.x * c - 0.328 * s, weights.y + (1 - weights.y) * c + 0.035 * s, weights.z - weights.z * c + 0.292 * s,
weights.x - weights.x * c + 1.250 * s, weights.y - weights.y * c - 1.050 * s, weights.z + (1 - weights.z) * c - 0.203 * s
);
return saturate(mul(mat, color));
}
half4 sampleMainTex(float2 uv)
{
return tex2D(_MainTex, saturate(uv));
}
half3 GaussianBlurRgb(float2 uv, float stepSize)
{
float angle = 1.937315; // ~111 deg, matches MemoryTuningSprite
float2 stepDir = float2(sin(angle), cos(angle));
float2 stepUv = stepDir * stepSize;
#if defined(SHADER_API_MOBILE)
half3 rgb = sampleMainTex(uv).rgb * 0.34;
rgb += sampleMainTex(uv + stepUv).rgb * 0.33;
rgb += sampleMainTex(uv - stepUv).rgb * 0.33;
#else
half3 rgb = sampleMainTex(uv).rgb * 0.18;
rgb += sampleMainTex(uv + stepUv * 1.0).rgb * 0.15;
rgb += sampleMainTex(uv - stepUv * 1.0).rgb * 0.15;
rgb += sampleMainTex(uv + stepUv * 2.0).rgb * 0.12;
rgb += sampleMainTex(uv - stepUv * 2.0).rgb * 0.12;
rgb += sampleMainTex(uv + stepUv * 3.0).rgb * 0.09;
rgb += sampleMainTex(uv - stepUv * 3.0).rgb * 0.09;
rgb += sampleMainTex(uv + stepUv * 4.0).rgb * 0.05;
rgb += sampleMainTex(uv - stepUv * 4.0).rgb * 0.05;
#endif
return rgb;
}
fixed4 sampleSprite(float2 uv, float2 screenUv)
{
float2 distortedUv = uv;
float2 centered = uv - 0.5;
float ripple = sin((length(centered) * 42.0) - (_Time.y * 8.0));
distortedUv += centered * ripple * _RoundWaveStrength * 0.018;
float glitchRow = floor(screenUv.y * 360.0);
float tear = (hash21(float2(glitchRow, floor(_Time.y * 20.0))) - 0.5) * _GlitchAmount * 0.012;
distortedUv.x += tear;
float noise = hash21(floor(uv * 42.0) + floor(_Time.y * 16.0));
distortedUv += (noise - 0.5) * _DistortAmount;
float2 texel = max(abs(_MainTex_TexelSize.xy), float2(1e-5, 1e-5));
float stepSize = length(texel) + _BlurSize;
fixed4 col = sampleMainTex(distortedUv);
fixed3 blurredRgb = GaussianBlurRgb(distortedUv, stepSize);
float blurStrength = pow(saturate(_BlurAmount), 0.75);
col.rgb = lerp(col.rgb, blurredRgb, blurStrength);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
float2 screenUv = i.screenPos.xy / i.screenPos.w;
float2 uv = i.uv;
fixed4 col = sampleSprite(uv, screenUv) * i.color;
float gray = dot(col.rgb, float3(0.299, 0.587, 0.114));
float2 revealDir = float2(cos(_RevealRotation), sin(_RevealRotation));
float directional = dot(uv - 0.5, revealDir) + 0.5;
float dissolveNoise = (hash21(floor(uv * 96.0)) - 0.5) * _RevealNoise;
float revealMask = smoothstep(_ColorReveal - _RevealWidth, _ColorReveal + _RevealWidth, directional + dissolveNoise);
// Idle (_GrayAmount=1) or fully colored (_GrayAmount=0): uniform mix; sweep only mid-transition.
float inSweep = step(0.001, 1.0 - _GrayAmount) * step(0.001, _GrayAmount);
float sweepFactor = lerp(1.0, (1.0 - revealMask), inSweep);
float grayMix = saturate(_GrayAmount * sweepFactor);
col.rgb = lerp(col.rgb, gray.xxx, grayMix);
float sweepEdge = 1.0 - abs(directional + dissolveNoise - _ColorReveal);
float edgeGlow = smoothstep(_RevealWidth * 0.15, _RevealWidth * 0.55, sweepEdge) * inSweep * _GrayAmount * (1.0 - revealMask);
col.rgb += float3(1.0, 0.92, 0.78) * edgeGlow * 0.35;
col.rgb = lerp(col.rgb, _WrongColor.rgb * max(gray, 0.08), _WrongColorAmount * _WrongColor.a);
col.rgb = hueShift(col.rgb, _HsvShift);
float shiftedGray = dot(col.rgb, float3(0.299, 0.587, 0.114));
col.rgb = lerp(shiftedGray.xxx, col.rgb, _HsvSaturation);
float posterize = max(2.0, _PixelSteps);
float3 posterized = floor(col.rgb * posterize) / posterize;
col.rgb = lerp(col.rgb, posterized, saturate(_DreamAmount + _MemoryAmount * 0.5));
float scan = sin(screenUv.y * 900.0 + _Time.y * 18.0) * 0.5 + 0.5;
float scanAmount = saturate(_ScanlineAmount + _MemoryAmount * 0.5);
col.rgb *= lerp(1.0, 0.68 + scan * 0.38, scanAmount);
float2 asciiGrid = floor(screenUv * _AsciiCellSize);
float asciiNoise = hash21(asciiGrid + floor(_Time.y * 8.0));
float asciiShape = step(0.48, frac(screenUv.x * _AsciiCellSize * 2.0)) * step(0.25 + asciiNoise * 0.35, frac(screenUv.y * _AsciiCellSize));
float asciiBrightness = step(asciiNoise, gray);
float ascii = asciiShape * asciiBrightness;
col.rgb = lerp(col.rgb, ascii.xxx * lerp(float3(1, 1, 1), col.rgb, 0.35), _AsciiAmount);
float chromaOffset = _GlitchAmount * 0.004;
if (chromaOffset > 0.0001)
{
float red = tex2D(_MainTex, uv + float2(chromaOffset, 0)).r;
float blue = tex2D(_MainTex, uv - float2(chromaOffset, 0)).b;
col.r = lerp(col.r, red, _GlitchAmount);
col.b = lerp(col.b, blue, _GlitchAmount);
}
col.a *= _SpriteFade;
return col;
}
ENDCG
}
}
Fallback "Sprites/Default"
}