// shaders/dialog_wave_core.frag #version 300 es precision highp float; #include uniform vec2 u_resolution; // setFloat(0, w) & (1, h) uniform float u_time; // setFloat(2, t) uniform float u_amp; // setFloat(3, amp) —— 建议传音量 RMS out vec4 fragColor; // ─────────── Noise Helpers ─────────── float hash(vec2 p){return fract(sin(dot(p,vec2(127.1,311.7)))*43758.545);} 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)),u.x), mix(hash(i+vec2(0,1)), hash(i+vec2(1,1)),u.x),u.y); } float fbm(vec2 p){ float a=.5, v=0.; mat2 m=mat2(1.6,1.2,-1.2,1.6); for(int i=0;i<3;i++){ v+=a*noise(p); p=m*p*1.6; a*=.55; } return v; } // ─────────── Palette ─────────── vec3 palette(float t){ vec3 deep = vec3(0.05,0.10,0.30); // 靛蓝 vec3 mid = vec3(0.15,0.00,0.55); // 暗紫 vec3 glow = vec3(0.00,0.60,1.00); // 电蓝 return mix(deep, mix(mid, glow, t*t), t); // t² 让亮部偏蓝 } void main(){ // ① 归一化到 [-1,1](保持比例) vec2 uv = (FlutterFragCoord().xy / u_resolution)*2.0 - 1.0; uv.x *= u_resolution.x / u_resolution.y; float r = length(uv); // 半径 0~√2 // ② “呼吸”——音量驱动整体缩放(amp ∈ [0,1]) float breath = 1.0 - (.08 + .05*u_amp) * sin(u_time*1.5); vec2 p = uv / breath; // 越大越收缩 p *= 3.0; // 纹理密度 p += u_time * 0.35; // 缓慢横移 // ③ 旋转扭曲 + fBm 云雾 float angle = atan(p.y,p.x) + 0.25*r; // 小角度漩涡 float radius = length(p); vec2 q = vec2(cos(angle),sin(angle))*radius; float n = fbm(q) * .7 + fbm(q*2.0) * .3; n = smoothstep(.3,.7,n); vec3 col = palette(n); // ④ 亮度脉冲(随 amp 加强) col += (.05 + .08*u_amp) * sin(u_time*2.0 + n*6.0); // ⑤ 外环光晕(amp 加深) float halo = smoothstep(.55,.05,r) * (0.15 + 0.5*u_amp); col += halo; // ⑥ 羽化:可见区半径 ≈ 0.96 float alpha = step(r, 0.75); fragColor = vec4(col, alpha); }