2007年,Robert Bridson写了一篇一页纸的论文,后来被引用了近1000次。这篇论文解决的问题很朴素:怎么在一片区域里随机撒点,又不让点挤在一起——比如往地图上摆树,不能有两棵树叠在同一个坑里。这个算法用了将近15年,几乎没有像样的挑战者。最近有篇个人技术博客提出了一个改进,说能明显减少生成同样点数所需的计算量。听起来是件小好事,但对照学界这些年在同一问题上的进展,会发现这个“聪明优化”绕开了一个真正难啃的问题:它有没有悄悄破坏泊松盘分布赖以成名的那种“随机感”。

Bridson算法在做什么

网格切块保证每格最多容纳一个点;再维护一份活跃列表,每次随机挑一个点,在它周围内径r、外径2r的环形区域里投几次随机点,投中就留下,多次没投中就把这个点从列表里踢掉。整套流程摊到平面上,复杂度接近线性——比朴素的“随机撒点+逐一碰撞检测”高出一个量级。这也是它十几年没被换掉的原因:简单,好实现,速度够用。

那篇博客的改进,是给每个点记一个父点。算法在某个点周围找新点时,朝父点方向的一段角度可以直接跳过——那个方向生成的点大概率离父点太近,注定会被拒绝。跳过“必然失败”的角度,作者给出的对比图显示,同样的尝试次数下,最终生成的点数明显更多。

Bridson算法四步走 网格切块 每格最多一点 活跃列表 随机取一点 环形采样 r 到 2r 内投点 留下或踢出 失败即淘汰 父子角度优化:在“环形采样”这一步提前跳过朝父点方向的失败角度

省下来的计算,可能省错了地方

这个思路听起来无可指摘,但泊松盘采样从来不只是“点数越多越好”。图形学和模拟领域真正看重的,是点分布的统计特性——业内叫蓝噪声:没有网格感,也没有肉眼可见的规律,任意两点间距离足够均匀。判断一个采样算法好不好,不能只数生成了多少个点,还要看这些点排出来的图案是否依然“长得随机”。

角度排除本质是一种贪心选择:主动避开某个方向。贪心策略在采样理论里是把双刃剑——提高效率,也容易在点与点之间引入方向性偏差,长期下来可能出现环状规律或“辐条”式的伪影。判断这件事有没有发生,标准做法是用成对相关函数或径向能谱去检验分布,而不是数点数。这篇博客只给出了“点数变多”的对比图,没有做这一步。

  • 风险.优化省下的采样开销,如果换来的是分布规律性上升,反而砸了泊松盘算法最值钱的那块招牌。

学界早就有人在解这道题

这不是一个孤立的算法。二维平面上,除了Bridson,还有Mitchell最佳候选点算法(复杂度更高,且不严格保证最小距离)、层级投点法。真正做到“极大性+均匀性+不靠碰撞检测撞运气”的,是Mitchell 2022年发的一套确定性算法——把每个网格单元切成三角形和“卡块”,逐步精确分配面积,理论上更干净,只是实现复杂得多。

高维场景是另一回事。Bridson的环形采样一进入四到六维就开始变慢——环形体积几乎全堆在外壳上,网格内存也随维度指数增长。这也是为什么k-d dartsspoke-darts这类专为高维设计的方法在学界渐渐成了默认选项,而不是硬着头皮扩展Bridson。那篇博客猜测高维推广“收益会递减”,方向没错,但只是直觉判断,没给出具体临界维度。

泊松盘采样的三层生态 底层:Bridson网格+退火环 二维主流方案,15年未被替代,胜在简单快速 中层:Mitchell最佳候选 / 2022确定性算法 更均匀、无需拒绝采样,但实现复杂得多 上层:k-d darts / spoke-darts 专攻高维,退火环在这里效率崩塌

工程落地还差几步

即便这个角度优化经得起统计检验,想真正用上它的人还要迈过一道更朴素的坎:主流的开源泊松盘采样库——像kchapelier、thinks、martynafford这些常被游戏和可视化项目直接拿来用的实现——目前并没有内置父子结构和角度排除逻辑,一些库在边界处理和高维扩展上本身就有已知缺陷。一个写在博客里、跑在个人测试脚本上的优化,和一个能安全塞进生产管线的补丁,中间还差着适配、边界case处理和回归测试。

点数变多不等于分布仍然随机,这中间差着一次统计检验没做。

这类“业余但聪明”的算法改进,在图形学圈子里并不少见——门槛低,验证成本高,大多数人只看效果图就信了。Bridson的算法能扛住15年,靠的不是最快,而是分布“够干净”这个信誉。给它提速却没验证信誉是否还在,风险不在代码本身,而在没人做的那一步检验。这个改进有没有价值,取决于有没有人愿意花时间把成对相关函数这道题补上——不补,它就只是一张好看的效果图。