pbd不适合水体流体模拟,也不等价于sph;它仅能实现无物理真实性的胶状近似,而sph或dfsph才能模拟涡旋、飞溅和表面张力等真实水体行为。

直接说结论:PBD(Position-Based Dynamics)本身不适合做水体流体模拟,更不等价于 SPSH(Smoothed Particle Hydrodynamics);用 PBD “实现水体”通常只是视觉近似,且必须放弃物理准确性——如果你需要真实感强、带涡旋/飞溅/表面张力的水体效果,SPH 或 DFSPH 是更合理的选择,而 PBD 只能处理极简化的“可拉伸胶状液体”。
为什么 PBD 不是 SPH,也不能直接替代 SPH
PBD 是一种约束求解框架,核心是迭代修正粒子位置以满足几何约束(如距离、体积、不可压缩性),它没有显式建模压力、粘度或核函数积分;而 SPH 是基于连续介质假设和核近似的拉格朗日流体方法,必须计算密度、压力梯度、粘性力等物理量,依赖 Wendland 或 Spiky 核函数和邻居搜索(如 spatial hashing 或 octree)。
常见误解是把“PBD + 体积约束”当成水——这只能防止粒子团塌缩,但无法产生表面张力、压力传播延迟、飞溅或自由液面行为。实际运行中你会看到:
- 粒子群像一团果冻,受重力后缓慢下垂,无流动分离
- 碰撞时无飞溅,只有整体反弹或穿透
- 无法调节粘度/表面张力参数,所有“流体感”靠调约束迭代次数和阻尼硬编码
如果坚持用 PBD 模拟类水体,关键改造点在哪
要在 PBD 框架里逼近水的观感,必须绕过其原生限制,引入少量 SPH 风格的计算,但不改变主循环结构。重点不是“替换算法”,而是“在 PBD 位置修正前插入轻量物理估算”:
- 用
spatial hashing构建邻居表(不能只靠暴力 O(n²)),哈希桶尺寸建议设为平均粒子间距的 1.5 倍 - 每帧先算局部密度
rho_i = sum_j W(|x_i − x_j|),用Spiky kernel(避免负压) - 按密度偏差构造伪压力约束:
Δx_i ∝ (rho_i − rho0) * ∇W,再把这个偏移加到 PBD 的位置更新步长中 - 表面张力可简化为:对每个粒子,收集邻居法向均值,再施加一个朝向该法向的小幅位移(需归一化,否则爆炸)
- 务必关闭 PBD 默认的
velocity damping,否则流体迅速停滞;改用基于速度差的邻居级粘性项(类似Monaghan viscosity的简化版)
性能瓶颈和最容易崩的三个地方
实时(≥30 FPS)跑 2k~5k 粒子水体,在现代 CPU 上可行,但稍有不慎就会崩溃或卡死:
-
neighbor search没做 early exit 或桶未复用内存,单帧耗时从 2ms 涨到 40ms - 密度计算中没加
rho0下限保护,某粒子密度突降到 0 → 压力项除零或反向爆炸 - 伪压力位移未与 PBD 主约束迭代解耦,导致约束冲突:比如体积约束想撑开粒子,压力项又往里推,结果震荡发散
调试时优先输出单粒子的 rho_i 和 Δx_i 绝对值,看是否集中在合理区间(例如 rho_i ∈ [0.8, 1.2] * rho0,|Δx_i| )。
真正做水,别硬套 PBD;真要用 PBD,就接受它是“类水软体”,别指望它解 Navier-Stokes。最常被忽略的是:SPH 的稳定性极度依赖时间步长和核半径比,而 PBD 用户往往直接抄了刚体参数,忘了流体对 dt 敏感度高两个数量级。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











