opengl - 计算着色器中与体素世界的粒子碰撞
问题描述
我在我正在开发的体素游戏中添加了一个粒子系统。目前,所有物理都在 CPU 上完成,而且速度非常慢(我的 CPU 与 2000 个粒子作斗争)。
对于每个粒子,我确定它理论上可以碰撞的体素范围(基于粒子的位置和速度以及经过的时间),然后检查与该范围内的所有体素的碰撞并使用最近的碰撞。
为了提高性能,我正在探索是否可以使用计算着色器来执行物理。
如果我将我的体素世界转换为位数组并将其放入 SSBO 中,那么计算着色器将拥有执行碰撞检测所需的所有几何信息。然而...
我为 CPU 编写的碰撞检测代码在 GPU 上根本不会高效;有很多分支/循环。有没有一种有效的方法让粒子在计算着色器上与体素网格碰撞?
解决方案
为简化起见,将您的粒子视为仅具有位置 P 和速度 V 单位/tick 的点状对象。不是精确计算您的粒子将接触哪些体素,粒子运动的第一个近似值可能只是检查 P + V 是否被固体体素占据(使用 3D 采样器),并将 V 设置为零(或设置为本身)如果是这种情况,否则将 P 增加 V。这些条件运算可以通过整数算术有效地完成,不需要分支。
如果这个近似值太粗略,因为 V 通常是多个体素单位长,并且因为您的体素几何结构足够精细,这可能会导致粒子穿过实心墙,您可以简单地在着色器中重复上述操作 N 次,使用 V /N 而不是 V,其中 N 应该是使剪辑在大多数情况下停止的最小常量整数。恒定长度的 for 循环将由着色器编译器展开,因此您仍然不需要真正的分支。
现在使用此算法,您的粒子的行为将是一旦它们到达障碍物就会停止所有(或大部分)运动。如果它们受到重力的影响(最好也在着色器内部完成),它们将直接向下坠落,但只有在失去垂直速度之后。如果他们到达一个楼层,他们将留在原地。
如果你想让你的粒子滑过水平表面而不是停在它们着陆的地方,并在撞击墙壁时保持它们的垂直动量,你可以将 V 分成水平和垂直分量,并对这两个分量分别执行上述步骤。
您还可以选择分离 V 的所有三个坐标,因此以对角线水平运动撞击墙壁的粒子将跟随墙壁而不是直接下降,但与两个组件相比,性能损失可能超过好处。
推荐阅读
- javascript - 如何在通过 JavaScript 克隆 html 元素后清除输入字段并选择字段?
- excel - VBA 代码覆盖保护设置 - 任何想法
- react-native - 命令失败:在 React-Native 中安装导航、firebase、图标等依赖项时出现 gradlew.bat installDebug 错误
- android - 将 Android Studio 配置为在文件打开时将一种格式应用于代码,在文件保存时将另一种格式应用于代码
- python - 如何平衡(过采样)PyTorch 中的不平衡数据(使用 WeightedRandomSampler)?
- php - 为什么将隐藏的输入标签放在 HTML5 DOCTYPE 声明之上
- gradle - 使用 Gradle 时如何阻止 IntelliJ IDEA 忘记忽略的目录?
- php - Laravel 雄辩的 ORM 关系
- java - 我运行了这个junit测试,但它失败了,怎么回事?
- c# - 如何通过ajax调用的c#函数更改asp标签的文本