computeTimestep = regl({
frag: `
precision highp float;
varying vec2 vUV;
uniform sampler2D uSrc;
uniform vec2 uResolution, dx;
uniform float dt, decay, h, g;
float tanh (float x) {
// Avoid overflow resulting from exp getting big even though tanh approaches 1
if (abs(x) > 10.0) return sign(x) * (1.0 - 2.0 * exp(-2.0 * x));
float e2x = exp(x);
return (e2x - 1.0) / (e2x + 1.0);
}
vec2 cexp(vec2 z) {
return vec2(cos(z.y), sin(z.y)) * exp(z.x);
}
vec2 cmul (vec2 a, vec2 b) {
return vec2(a.x * b.x - a.y * b. y,a.y * b.x + a.x * b.y);
}
${glslWavenumber}
${dispersionRelationGLSL}
void main () {
vec2 yfft = texture2D(uSrc, vUV).xy;
vec2 kxy = wavenumber(uResolution, dx);
float kx2ky2 = dot(kxy, kxy);
float k = sqrt(kx2ky2);
// Evaluate the dispersion relation defined at the top
float w = omega(k, g, h);
// Construct the complex phasor. This is wasteful to multiply it out
// like this without simplifying, but compared to the FFT, it's nothing.
vec2 phasor = cexp(cmul(vec2(0, 1), vec2(dt * w, 0)));
gl_FragColor.xy = cmul(yfft, phasor) * decay;
}`,
uniforms: {
uSrc: regl.prop('src'),
uResolution: forwardFFT[0].resolution
}
})