// shaders/mic_flow.frag #version 300 es precision highp float; #include uniform vec2 u_resolution; // 由 FlutterShaders 自动注入 uniform float u_time; // AnimationController -> setFloat(2, ...) uniform float u_amp; // 可选:实时音量 (0~1),建议 setFloat(3, rms) out vec4 fragColor; // ——— 经典 hash & noise ——— float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1,311.7))) * 43758.5453123); } float noise(vec2 p) { vec2 i = floor(p), f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); return mix(mix(hash(i), hash(i + vec2(1.0,0.0)), u.x), mix(hash(i + vec2(0.0,1.0)), hash(i + vec2(1.0,1.0)), u.x), u.y); } // fBm:3-oct & 微 Domain Warp float fbm(vec2 p) { float sum = 0.0, amp = 0.5; mat2 m = mat2(1.6, 1.2, -1.2, 1.6); // 轻微旋转,防止轴纹 for (int i = 0; i < 3; ++i) { sum += amp * noise(p); p = m * p * 1.6; amp *= 0.55; } return sum; } // 调色盘:深蓝 → 云白 vec3 palette(float t) { vec3 deep = vec3(0.08, 0.42, 1.00); vec3 light= vec3(0.94, 0.98, 1.00); return mix(deep, light, t); } void main() { // 0‒1 -> -0.5‒0.5,保持圆心在 Shader 0,0 vec2 uv = (FlutterFragCoord().xy / u_resolution) - .5; // 呼吸缩放(≈ 0.92‒1.08) float breath = 1.0 + (0.05 + 0.03 * u_amp) * sin(u_time * 1.4); vec2 p = uv * 3.2 / breath; // 越大云越细腻 p += u_time * 0.35; // 横向漂移 // 多层 fBm + 微距 domain-warp float n = fbm(p) * 0.65 + fbm(p * 2.0 + vec2(5.2)) * 0.35; float t = smoothstep(0.32, 0.68, n); // 阈值决定明暗分布 vec3 col= palette(t); // ─── 边缘羽化 ─── float r = length(uv); // 半径 0-0.5 float alpha = smoothstep(0.48, 0.46, r); // 92% 处开始衰减 // 轻量亮度脉冲:让中心更有“呼吸”感 float pulse = 0.04 * sin(u_time * 2.0 + n * 4.0); col += pulse; fragColor = vec4(col, alpha); }