在本文中,我将描述我对骨骼动画的理解,骨骼动画在所有现代 3D 引擎中用于动画角色、游戏环境等。
我将从最具体的部分开始描述——顶点着色器,因为整个计算路径,无论多么复杂,最终都会将准备好的用于显示的数据传输到顶点着色器。

骨骼动画经过CPU处理后,进入顶点着色器。
让我提醒一下没有骨骼动画的顶点的公式:
gl_Position = 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点;
对于那些不明白这个公式是如何产生的人,您可以阅读我的文章,该文章描述了在 OpenGL 上下文中使用矩阵显示 3D 内容的原理。
对于其余的–骨骼动画的实现公式:
” vec4animatedVertex=bone0matrix*顶点*bone0weight+”
“骨骼1矩阵 * 顶点 * 骨骼1权重 +”
“骨骼2矩阵 * 顶点 * 骨骼2权重 +”
“骨骼3矩阵 * 顶点 * 骨骼3权重;\n”
” gl_Position = 投影矩阵 * 视图矩阵 * 模型矩阵 * 动画顶点;\n”
也就是说,我们将最终的骨骼变换矩阵乘以顶点以及该矩阵相对于顶点的权重。每个顶点可以由4个骨骼进行动画,冲击的强度由骨骼权重参数调节,冲击的总和应等于1。
如果影响顶点的骨骼少于 4 个怎么办?我们需要将它们之间的权重分开,并使其余的影响为零。
从数学上讲,权重乘以矩阵称为“矩阵标量乘法”。乘以一个标量可以让您总结矩阵对结果顶点的影响。
骨骼变换矩阵本身作为数组传输。 此外,该数组包含整个模型的矩阵,而不是单独的每个网格的矩阵。
但是对于每个顶点,以下信息是单独传输的:
–影响顶点的矩阵索引
–影响顶点的矩阵权重
传输多于一根骨骼,通常使用顶点上4根骨骼的效果。
另外,4 个骰子的权重之和必须始终等于 1。
接下来我们看看它在着色器中的样子。
矩阵数组:
“统一 mat4 骨骼矩阵[kMaxBones];”
有关每个顶点上 4 个骨骼的效果的信息:
“属性 vec2bon0info;”
“属性 vec2bon1info;”
“属性 vec2骨头2info;”
“属性 vec2bon3info;”
vec2 –在 X 坐标中,我们存储骨骼的索引(并在着色器中将其转换为 int),在 Y 坐标中,我们存储骨骼对顶点的影响的权重。为什么必须以二维向量传输这些数据?因为 GLSL 不支持将具有有效字段的 C 可读结构传递给着色器。
下面我将给出一个从向量中获取必要信息以进一步代入animatedVertex公式的示例:
“int boone0Index = int(bone0info.x);”
“浮动骨头0权重=骨头0info.y;”
“mat4骨头0矩阵=骨头Matrices[bone0Index];”
“int boone1Index = int(bone1info.x);”
“浮动骨头1权重=骨头1info.y;”
“mat4骨1矩阵=骨头Matrices[bone1Index];”
“int骨头2Index = int(bone2info.x);”
“浮动骨头2权重=骨头2info.y;”
“mat4骨2矩阵=骨头Matrices[bone2Index];”
“int骨头3Index = int(bone3info.x);”
“浮动骨头3权重=骨头3info.y;”
“mat4骨头3矩阵=骨头Matrices[bone3Index];”
现在 CPU 上填充的顶点结构应如下所示:
x、y、z、u、v、bone0index、bone0weight、bone1index、bone1weight、bone2index、bone2weight、bone3index、bone3weight
顶点缓冲区结构在模型加载期间填充一次,但变换矩阵会在每个渲染帧从 CPU 传输到着色器。
在剩下的部分中,我将描述在CPU上计算动画的原理,在将其传输到顶点着色器之前,我将描述骨骼节点树,遍历动画-模型-节点-网格层次结构,矩阵插值。
来源
http://ogldev.atspace.co。英国/www/tutorial38/tutorial38.html
源代码
https://gitlab.com/demensdeum/skeletal-animation