194 lines
6.8 KiB
GLSL
194 lines
6.8 KiB
GLSL
#define TURBULENCE_SAMPLER iChannel3
|
|
#define CONFINEMENT_SAMPLER iChannel2
|
|
#define POISSON_SAMPLER iChannel1
|
|
#define VELOCITY_SAMPLER iChannel0
|
|
|
|
#define V(d) texture(TURBULENCE_SAMPLER, fract(uv+(d+0.))).xy
|
|
|
|
vec2 gaussian_turbulence(vec2 uv) {
|
|
vec2 texel = 1.0/iResolution.xy;
|
|
vec4 t = vec4(texel, -texel.y, 0);
|
|
|
|
vec2 d = V( t.ww); vec2 d_n = V( t.wy); vec2 d_e = V( t.xw);
|
|
vec2 d_s = V( t.wz); vec2 d_w = V(-t.xw); vec2 d_nw = V(-t.xz);
|
|
vec2 d_sw = V(-t.xy); vec2 d_ne = V( t.xy); vec2 d_se = V( t.xz);
|
|
|
|
return 0.25 * d + 0.125 * (d_e + d_w + d_n + d_s) + 0.0625 * (d_ne + d_nw + d_se + d_sw);
|
|
}
|
|
|
|
#define C(d) texture(CONFINEMENT_SAMPLER, fract(uv+(d+0.))).xy
|
|
|
|
vec2 gaussian_confinement(vec2 uv) {
|
|
vec2 texel = 1.0/iResolution.xy;
|
|
vec4 t = vec4(texel, -texel.y, 0);
|
|
|
|
vec2 d = C( t.ww); vec2 d_n = C( t.wy); vec2 d_e = C( t.xw);
|
|
vec2 d_s = C( t.wz); vec2 d_w = C(-t.xw); vec2 d_nw = C(-t.xz);
|
|
vec2 d_sw = C(-t.xy); vec2 d_ne = C( t.xy); vec2 d_se = C( t.xz);
|
|
|
|
return 0.25 * d + 0.125 * (d_e + d_w + d_n + d_s) + 0.0625 * (d_ne + d_nw + d_se + d_sw);
|
|
}
|
|
|
|
#define D(d) texture(POISSON_SAMPLER, fract(uv+d)).x
|
|
|
|
vec2 diff(vec2 uv) {
|
|
vec2 texel = 1.0/iResolution.xy;
|
|
vec4 t = vec4(texel, -texel.y, 0);
|
|
|
|
float d = D( t.ww); float d_n = D( t.wy); float d_e = D( t.xw);
|
|
float d_s = D( t.wz); float d_w = D(-t.xw); float d_nw = D(-t.xz);
|
|
float d_sw = D(-t.xy); float d_ne = D( t.xy); float d_se = D( t.xz);
|
|
|
|
return vec2(
|
|
0.5 * (d_e - d_w) + 0.25 * (d_ne - d_nw + d_se - d_sw),
|
|
0.5 * (d_n - d_s) + 0.25 * (d_ne + d_nw - d_se - d_sw)
|
|
);
|
|
}
|
|
|
|
#define N(d) texture(VELOCITY_SAMPLER, fract(uv+(d+0.)))
|
|
|
|
vec4 gaussian_velocity(vec2 uv) {
|
|
vec2 texel = 1.0/iResolution.xy;
|
|
vec4 t = vec4(texel, -texel.y, 0);
|
|
|
|
vec4 d = N( t.ww); vec4 d_n = N( t.wy); vec4 d_e = N( t.xw);
|
|
vec4 d_s = N( t.wz); vec4 d_w = N(-t.xw); vec4 d_nw = N(-t.xz);
|
|
vec4 d_sw = N(-t.xy); vec4 d_ne = N( t.xy); vec4 d_se = N( t.xz);
|
|
|
|
return 0.25 * d + 0.125 * (d_e + d_w + d_n + d_s) + 0.0625 * (d_ne + d_nw + d_se + d_sw);
|
|
}
|
|
|
|
vec2 vector_laplacian(vec2 uv) {
|
|
const float _K0 = -20.0/6.0, _K1 = 4.0/6.0, _K2 = 1.0/6.0;
|
|
vec2 texel = 1.0/iResolution.xy;
|
|
vec4 t = vec4(texel, -texel.y, 0);
|
|
|
|
vec4 d = N( t.ww); vec4 d_n = N( t.wy); vec4 d_e = N( t.xw);
|
|
vec4 d_s = N( t.wz); vec4 d_w = N(-t.xw); vec4 d_nw = N(-t.xz);
|
|
vec4 d_sw = N(-t.xy); vec4 d_ne = N( t.xy); vec4 d_se = N( t.xz);
|
|
|
|
return (_K0 * d + _K1 * (d_e + d_w + d_n + d_s) + _K2 * (d_ne + d_nw + d_se + d_sw)).xy;
|
|
}
|
|
|
|
|
|
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
|
{
|
|
vec2 uv = fragCoord/iResolution.xy;
|
|
vec2 tx = 1.0/iResolution.xy;
|
|
|
|
|
|
vec2 turb, confine, div, delta_v, offset, lapl = vec2(0);
|
|
vec4 vel, adv = vec4(0);
|
|
vec4 init = N();
|
|
|
|
#ifdef RECALCULATE_OFFSET
|
|
for (int i = 0; i < ADVECTION_STEPS; i++) {
|
|
#ifdef BLUR_TURBULENCE
|
|
turb = gaussian_turbulence(uv + tx * offset);
|
|
#else
|
|
turb = V(tx * offset);
|
|
#endif
|
|
|
|
#ifdef BLUR_CONFINEMENT
|
|
confine = gaussian_confinement(uv + tx * offset);
|
|
#else
|
|
confine = C(tx * offset);
|
|
#endif
|
|
|
|
#ifdef BLUR_VELOCITY
|
|
vel = gaussian_velocity(uv + tx * offset);
|
|
#else
|
|
vel = N(tx * offset);
|
|
#endif
|
|
|
|
// an alternative, but seems to give less smooth results:
|
|
// offset += (1.0 / float(ADVECTION_STEPS)) * ...
|
|
offset = (float(i+1) / float(ADVECTION_STEPS)) * - ADVECTION_SCALE * (ADVECTION_VELOCITY * vel.xy + ADVECTION_TURBULENCE * turb - ADVECTION_CONFINEMENT * confine + ADVECTION_DIVERGENCE * div);
|
|
|
|
div = diff(uv + tx * DIVERGENCE_LOOKAHEAD * offset);
|
|
|
|
lapl = vector_laplacian(uv + tx * LAPLACIAN_LOOKAHEAD * offset);
|
|
|
|
adv += N(tx * offset);
|
|
|
|
delta_v += VELOCITY_LAPLACIAN * lapl + VELOCITY_TURBULENCE * turb + VELOCITY_CONFINEMENT * confine - DAMPING * vel.xy - DIVERGENCE_MINIMIZATION * div;
|
|
}
|
|
adv /= float(ADVECTION_STEPS);
|
|
delta_v /= float(ADVECTION_STEPS);
|
|
#else
|
|
#ifdef BLUR_TURBULENCE
|
|
turb = gaussian_turbulence(uv);
|
|
#else
|
|
turb = V();
|
|
#endif
|
|
|
|
#ifdef BLUR_CONFINEMENT
|
|
confine = gaussian_confinement(uv);
|
|
#else
|
|
confine = C();
|
|
#endif
|
|
|
|
#ifdef BLUR_VELOCITY
|
|
vel = gaussian_velocity(uv);
|
|
#else
|
|
vel = N();
|
|
#endif
|
|
|
|
offset = - ADVECTION_SCALE * (ADVECTION_VELOCITY * vel.xy + ADVECTION_TURBULENCE * turb - ADVECTION_CONFINEMENT * confine + ADVECTION_DIVERGENCE * div);
|
|
|
|
div = diff(uv + tx * DIVERGENCE_LOOKAHEAD * offset);
|
|
|
|
lapl = vector_laplacian(uv + tx * LAPLACIAN_LOOKAHEAD * offset);
|
|
|
|
delta_v += VELOCITY_LAPLACIAN * lapl + VELOCITY_TURBULENCE * turb + VELOCITY_CONFINEMENT * confine - DAMPING * vel.xy - DIVERGENCE_MINIMIZATION * div;
|
|
|
|
for (int i = 0; i < ADVECTION_STEPS; i++) {
|
|
adv += N((float(i+1) / float(ADVECTION_STEPS)) * tx * offset);
|
|
}
|
|
adv /= float(ADVECTION_STEPS);
|
|
#endif
|
|
|
|
|
|
|
|
// define a pump, either at the center of the screen,
|
|
// or alternating at the sides of the screen.
|
|
vec2 pq = 2.0*(uv*2.0-1.0) * vec2(1,tx.x/tx.y);
|
|
#ifdef CENTER_PUMP
|
|
vec2 pump = sin(PUMP_CYCLE*iTime)*PUMP_SCALE*pq.xy / (dot(pq,pq)+0.01);
|
|
#else
|
|
vec2 pump = vec2(0);
|
|
#define AMP 15.0
|
|
#define SCL -50.0
|
|
float uvy0 = exp(SCL*pow(pq.y,2.0));
|
|
float uvx0 = exp(SCL*pow(uv.x,2.0));
|
|
pump += -AMP*vec2(max(0.0,cos(PUMP_CYCLE*iTime))*PUMP_SCALE*uvx0*uvy0,0);
|
|
|
|
float uvy1 = exp(SCL*pow(pq.y,2.0));
|
|
float uvx1 = exp(SCL*pow(1.0 - uv.x,2.0));
|
|
pump += AMP*vec2(max(0.0,cos(PUMP_CYCLE*iTime + 3.1416))*PUMP_SCALE*uvx1*uvy1,0);
|
|
|
|
float uvy2 = exp(SCL*pow(pq.x,2.0));
|
|
float uvx2 = exp(SCL*pow(uv.y,2.0));
|
|
pump += -AMP*vec2(0,max(0.0,sin(PUMP_CYCLE*iTime))*PUMP_SCALE*uvx2*uvy2);
|
|
|
|
float uvy3 = exp(SCL*pow(pq.x,2.0));
|
|
float uvx3 = exp(SCL*pow(1.0 - uv.y,2.0));
|
|
pump += AMP*vec2(0,max(0.0,sin(PUMP_CYCLE*iTime + 3.1416))*PUMP_SCALE*uvx3*uvy3);
|
|
#endif
|
|
|
|
fragColor = mix(adv + vec4(VELOCITY_SCALE * (delta_v + pump), offset), init, UPDATE_SMOOTHING);
|
|
|
|
if (iMouse.z > 0.0) {
|
|
vec4 mouseUV = iMouse / iResolution.xyxy;
|
|
vec2 delta = normz(mouseUV.zw - mouseUV.xy);
|
|
vec2 md = (mouseUV.xy - uv) * vec2(1.0,tx.x/tx.y);
|
|
float amp = exp(max(-12.0,-dot(md,md)/MOUSE_RADIUS));
|
|
fragColor.xy += VELOCITY_SCALE * MOUSE_AMP * clamp(amp * delta,-1.0,1.0);
|
|
}
|
|
|
|
// Adding a very small amount of noise on init fixes subtle numerical precision blowup problems
|
|
if (iFrame==0) fragColor=1e-6*rand4(fragCoord, iResolution.xy, iFrame);
|
|
}
|