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

den*_*niz 4 opengl glsl matrix skeletal-mesh

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

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

dat*_*olf 6

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

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

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

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

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


Axe*_*ing 5

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

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

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