5.2 粒子系统与 SPH 流体


5.2 粒子系统与 SPH 流体

本节摘要:无网格流体用 SPH:每个粒子用核函数向邻居插值密度,密度偏离静止值就产生压力,压力梯度把粒子推开,再加粘性和重力。邻居搜索用第 3 章同一套网格。SPH 好看、好耦合刚体,难保证不可压缩;要做大体积静水,网格流体或 PBF 更合适。先写能泼出去的一碗粒子。

本节地图

阅读完本节,你应当能够:

  1. 用哈希网格找半径 h 内的邻居
  2. 写出密度、压力、加速度三项循环
  3. 处理边界:鬼粒子或核修正,避免贴墙密度丢失
  4. 判断 SPH、PBF、网格流体各自的使用场景

一、粒子不是刚体球海

一千个刚体球加接触也能“像液体”,但接触对数和求解迭代会打死预算,而且不可压缩性极差,会弹。SPH 把“流体微团”当成带核半径的采样点,力来自场而不是互补接触。粒子可以重叠,靠压力分开。这是另一套状态:位置、速度、密度、压力,没有朝向。

核半径 h 决定分辨率。h 太小,邻居不够,密度噪声大,粒子炸;h 太大,模糊成一团浆。经验:静止时每个粒子邻居 30 左右(三维),二维十几个。粒子间距 r0 ≈ h/2 量级,按核函数具体定。质量 m = 密度0 * 粒子体积。

for each particle i: rho_i = sum_j m_j * W(xi - xj, h) P_i = k * (rho_i / rho0 - 1) # 或 Tait 状态方程 for each particle i: a_pressure = -sum_j m_j * (P_i/rho_i^2 + P_j/rho_j^2) * gradW a_visc = 粘性项 v += (g + a_pressure + a_visc) * dt x += v * dt

压力公式多种。线性的好懂但压缩明显;Tait 指数硬一些。真正接近不可压缩要 PBF(位置基流体)或隐式压力投影。游戏水花、血液、魔法流体,显式 SPH 往往够。

方案 不可压缩 实现 与刚体耦合 适合
刚体球海 已有求解器 天然 演示错误
显式 SPH 差到中 采样或接触 小规模特效
PBF/XPBD 流体 较好 位置接触 游戏水体
网格欧拉流体 较烦 大体积、烟火

动手优先:先显式 SPH 泼一碗,再决定要不要 PBF。不要先写完整 Navier-Stokes 求解器。

二、邻居网格与边界

邻居搜索就是 3.1 的均匀网格,格边长等于 h。只查邻格。这是 SPH 的性能心脏。粒子数上万时, squar 邻居是自杀。

自由表面处邻居少,密度被低估,压力变负,表面张力乱或粒子自爆。常用:密度钳制不低于 rho0 的某个比例;或用核修正除以核之和;或负压当 0。墙:若只用刚体碰撞推粒子,贴墙粒子半边没有邻居,密度又低,会往墙里吸。鬼粒子(墙外镜像)或把边界力单独加,专门补密度。

💡 关键直觉:SPH 的一切错误外观,多半是密度估错。先可视化密度颜色,再调压力系数。

粘性让流体成块而不是气体。过粘像糖浆,过低像喷雾。XSPH 把速度向邻居平均,是一种便宜粘性。表面张力用颜色场或凝聚力项,小尺度水珠才需要。

时间步受 CFL 限制:粒子不要一步跨过太大的 h 比例,压力波速高时 dt 要小。流体常常要比刚体更细的子步。刚体 60Hz,流体 120–240Hz 子步并不罕见。两边耦合时在细步上采样刚体位置。

三、和刚体、渲染的桥

刚体对流体:把刚体表面当边界,或对重叠粒子施加惩罚/投影。流体对刚体:把压力或碰撞冲量积到刚体上。浮力应自然出现——若箱子不下沉也不上浮,检查力是否成对。单向耦合(流体碰墙但墙不动)做瀑布够用,做船不够。

⚠️ 常见坑:压力系数 k 调到极大想消灭压缩,dt 没减,第一步粒子就飞出屏幕。先减 dt 或改 PBF,不要只加 k。

渲染:粒子可以画球,或用 marching cubes/各向异性核出表面。物理教程不必做出电影水面,但要能看密度。调试用假色:蓝低密红高密。

PBF 简介:预测位置后,用密度约束做 XPBD 式投影,迭代把密度推回 rho0,再更新速度。压缩明显改善,实现仍是粒子加网格。若你已经写了 5.1 的 XPBD,PBF 是同一套思想换约束形式。我更愿意在游戏水体上用 PBF 而不是把 SPH 的 k 拉上天。

烟和火常用网格加半拉格朗日平流,不是 SPH。SPH 做烟扩散贵且难散。别把一种粒子方法当所有流体。选方法看:要泼溅耦合刚体用粒子;要大片烟雾用网格。

毕业实验:盒子里静止粒子,密度应接近 rho0,不应持续沸腾。开一个缺口应流出来,流量随缺口增大。放入轻盒子应浮,重盒子应沉。沸腾不停先查边界密度和负压。

哈希网格与刚体宽相可以共用代码,不要复制一份。粒子数量变化大,每帧重建网格通常比增量更新简单且够快。

单位:粒子位置仍是米。有人用像素粒子,压力系数完全无法迁移。从第一滴水就用米。

四、一碗水的参数表与沸腾诊断

从一组能静止的参数开始:粒子间距 0.05 米,h=0.1 米,rho0=1000,k 从小加到水面看起来硬但第一步不炸,dt 从 1/120 试起,粘性刚好消除抖动。记下这组数,换场景先复制再改一个量。没有“标准 SPH 参数”,只有“这碗水的参数”。

沸腾诊断:假色密度。表面发红内部发蓝是密度估错或负压没钳。贴墙粒子发黑往墙吸是缺邻居。满盒均匀红且仍动,是压力积分不稳,减 dt。粒子成晶体格子不流动,是粘性过大或 k 过大把它们焊死。

与刚体浮力:轻盒排水重量应大于重力。若不下沉不上浮,检查力是否只加在粒子上没还到刚体。可视化刚体受力箭头。单向耦合做瀑布时箭头可以为空,做船不行。

PBF 迭代 2–4 次通常够游戏水体。迭代 20 次会很硬但贵,且边界处理不好时会抖。先边界后迭代。SPH 转 PBF 时邻居网格可原样复用,不要重写宽相。

实践问答

邻居数多少算健康?

三维静止大约三十,二维十几个。太少密度噪,太多浆。h 和间距一起定,不要只改一个。

负压要不要保留?

表面常被低估密度出现负压,粒子自爆或聚团。游戏里常把负压当 0。要表面张力再单独加凝聚力,不要靠负压装表面张力。

流体 dt 为什么更小?

压力波速高,CFL 更严。刚体 60Hz、流体子步 2 到 4 常见。耦合在细步采样刚体。

什么时候上 PBF?

压缩明显、加 k 就炸时。PBF 用密度约束投影,复用邻居网格。不要无限加 k。

烟为什么不用 SPH?

烟要扩散和大体积,网格半拉格朗日更合适。SPH 做烟贵且难散。泼溅用粒子,烟火用网格。

参数扫描笔记:SPH 一碗水

扫描 1:从能静止的参数复制

没有标准参数。一次改一个量。

扫描 2:满盒均匀红仍动

压力积分不稳,减 dt。

扫描 3:成晶体不流动

粘性或 k 过大焊死。

扫描 4:船不下沉不上浮

力没还到刚体。可视化受力箭头。

扫描 5:k 极大想消灭压缩

第一步飞走。改 PBF 或减 dt。

扫描 6:烟用 SPH

贵且难散。烟走网格。

扫描 7:邻居暴力搜

比刚体暴力更早死。必须网格。

扫描 8:边界只用刚体推无密度补

贴墙往里吸。

工程备忘录

备忘 1

调「02-粒子流体SPH」时一次只改一个量,写下场景名、旧值、新值、醒岛数或能量变化。没有笔记的调参会在一周后变成传说。传说不能回归,不能交给同事,也不能在换库时当合同。 本条对应「02-粒子流体SPH」第 1 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 2

「02-粒子流体SPH」的单元测试尽量不依赖图形窗口。能在无头模式跑的断言,才会每次提交都跑。只靠进游戏看一看,等于没有测试。把金字塔睡眠、速度交换、自由落体距离这类金标准写成断言。 本条对应「02-粒子流体SPH」第 2 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 3

文档里的公式符号必须和代码注释同一张表。尤其是法向从谁指向谁、相对速度谁减谁、lambda 是力还是冲量。「02-粒子流体SPH」相关代码若混用两套符号,吸引接触和飞天会轮流出现,现场非常像随机 bug。 本条对应「02-粒子流体SPH」第 3 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 4

性能上先问能不能少做。「02-粒子流体SPH」再快,也快不过把睡着的岛整岛跳过、把碎片到期删掉、把静态体移出动态表。减工作量优于把同样工作向量化。向量化平方算法只是错得更稳更快。 本条对应「02-粒子流体SPH」第 4 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 5

可视化是「02-粒子流体SPH」的一部分而不是插件。接触生成时就把点、法向、深度留下来给绘制。事后从形状重新推断,会和求解器看到的数据不一致,你会修一个并不存在的偏差。 本条对应「02-粒子流体SPH」第 5 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 6

固定时间步是「02-粒子流体SPH」所有数值实验的尺子。尺子在抖,你无法比较积分器,无法调 beta,无法谈确定性。谁把渲染帧时间直接喂进物理,谁就在用弹性的尺子量钢梁。 本条对应「02-粒子流体SPH」第 6 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 7

「02-粒子流体SPH」里出现 NaN 要在源头断言:未归一化法向、零长度边当轴、除以过小的有效质量、四元数没归一。把 NaN 传到求解器再查,整场速度都会脏,回溯成本高一个数量级。 本条对应「02-粒子流体SPH」第 7 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 8

和美术、策划交接「02-粒子流体SPH」参数时,用测试盒而不是形容词。说清楚二十厘米台阶能上、八十厘米不能,比说手感更跟手有用。测试盒还能在引擎升级后当合同跑一遍。 本条对应「02-粒子流体SPH」第 8 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 9

「02-粒子流体SPH」若跨模块耦合,先单向再双向。布料先撞静地,流体先撞静箱,关节先吊静锚。双向一步到位时,你分不清是 A 推 B 写错还是 B 还力写错。控制变量不是学术,是省生命。 本条对应「02-粒子流体SPH」第 9 号备忘,和相邻条目不要合并成一句空话,分开验收。

备忘 10

睡眠和唤醒属于「02-粒子流体SPH」正确性,不只是性能。该醒不醒会穿模,不该醒全醒会卡顿。爆炸查询、关节边、运动学平台都是唤醒图的边。漏一条边,现场像鬼。 本条对应「02-粒子流体SPH」第 10 号备忘,和相邻条目不要合并成一句空话,分开验收。

核心回顾

  • SPH 用邻居插值密度,压力来自密度误差;邻居网格是性能关键。
  • 边界缺邻居会吸进墙,要鬼粒子或密度修正。
  • 先看密度可视化,再调 k 和粘性
  • dt 受压力波和 h 限制,流体常要比刚体更细子步。
  • 双向耦合才有浮力;单向只够撞静态地形。
  • 不可压缩不够就 PBF,不要无限加 k
  • 烟火走网格,泼溅走粒子,不要一种方法包打。

下一节把 XPBD 用到布料和绳索上:弯曲、拉伸、对刚体的单向拉。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U