5

我已经阅读了几篇关于 OpenGL 中骨骼动画的教程,它们似乎都一心一意地使用四元数进行旋转,使用 3d 矢量进行平移,而不是矩阵。

但是当他们进入顶点蒙皮过程时,他们将所有四元数和 3d 向量组合成一个 4x4 矩阵,然后上传矩阵以在着色器中进行其余的计算。4x4 矩阵有 16 个元素,而四元数 + 3d 向量只有 7 个。那么为什么我们要在上传之前将它们转换为 4x4 矩阵呢?

4

2 回答 2

7

因为只有两个 4×4 矩阵,每个骨骼一个顶点被分配和加权,你只需要做两个 4 向量 4×4 矩阵乘法和一个加权和。

与此相反,如果您作为单独的四元数和翻译提交,则必须执行两个 3 向量 3×3 矩阵乘法加上四个 3 向量 3 向量加法和加权和的等价。要么首先将四元数转换为旋转矩阵,然后再转换为 3 向量 3×3 矩阵乘法,或者直接进行 3 向量四元数乘法,计算量大致相同。之后,您必须使用模型视图矩阵进行后乘。

完全可以使用 4 元素向量 uniform 作为四元数,但是您必须在顶点着色器中链接大量计算:首先将顶点旋转两个四元数,然后对其进行平移然后将其与模型视图矩阵相乘. 通过简单地上传两个在着色器中加权的变换矩阵,您可以在 GPU 上节省大量计算。在 CPU 上执行四元数矩阵乘法只对每个骨骼执行一次计算,而在着色器中执行它会针对每个单个顶点执行计算。如果您必须使用不同的输入日期进行大量相同的计算,那么 GPU 非常棒。但是,如果您只需要计算少数几个值,它们会被大量数据重用,那么它们就很糟糕了。然而,CPU 喜欢这种任务。

由 4×4 矩阵表示的齐次变换的好处是,单个矩阵可以包含整个变换链。如果将旋转和平移分开,则必须按顺序执行整个操作链。只有一次旋转和平移,它比单个 4×4 矩阵变换的操作少。添加一个转换,您就达到了收支平衡。

即使在应用于网格的骨架姿势中,变换矩阵也是相同的对于所有顶点。假设网格在一对骨骼周围有 100 个顶点(这是一个很小的数字,顺便说一句),那么您必须对每个顶点进行上述计算,浪费宝贵的 GPU 计算周期。为了什么?确定一些 32 个标量值(或 8 个 4 向量)。现在比较一下:100 个 4 向量(如果您只考虑顶点位置)与仅 8 个。这是在着色器中处理四元数姿势所施加的计算开销的数量级。在 CPU 上计算一次,然后将其分配给预先计算好的 GPU,以便在基元之间共享。如果你编码正确,单个矩阵列的整个计算将很好地适应 CPU 管道,使得它的性能大大优于每次并行化它的尝试。并行化不是免费的!

于 2013-03-29T13:30:39.057 回答
6

在现代 GPU 中,上传到常量缓冲区的数据格式没有限制。

当然,您需要以不同的方式编写顶点着色器,以便使用四元数而不是矩阵进行蒙皮。事实上,我们在引擎中使用了双四元数蒙皮。

请注意,旧的固定功能硬件蒙皮确实只适用于矩阵,但那是很久以前的事了。

于 2013-03-29T13:26:22.327 回答