鱼群效果模拟
文章目录
- 鱼群效果模拟
- Boid算法
- 实现方式
- version1_CPU
- version2_GPU
- version3_Multilateration
- version4_Bitonic_Sorting (GPU友好)
- version5_Skinning (TODO)
- 细节项
- 优化项
- 参考链接
Boid算法
Boid算法是一种模拟群体行为的算法,由Craig Reynolds在1986年提出,主要用于模拟鸟群、鱼群等生物的集体运动。其核心思想是通过简单的规则让个体(Boid)表现出复杂的群体行为。
- 分离(Separation):
● 每个Boid会与邻近的Boid保持一定距离,避免碰撞。
● 通过计算与邻近Boid的距离并调整方向,确保个体间不靠得太近。 - 对齐(Alignment):
● 每个Boid会调整自己的方向,使其与邻近Boid的平均方向一致。
● 通过计算邻近Boid的平均方向,调整自身方向以保持群体的一致性。 - 凝聚(Cohesion):
● 每个Boid会向邻近Boid的中心位置移动,保持群体聚集。
● 通过计算邻近Boid的中心位置,调整自身位置以维持群体凝聚力。
实现方式
version1_CPU
核心:使用Physics.OverlapSphere函数获取周围鱼的信息,并更新旋转和方向。但此时cpu会大量循环,造成卡顿,URP里但依然会合批。
version2_GPU
核心:不能使用unityapi获取周围鱼群,在computershader中去遍历所有鱼群,进行Boid计算,Graphics.DrawMeshInstancedIndirect 直接提交gpu绘制。此时使用gpu代替cpu计算,但是遍历计算次数还是太多。
version3_Multilateration
核心:多点定位。
先进行多点定位,在进行Boid计算,只是修正了算法,本质上没有提升效率。
version4_Bitonic_Sorting (GPU友好)
核心:空间划分,哈希,双调排序
空间划分论文链接
双调排序的作用是什么?
● 首先我们需要将空间划分为3d/2d的均匀网格,当我们计算鱼下一帧位置时,获取周围的单位只需要获取以其为圆心,自定义半径内的网格体集合,避免大量循环。
● 在同一个网格的单位cell key (可能会有相同键值,所以还会进行距离计算进行剔除)
index | 索引 |
---|---|
cell coord | 空间坐标 |
cell hash | 哈希值 |
cell key | 哈希键 |
根据哈希算法,我们就能获取以 CellKey 为排序的列表,并且能跟cellkey获取相同单元格内的鱼单位,也能根据空间网格坐标(cell coord) 获取的CellKey计算周围单元格。
● 实现上述以 CellKey 为排序的列表的列表就用到了双调排序,获取从小到大或者从大到小的序列。
● 最终流程就是,将上述所有数据和运算全部放到gpu里运算。
version5_Skinning (TODO)
当我们不使用顶点动画而是骨骼动画时,动画系统大多在CPU上进行, 就需要使用到GPU Skinning ,但是鱼群的数量很多,玩家一般不会观察特别细致,只要进行简单函数修改定点着色器就行了
细节项
- 鱼的集群行为模式,如旋涡等
- 鱼的避障、攻击和跟随
- 鱼的动作可以根据顶点动画来进行修改
优化项
- 大场景避免鱼群到处乱跑,给你固定一个区域(AABB包围盒),同时对包围盒进行视锥剔除,不在相机内时就可以剔除渲染,同时终止该区域鱼群绘制。
参考链接
网易雷火经验贴
CUDA 空间划分 论文
GPU Skinning