2

我正在使用 WebGL 进行硬件蒙皮,但是更新我的模型节点层次结构会对性能造成巨大影响。

每个节点都需要查询其当前的位置/旋转/缩放关键帧,用它们构造一个局部矩阵,如果有父节点,则将其与父节点的世界矩阵相乘。

矩阵数学本身已尽可能优化(基于 gl-matrix 的矩阵构造的特殊变体)。

尽管如此,如果我更新许多模型,每个模型都有数十个节点(有些甚至有数百个,可悲的是),这会占用浏览器的所有执行时间。

当节点实际上不需要更新时,我尝试使用脏状态,但只需检查它们的本地数据是否更改(主要是检查位置或旋转是否更改)实际上会导致与计算矩阵相同的处理量。

WebCL 本来是理想的,但自 2014 年以来这似乎无处可去。

我开始考虑在着色器中运行它,但我不能完全理解如何设计它(例如存储关键帧,它是帧->数据的映射,或者如何写回数据)。

另一种方法是将所有动画变换缓存在纹理中,但这不能很好地缩放。对于关键帧数量足够少的模型,这是可以的,但对于动画较长的模型,这会很快变成数百兆字节。这主要是因为我想不出任何存储稀疏数据的方法。如果可能的话,那么我可以存储与关键帧相同数量的变换,这不会占用大量内存(现在,我存储每一帧的变换)。当然,这需要进行矩阵插值,我不确定这有多可靠。

有没有人有任何想法?

4

1 回答 1

0

我认为将整个节点层次结构计算卸载到 GPU 是不切实际的。你能做的最好的是将 2 个绝对世界变换关键帧上传到 GPU 并让 GPU 在它们之间进行插值。但我不确定插值的世界变换是否与您通过节点层次结构实际计算的相同。如果这是可能的,那么这将是一个可行的解决方案。请注意,您也不能在矩阵之间进行插值。您需要将其转换为支持插值的形式,例如使用四元数 + 附加数据。

实际上,我的项目也遇到了这个问题。我发现更新转换计算是最耗时的操作,尽管有完整的碰撞系统 + 响应也在进行。

我通过减少需要调用此更新转换的次数解决了这个问题。例如,如果您可以断定整个模型不在您的视锥体中,那么您根本不需要计算转换。这可能会将您需要执行的计算量减少到 ~1/6 到 ~1/4 之间。

其次,对于远处的物体,你不需要每帧都更新它们的变换。每隔几帧左右更新一次他们的变换。请记住,有些游戏仅提供 30 FPS,因此对于远处物体的一些跳帧可能并不明显。

最后,这可能根本不适用于 Javascript,所以我(还)没有这样做,你应该以缓存一致的方式存储和访问数据。请参阅这些幻灯片。可以有 10 倍的性能提升。但同样,可能不适用于 Javascript,因为 Javascript 数组不能保证按顺序打包数据。

于 2015-08-15T05:11:17.317 回答