☰
WebGL 流体模拟实战指南:WebGL-Fluid-Simulation 浏览器端实时流体仿真的原理、配置与移动端优化
2026/10/1 16:51:30 网站建设 项目流程
  • 图形学
  • 物理引擎

【免费下载链接】WebGL-Fluid-Simulation

Play with fluids in your browser (works even on mobile)

项目地址:https://gitcode.com/gh_mirrors/web/WebGL-Fluid-Simulation
点击查看免费下载

本指南围绕开源项目 WebGL-Fluid-Simulation 展开,它是一个纯浏览器端、基于 WebGL 的二维流体仿真引擎,项目定位是"在浏览器里玩流体(在手机上也能流畅运行)"。读完本文,你将掌握该项目的运行方式、Stable Fluids 类 GPU 求解管线(涡量、散度、压力 Jacobi 迭代、平流)、全部可调参数的含义与默认值、dat.GUI 交互面板的使用,以及移动端降级与截图导出等实战能力。

一、项目概览与快速上手

仓库根目录的 README.md 对该项目的定位非常简洁:"Play with fluids in your browser (works even on mobile)",并给出了在线体验入口、三份参考文献以及 MIT 许可证声明。整个项目是零依赖构建的静态网页应用,核心文件只有三个:

  • index.html:页面骨架,包含<canvas>、样式、移动端 App 推广弹层,并通过<script src="./script.js">引入主逻辑;
  • script.js:全部仿真代码(约 1600 行),包括 WebGL 上下文初始化、全部着色器、求解管线、输入交互与 GUI;
  • dat.gui.min.js:dat.GUI 控件库,用于生成右侧的参数调节面板。

由于项目没有任何打包步骤,运行方式非常简单:直接用浏览器打开 index.html 即可(需要支持 WebGL1/WebGL2 的现代浏览器);若要部署到服务器,将仓库内所有文件作为静态资源原样托管即可。页面加载后会立即在 canvas 上注入若干随机 splat(色块),随后用户用鼠标拖拽或手指滑动即可向流体注入扰动。

从源码结构看,index.html 中的<canvas></canvas>是唯一渲染目标,script.js启动时的调用链为getWebGLContext→startGUI→updateKeywords→initFramebuffers→ 若干随机multipleSplats→update()主循环(script.js)。

二、核心实现原理:基于 GPU Gems 第 38 章的 Stable Fluids 求解

README 的 References 部分列出了本项目的三条算法脉络:

  1. GPU Gems 第 38 章("Fast Fluid Dynamics Simulation on the GPU")——这是本项目求解器的主干,即 Jos Stam 的Stable Fluids(稳定流体)方法在 GPU 上的实现;
  2. mharrys/fluids-2d与haxiomic/GPU-Fluid-Experiments——两个开源的二维/GPU 流体实验项目,为具体着色器写法与效果组织提供了参考。

围绕 GPU Gems 的思路,script.js中step(dt)函数(script.js)每帧按固定顺序执行以下 GPU 计算链:

阶段对应着色器作用
涡量计算curlShader由速度场计算旋度(vorticity),script.js
涡量约束vorticityShader施加涡量增强力,弥补数值耗散、恢复湍流细节,强度由CURL控制,script.js
散度计算divergenceShader计算速度场的散度,用于检测"不可压缩"约束的偏差,script.js
压力初值清理clearShader以PRESSURE系数初始化压力场,script.js
压力 Poisson 求解pressureShader用Jacobi 迭代解压力场,迭代次数由PRESSURE_ITERATIONS决定(默认 20 次),script.js
压力梯度投影gradientSubtractShader从速度场减去压力梯度,使速度场变为无散度(不可压缩),script.js
速度/染料平流advectionShader沿速度场反向追踪采样(semi-Lagrangian advection),并施加耗散衰减,script.js

其中advectionShader值得单独说明:它默认依赖 GPU 的线性过滤,若设备不支持OES_texture_float_linear,着色器会自动编译进MANUAL_FILTERING宏,改用软件双线性插值(bilerp)完成采样(script.js),这也是项目兼容低端移动设备的关键设计之一。

三、参数配置详解:默认值与取值范围

整个仿真的可调状态集中在config对象中(script.js),理解这些参数即可控制效果与性能的平衡:

参数默认值说明
SIM_RESOLUTION128物理(速度/压力)场分辨率,整数(32/64/128/256),越高物理细节越精细、越耗性能
DYE_RESOLUTION1024染料(颜色)场分辨率,高/中/低/极低对应 1024/512/256/128
CAPTURE_RESOLUTION512截图导出分辨率
DENSITY_DISSIPATION1染料密度耗散(0~4),越大颜色消退越快
VELOCITY_DISSIPATION0.2速度耗散(0~4),越大流体减速越快
PRESSURE0.8压力场初值系数(0~1)
PRESSURE_ITERATIONS20压力 Jacobi 迭代次数,越大越接近精确解、越耗性能
CURL30涡量增强强度(0~50,步进 1),增大后漩涡更"卷"
SPLAT_RADIUS0.25单次注入半径(0.01~1),实际使用时除以 100 再经宽高比修正
SPLAT_FORCE6000指针拖动时施加的速度力倍数
SHADINGtrue是否启用伪光照(法线扰动明暗)
COLORFULtrue是否随时间自动更换注入颜色
COLOR_UPDATE_SPEED10颜色自动更换速度
PAUSEDfalse暂停仿真(按P键也可切换)
BACK_COLOR{r:0,g:0,b:0}背景色
TRANSPARENTfalse透明背景模式(启用后在画布显示棋盘格)
BLOOMtrue辉光后处理开关
BLOOM_ITERATIONS8辉光模糊的降采样级数
BLOOM_RESOLUTION256辉光缓冲分辨率
BLOOM_INTENSITY0.8辉光强度(GUI 可调 0.1~2.0)
BLOOM_THRESHOLD0.6辉光亮度阈值(GUI 可调 0~1)
BLOOM_SOFT_KNEE0.7阈值过渡的软膝(soft-knee)系数
SUNRAYStrue体积光(god rays)开关
SUNRAYS_RESOLUTION196体积光缓冲分辨率
SUNRAYS_WEIGHT1.0体积光强度(GUI 可调 0.3~1.0)

从源码结构看,getResolution()(script.js)会根据画布宽高比把分辨率换算为{width, height}二元组,且保证长边对应分辨率数值;因此DYE_RESOLUTION=1024实际意味着"长边 1024"。

四、dat.GUI 面板与快捷键操作

startGUI()(script.js)使用 dat.GUI 构建了宽 300px 的右侧控制面板,包含以下分组:

  • 质量(quality):DYE_RESOLUTION四档(高 1024 / 中 512 / 低 256 / 极低 128),修改后立即重建帧缓冲;
  • 仿真分辨率(sim resolution):SIM_RESOLUTION四档(32/64/128/256);
  • 基础滑块:density diffusion(DENSITY_DISSIPATION)、velocity diffusion(VELOCITY_DISSIPATION)、pressure(PRESSURE)、vorticity(CURL)、splat radius(SPLAT_RADIUS);
  • 开关:shading(SHADING)、colorful(COLORFUL)、paused(PAUSED);
  • Random splats 按钮:随机注入 5~24 个色块;
  • Bloom 文件夹:enabled / intensity / threshold;
  • Sunrays 文件夹:enabled / weight;
  • Capture 文件夹:background color(取色器)、transparent 开关、take screenshot(截图导出);
  • 外部链接:Github / Twitter / Discord / Check out mobile app。

快捷键方面(script.js):空格键触发一次随机多色注入,P键切换暂停/继续。

五、输入交互:鼠标与多点触控

项目同时支持鼠标与触摸输入,pointers数组维护了最多可同时存在的指针实例(script.js):

  • 鼠标:mousedown/mousemove/mouseup事件驱动单指针(script.js);
  • 触屏:touchstart/touchmove/touchend支持多指同时注入,每个触点按identifier追踪(script.js)。

每个指针携带texcoordX/Y、prevTexcoordX/Y、deltaX/Y等状态(pointerPrototype,script.js),其中位移增量会被correctDeltaX/correctDeltaY按宽高比修正,再乘以SPLAT_FORCE后写入速度场(splatPointer,script.js)。颜色方面,generateColor()使用 HSV 随机色并整体乘以 0.15 保持暗色调(script.js),且COLORFUL开启时每COLOR_UPDATE_SPEED秒自动更换一次颜色(updateColors,script.js)。

六、渲染与后处理管线

render()(script.js)负责把染料场合成到屏幕,后处理按需启用:

  • Shading(伪光照):displayShaderSource中通过四邻域颜色梯度构造法线,再与固定光源做点积得到漫反射明暗(script.js);
  • Bloom(辉光):预滤波 → 逐级降采样模糊 → 反向累加 → 最终按BLOOM_INTENSITY输出(applyBloom,script.js),模糊使用bloomBlurShader的四邻域均值;
  • Sunrays(体积光):sunraysMaskShader依据亮度生成遮罩,再以sunraysShader沿径向做 16 次累积采样并施加Decay=0.95衰减(script.js),模拟光源散射;
  • 抖动消除色带:显示阶段叠加 LDR_LLL1_0.png 作为抖动纹理(dithering texture),在 Bloom 输出中混入 ±1/255 的噪声,平滑渐变区域的色带(script.js)。

这些效果通过Material.setKeywords机制按需编译着色器变体:updateKeywords()(script.js)把SHADING/BLOOM/SUNRAYS宏注入 display shader,并以宏组合哈希缓存 program,避免每帧重复编译。

七、截图导出:帧缓冲读取流程

Capture 面板的 "take screenshot" 按钮触发captureScreenshot()(script.js),完整流程为:

  1. 按CAPTURE_RESOLUTION(默认 512)创建目标帧缓冲,执行一次离线render(target);
  2. framebufferToTexture用gl.readPixels(..., gl.FLOAT, ...)读回浮点 RGBA;
  3. normalizeTexture把浮点值 clamp 到 0~1 并转成Uint8Array(同时翻转 Y 轴);
  4. textureToCanvas写入 2D canvas,toDataURL()生成 PNG;
  5. downloadURI('fluid.png', datauri)触发浏览器下载(script.js)。

该功能对效果展示、壁纸制作与画面分享非常实用。

八、移动端适配与低端设备降级

"works even on mobile" 并非口号,源码中有三处显式的移动端/低端设备策略:

  1. 分辨率降级:isMobile()(匹配Mobi|Android的 UA 正则,script.js)为真时,DYE_RESOLUTION从 1024 降到 512(script.js);
  2. 能力探测降级:当设备不支持线性浮点过滤(OES_texture_float_linear)时,关闭SHADING/BLOOM/SUNRAYS并把染料分辨率降到 512(script.js),同时平流着色器自动切换MANUAL_FILTERING软件插值;
  3. 交互适配:移动端默认收起 GUI 面板(script.js);首次访问 20 秒后弹出 App 推广浮层(带promo/promo-close关闭按钮,见 index.html 与 script.js),并提供 App Store / Google Play 徽标入口。

WebGL 上下文初始化方面,getWebGLContext()(script.js)优先尝试 WebGL2,失败则回退到 WebGL1 /experimental-webgl;纹理格式通过getSupportedFormat从R16F → RG16F → RGBA16F逐级探测,保证在不同 GPU 上都能找到可渲染的半浮点格式(script.js)。

九、参考文献与开源许可

README 明确标注了本项目的算法与灵感来源:

  • GPU Gems 第 38 章:GPU 上的快速流体动力学仿真(Stable Fluids 方法),是求解管线的主干;
  • mharrys/fluids-2d与haxiomic/GPU-Fluid-Experiments:二维流体与 GPU 流体实验项目,为着色器实现提供参考。

许可证方面,项目在 LICENSE 中以MIT License发布(Copyright (c) 2017 Pavel Dobryakov),允许自由使用、修改与再分发,只需保留版权声明。若要在自己的页面中集成或二次开发,直接以静态方式引入 index.html 与 script.js 即可,无需任何构建工具或第三方依赖。

  • 图形学
  • 物理引擎

【免费下载链接】WebGL-Fluid-Simulation

Play with fluids in your browser (works even on mobile)

项目地址:https://gitcode.com/gh_mirrors/web/WebGL-Fluid-Simulation
点击查看免费下载

相关推荐

上一篇:Middleman与Sass完美结合:构建模块化CSS架构
下一篇:分子动力学模拟分析利器MDAnalysis:安装与环境配置终极教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询