1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| Shader "Custom/URP/SpectrumVisualizer" { Properties { _SpectrumTex ("Spectrum Texture", 2D) = "black" {} _BarColor ("Bar Color", Color) = (0.2, 0.8, 1.0, 1.0) _PeakColor ("Peak Color", Color) = (1.0, 0.3, 0.1, 1.0) _BackgroundColor("Background Color", Color) = (0.05, 0.05, 0.1, 1.0) _BarCount ("Bar Count", Float) = 64 _GlowStrength ("Glow Strength", Range(0, 3)) = 1.0 _PeakThreshold ("Peak Threshold", Range(0.6, 1)) = 0.85 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" } Pass { Tags { "LightMode"="UniversalForward" } HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionHCS : SV_POSITION; float2 uv : TEXCOORD0; };
TEXTURE2D(_SpectrumTex); SAMPLER(sampler_SpectrumTex);
CBUFFER_START(UnityPerMaterial) float4 _BarColor; float4 _PeakColor; float4 _BackgroundColor; float _BarCount; float _GlowStrength; float _PeakThreshold; CBUFFER_END
Varyings vert(Attributes IN) { Varyings OUT; OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); OUT.uv = IN.uv; return OUT; }
half4 frag(Varyings IN) : SV_Target { float2 uv = IN.uv;
// 确定当前像素属于哪个频段 float barIndex = floor(uv.x * _BarCount); float barLocalX = frac(uv.x * _BarCount); // [0,1] 在单个条内
// 采样该频段的频谱强度 float bandU = (barIndex + 0.5) / _BarCount; float spectrum = SAMPLE_TEXTURE2D(_SpectrumTex, sampler_SpectrumTex, float2(bandU, 0.5)).r;
// 条的宽度(中间 80% 是颜色,两侧 10% 是间隙) float barGap = 0.1; float inBar = step(barGap, barLocalX) * step(barLocalX, 1.0 - barGap);
// 柱状图高度判断:当前 Y 是否在频谱强度以下 float belowBar = step(uv.y, spectrum); float inBarArea = inBar * belowBar;
// 峰值高亮:接近当前高度顶部的部分用 PeakColor float nearPeak = smoothstep(spectrum - 0.05, spectrum, uv.y) * smoothstep(spectrum + 0.01, spectrum, uv.y) * inBar * step(_PeakThreshold, spectrum);
// 颜色计算 // 高度渐变:底部偏蓝,顶部偏红 float heightRatio = uv.y / max(spectrum, 0.001); half3 barColor = lerp(_BarColor.rgb, _PeakColor.rgb, heightRatio * heightRatio);
// 发光效果(条的侧边发光) float glowDist = abs(barLocalX - 0.5) * 2.0; // 0=中心, 1=边缘 float glow = exp(-glowDist * 5.0) * spectrum * _GlowStrength;
// 合成 half3 finalColor = _BackgroundColor.rgb; finalColor = lerp(finalColor, barColor, inBarArea); finalColor = lerp(finalColor, _PeakColor.rgb, nearPeak); finalColor += barColor * glow * inBar; // 叠加发光
// 动态脉冲:随 _BeatIntensity 全局闪烁 float beatIntensity = _GlobalBeatIntensity; // 由 C# 设置 finalColor += barColor * beatIntensity * 0.3 * inBarArea;
return half4(finalColor, 1.0); } ENDHLSL } } }
|