【问题标题】:Javascript - optimizing node hierarchy updates for 3D animationsJavascript - 优化 3D 动画的节点层次结构更新
【发布时间】:2015-08-15 13:11:17
【问题描述】:

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

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

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

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

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

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

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

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

有人有什么想法吗?

【问题讨论】:

    标签: javascript webgl hierarchical-data skeletal-animation


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 我的模拟已经以 30FPS 运行。您链接的幻灯片很好,但是我真的想知道它们与 JS 的相关性如何。我的节点实际上已经在一个共享类型数组中(尽管所有成员都按顺序存储,即[local_matrix1, world_matrix1, local_location1, ..., local_matrix2, ...],不确定这是否重要),我认为我从未注意到这会加速任何事情 - 我实际上这样做只是为了能够在网络工作者周围移动阵列。剔除和 LOD 可能会起作用,但我更喜欢首先为最大的 N 个可见对象尽可能快地获取它。
    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    相关资源
    最近更新 更多