上传到着色器时为什么需要将四元数转换为4x4矩阵?

时间:2013-03-29 13:20:11

标签: opengl matrix glsl skeletal-mesh

我已经阅读了几篇关于OpenGL骨架动画的教程,它们似乎都是单一的使用四元数进行旋转,3d矢量进行翻译,所以不是矩阵。

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

2 个答案:

答案 0 :(得分:6)

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

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

完全可以使用4元素矢量均匀作为四元数,但是你必须在顶点着色器中链接大量计算:首先通过两个四元数旋转顶点,然后将其翻译为和< / em>然后将它与modelview矩阵相乘。通过简单地上传在着色器中加权的两个变换矩阵,可以在GPU上节省大量计算。在CPU上执行四元数矩阵乘法仅对每个骨骼执行一次计算,而在着色器中执行此计算会为每个单个顶点执行此计算。如果您需要进行大量具有不同输入日期的相同计算,GPU非常棒。但是,如果你只需要计算一小部分值,那么它们会很糟糕,这些值会在大量数据上重复使用。然而,CPU喜欢这种任务。

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

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

答案 1 :(得分:5)

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

当然,您需要以不同方式编写顶点着色器,以便使用四元数进行蒙皮而不是矩阵。实际上,我们正在使用双四元数蒙皮in our engine

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