#version 100 precision mediump float; uniform float u_time; uniform vec2 u_resolution; uniform vec2 u_mouse; uniform sampler2D u_backbuffer; // Fluid Parameters #define DT 0.15 #define VISCOSITY 0.99 #define FADE 0.995 // Pseudo-random float rand(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } void main() { vec2 pixel = 1.0 / u_resolution; vec2 uv = gl_FragCoord.xy / u_resolution; // 1. Read current state (Vel, Density) if (u_time < 0.5 || u_resolution.x < 1.0) { gl_FragColor = vec4(0.5, 0.5, 0.0, 1.0); return; } vec4 state = texture2D(u_backbuffer, uv); vec2 vel = state.xy; // velocity range [-1, 1]? we store as [0,1]. Need remap. // Actually simpler to store raw flow in 0..1 range whre 0.5 is 0 velocity. // Let's assume 0.5 is 0. vec2 v = (vel - 0.5) * 2.0; float density = state.z; // 2. Advection (move state by velocity) // We look *back* along velocity to find where the current content came from. vec2 coord = uv - v * pixel * 5.0; // Scale velocity effect vec4 advected = texture2D(u_backbuffer, coord); vec2 new_v = (advected.xy - 0.5) * 2.0; float new_d = advected.z; // 3. Mouse Interaction (Splat) float d = distance(gl_FragCoord.xy, u_mouse); if (d < 30.0 && u_mouse.x > 0.0) { // Add density new_d += 0.5; // Add velocity (push away from mouse or just random?) // Ideally we need mouse delta (velocity). u_mouse is just pos. // We can just add a radial force or flow? // Let's just add some noise/movement new_v += vec2(rand(uv + u_time) - 0.5, rand(uv + u_time + 1.0) - 0.5) * 1.0; } // 4. Decay (Viscosity/Dissipation) new_v *= VISCOSITY; new_d *= FADE; // Remap velocity back to 0..1 vel = new_v * 0.5 + 0.5; gl_FragColor = vec4(vel, new_d, 1.0); }