由 Rust + WebAssembly 实时求解不可压缩流体方程
🖱️ 拖拽 搅动流体并注入染料 | 提高粘度,流动会变得像蜂蜜一样黏稠
用 Jos Stam 提出的「稳定流体」(Stable Fluids)算法实时求解不可压缩流体的 Navier-Stokes 方程。整个画面是一个 N×N 的网格,每个格子保存速度和染料浓度;每一帧先更新速度场,再让染料随速度场流动。这个算法最大的特点是无论时间步长多大都不会数值爆炸,因此常被用在游戏和交互特效里。
(1 + 4a)·x − a·Σ邻居 = x₀,采用 20 次 Gauss-Seidel 迭代。隐式方法对任意步长都稳定。∇²p = ∇·u,再从速度中减去压力梯度 u ← u − ∇p,得到无散度的速度场。这一步正是产生漩涡的关键。fluid_add_velocity() 和 fluid_add_density() 在拖拽位置注入力和染料;开启「自动喷射」时,底部两个喷口会持续注入。fluid_step(dt, 粘度, 扩散, 消散):先处理速度(扩散 → 投影 → 平流 → 投影),再处理染料(扩散 → 平流),最后按消散系数衰减染料。fluid_render() 把 N×N 的染料浓度映射成颜色(深色 → 蓝 → 橙 → 浅黄),返回 RGBA 字节数组。ImageData,再开启平滑缩放,绘制到 512×512 的画布上。f32 的一维数组存储,按行连续排列,内层循环顺序访问内存,对缓存友好。源码crates/simulation/fluid/src/lib.rswww/fluid/index.js