feat(peipei-eye): 新增 EyeUnifiedSprite 着色器与材质

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-30 12:54:08 +08:00
co-authored by Cursor
parent db73b64980
commit 4f6f5a1ae9
4 changed files with 290 additions and 0 deletions
@@ -0,0 +1,55 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: EyeUnifiedSprite
m_Shader: {fileID: 4800000, guid: f7f1f0a7430f4f44fa1d7af89e1e013f, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _AsciiAmount: 0
- _AsciiCellSize: 64
- _BlurAmount: 0.627
- _BlurSize: 0.00279
- _ColorReveal: 0
- _DistortAmount: 0
- _DreamAmount: 0
- _GlitchAmount: 0
- _GrayAmount: 1
- _HsvSaturation: 1
- _HsvShift: 0
- _MemoryAmount: 0
- _PixelSteps: 8
- _RevealNoise: 0.08
- _RevealRotation: 0
- _RevealWidth: 0.18
- _RoundWaveStrength: 0
- _ScanlineAmount: 0
- _SpriteFade: 1
- _WrongColorAmount: 0
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _WrongColor: {r: 1, g: 0.16, b: 0.08, a: 1}
m_BuildTextureStacks: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e8f4a2b1c3d5476980abcdef01234567
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+217
View File
@@ -0,0 +1,217 @@
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));
}
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 * 240.0);
float tear = (hash21(float2(glitchRow, floor(_Time.y * 18.0))) - 0.5) * _GlitchAmount * 0.04;
distortedUv.x += tear;
float noise = hash21(floor(uv * 42.0) + floor(_Time.y * 16.0));
distortedUv += (noise - 0.5) * _DistortAmount;
float2 blur = _MainTex_TexelSize.xy + _BlurSize;
fixed4 col = tex2D(_MainTex, distortedUv);
fixed4 blurCol = col;
blurCol += tex2D(_MainTex, distortedUv + float2(blur.x, 0));
blurCol += tex2D(_MainTex, distortedUv - float2(blur.x, 0));
blurCol += tex2D(_MainTex, distortedUv + float2(0, blur.y));
blurCol += tex2D(_MainTex, distortedUv - float2(0, blur.y));
blurCol *= 0.2;
return lerp(col, blurCol, _BlurAmount);
}
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);
// Sweep only applies while the target is still desaturated; full color when _GrayAmount reaches 0.
float grayMix = saturate(max(_GrayAmount, (1.0 - revealMask) * _GrayAmount));
col.rgb = lerp(col.rgb, gray.xxx, grayMix);
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.006;
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"
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f7f1f0a7430f4f44fa1d7af89e1e013f
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
shaderImporterVersion: 1
userData:
assetBundleName:
assetBundleVariant: