Drifting banks lit from behind, with real depth.
GLSL fragment shader
The effect's own code. The uniforms and helpers above it — uTex, uFeedback, the depth proxy, the frame ring, depthAt(), timeAt() — are the same header every Ether-MOSH shader opens with, and are documented once on the registry rather than reprinted on all 143 pages.
void main(){ // Layered drifting banks with light scattering through them, rather than // one flat noise tint — the old version veiled uniformly and disappeared // under any other effect. float t = uTime * 0.06; float n1 = noise(vUv * vec2(3.0, 1.6) + vec2(t, t * 0.3)); float n2 = noise(vUv * vec2(7.0, 3.2) - vec2(t * 1.7, t * 0.4)); float bank = n1 * 0.65 + n2 * 0.35; // Thickest low in the frame, thinning with height. float depth = smoothstep(1.05, -0.15, vUv.y); float density = clamp(bank * depth * uAmount * 2.1, 0.0, 1.0); // Refract through the fog so it displaces as well as tints; a pure tint is // what made it interchangeable with grain and haze. vec2 uv = vUv + vec2(n1 - 0.5, n2 - 0.5) * density * 0.045; vec4 cTex = texture2D(uTex, uv); vec3 c = cTex.rgb; // Scattering: the bank glows where the frame behind it is bright. float glow = max(0.0, dot(discBlur(vUv, 16.0), vec3(0.299, 0.587, 0.114)) - 0.32); vec3 haze = mix(hsv2rgb(vec3(uHue, 0.35, 0.72)), vec3(1.0, 0.95, 0.86), clamp(glow * 1.8, 0.0, 1.0)); // The haze is atmosphere sitting in front of the subject, not a // separate opaque object, so it shouldn't punch new holes in — or fill // in — a transparent source's own silhouette. Alpha rides the // refracted uv (the fog's own displacement), unaffected by the color mix. gl_FragColor = vec4(mix(c, haze, density), cTex.a); }