/* Created by Cornus Ammonis (2019) Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. */ /* This is a mipmap-based approach to multiscale fluid dynamics. Check the Common tab for lots of configurable parameters. Click to interact with your mouse. I'd recommend turning off the "pump" by setting PUMP_SCALE to 0.0 on line 113 of the Common tab to play around with just mouse interaction. Buffer B is a multiscale method for computing turbulence along the lines of the Large Eddy Simulation method; multiscale curl is also computed in Buffer B, to be passed along to Buffer C. Buffer C is a fairly conventional Vorticity Confinement method, also multiscale, using the curl computed in Buffer B. It probably makes more sense to compute each curl scale separately before accumulating, but for the sake of efficiency and simplicity (a larger kernel would be required), I haven't done that here. Buffer D is a multiscale Poisson solver, which converges rapidly but not to an exact solution - this nonetheless works well for the purposes of divergence minimization since we only need the gradient, with allowances for the choice of scale weighting. Buffer A computes subsampled advection and velocity update steps, sampling from Buffers B, C, and D with a variety of smoothing options. There are a number of options included to make this run faster. Using mipmaps in this way has a variety of advantages: 1. The scale computations have no duplicative or dependent reads, we only need that for advection. 2. No randomness or stochastic sampling is involved. 3. The total number of reads can be greatly reduced for a comparable level of fidelity to some other methods. 4. We can easily sample the entire buffer in one pass (on average). 5. The computational complexity is deferred to mipmap generation (though with a large coefficient), because: 6. The algorithm itself is O(n) with a fixed number of scales (or we could potentially do scale calculations in parallel with mipmap generation, equalling mipmap generation complexity at O(nlogn)) Notable downsides: 1. Using mipmaps introduces a number of issues, namely: a. Mipmaps can introduce artifacts due to interpolation and downsampling. Using Gaussian pyramids, or some other lowpass filtering method would be better. b. Using higher-order sampling of the texture buffer (e.g. bicubic) would also be better, but that would limit our performance gains. c. NPOT textures are problematic (as always). They can introduce weird anisotropy issues among other things. 2. Stochastic or large-kernel methods are a better approximation to the true sampling distribution approximated here, for a large-enough number of samples. 3. We're limited in how we construct our scale-space. Is a power-of-two stride length on both axes always ideal, even along diagonals? I'm not particularly sure. There are clever wavelet methods out there for Navier-Stokes solvers, and LES in particular, too. */ #define BUMP 3200.0 #define D(d) -textureLod(iChannel1, fract(uv+(d+0.0)), mip).w vec2 diff(vec2 uv, float mip) { vec2 texel = 1.0/iResolution.xy; vec4 t = float(1<