导语
Unity中骨骼动画使用SkinnedMeshRenderer渲染,无法合批,一个骨骼动画就是一个DrawCall。当场景中有数量比较多的骨骼动画时,会为游戏带来渲染压力。如果将骨骼动画数据烘焙到一张纹理中,在GPU中计算模型各顶点位置,使用Mesh渲染骨骼动画,配合GpuInstance,可以实现大规模的骨骼动画的渲染。
骨骼动画原理
传统骨骼动画,模型动画的相关计算在CPU中完成。模型由一组顶点组成,这些顶点互相连接组成mesh。
动画就是控制这些顶点的位置,使模型看起来在运动。模型中有一些长条装的物体称为骨骼,顶点绑定到骨骼上。当骨骼运动时,带动顶点运动。而模型摆成的双臂展开的姿势被成为T-Pose,又称为绑定姿势(bind position)。是模型制作时的默认姿势。之后在计算骨骼动画时,具有重要作用
我们以模型的一只手臂的运动为例来讲解骨骼动画的原理。
假设手臂从绑定姿势B运动到目标姿势T,设骨骼j0,j1,j2。已知顶点v在绑定姿势下模型空间中的坐标B,各骨骼相对于父骨骼的位移和旋转,求顶点v在目标姿势下模型空间中的坐标T 。

首先求出顶点v在j2骨骼空间的坐标。骨骼的逆绑定姿势可以将顶点从模型空间变换到骨骼空间。即顶点v在模型空间的坐标左乘绑定姿势的逆变换矩阵BindPoses。
骨骼的绑定姿势
在3D动画和计算机图形学中,骨骼中的“绑定姿势”(Binding Pose)是一个非常重要的概念。它指的是模型和其骨骼系统在没有任何动画应用时的默认或初始姿势。这个姿势是建模和蒙皮过程中的基础,也是所有动画变换的参考点。
绑定姿势的重要性
- 参考基准:绑定姿势为模型提供了一个参考状态,所有的动画变换都是相对于这个状态进行的。这意味着,无论动画如何变化,都可以通过参考绑定姿势来计算出正确的变换。
- 蒙皮基础:在蒙皮过程中,模型的每个顶点都会被绑定到一个或多个骨骼上。顶点的初始位置是相对于绑定姿势中骨骼的位置来确定的。因此,绑定姿势直接影响了蒙皮的质量和最终动画的自然度。
- 动画制作:动画师通常在绑定姿势的基础上创建动画。一个清晰且适当定义的绑定姿势可以使动画制作过程更加直观和高效。
绑定姿势的特点
- T姿势:在许多情况下,绑定姿势被设置为“T姿势”,其中角色的手臂水平伸展,腿部直立,面向正前方。这种姿势使得皮肤权重的分配更加均匀,便于动画师理解和操作。
- A姿势:另一种常见的绑定姿势是“A姿势”,其中手臂稍微下垂。这种姿势有时被认为在某些动画制作中更自然。
绑定姿势逆矩阵
在技术实现上,每个骨骼的绑定姿势逆矩阵(Inverse Bind Pose Matrix)是关键。这个矩阵是骨骼在绑定姿势下的变换矩阵的逆,用于将顶点坐标从模型空间转换到骨骼空间。在实际的蒙皮计算中,顶点的最终位置是通过将这些逆矩阵与骨骼的当前动画矩阵相乘来确定的。
实际应用
在实际的3D模型和动画制作流程中,确保绑定姿势的正确设置是非常重要的。错误的绑定姿势可能导致动画中出现扭曲或其他视觉问题。因此,模型师和动画师需要密切合作,确保绑定姿势的正确性和实用性。
总之,绑定姿势是3D动画制作中的一个基础概念,它为动画的创建和实现提供了必要的基础和参考。正确理解和应用绑定姿势对于制作高质量的3D动画至关重要。
在计算骨骼动画和蒙皮时,绑定姿势(Bind Pose)是一个非常重要的概念。绑定姿势是指模型在建模软件中被创建时的初始姿势,通常是一个标准的姿势,比如T形姿势。在这个姿势下,所有的骨骼变换矩阵被记录下来,用于后续的动画计算。
绑定姿势矩阵(Bind Pose Matrix)是每个骨骼在绑定姿势下的全局变换矩阵。这个矩阵用于将顶点从模型空间转换到骨骼空间。为了在动画过程中正确地应用骨骼变换,我们需要计算每个骨骼的逆绑定姿势矩阵(Inverse Bind Pose Matrix),用于将顶点从骨骼空间转换回模型空间。
在蒙皮过程中,顶点的位置通过以下步骤进行变换:
- 将顶点从模型空间转换到骨骼空间:使用逆绑定姿势矩阵。
- 应用骨骼的动画变换:使用当前帧的骨骼全局变换矩阵。
- 将顶点从骨骼空间转换回模型空间:使用绑定姿势矩阵。
在代码中,绑定姿势矩阵和逆绑定姿势矩阵的计算通常在初始化时完成,并在动画过程中反复使用。以下是一个简单的示例,展示如何在代码中使用绑定姿势:
public class Bone
{
public Matrix4x4 localTransform;
public Matrix4x4 globalTransform;
public Matrix4x4 bindPoseMatrix;
public Matrix4x4 inverseBindPoseMatrix;
public List<Bone> children = new List<Bone>();
public Bone(Matrix4x4 localTransform, Matrix4x4 bindPoseMatrix)
{
this.localTransform = localTransform;
this.bindPoseMatrix = bindPoseMatrix;
this.inverseBindPoseMatrix = bindPoseMatrix.inverse;
}
}
在这个示例中,bindPoseMatrix 是骨骼在绑定姿势下的全局变换矩阵,而 inverseBindPoseMatrix 是其逆矩阵。通过这些矩阵,我们可以在动画过程中正确地计算顶点的位置。
在实际应用中,绑定姿势矩阵通常由建模软件导出,并在导入到游戏引擎时使用。确保这些矩阵的正确性对于实现精确的骨骼动画至关重要。
绑定姿势的逆变换矩阵又称为Bone OffsetMatrix,是T-Pose阶段,SkinMesh空间到某个骨骼空间的转换矩阵,用于将顶点从 SkinMesh空间转到骨骼空间矩阵。BindPoses在Unity里是bone.bindpose,是个Matrix4x4,包含平移、旋转、缩放,每个骨骼有自己的BindPoses。在3DMax中 模型坐标系不一定与世界坐标系重合,所以 BindPoses其实是一个复合的矩阵,包含顶点从Skinmesh空间变换到世界空间 * 从世界空间变换到某一个bone空间。
bindPoses[i] = bones[i].worldToLocalMatrix * transform.localToWorldMatrix;
在3Dmax制作过程中,在T-POSE阶段,程序已经帮我们计算出来结果了,存储于模型里的骨骼信息。
然后顶点在骨骼空间的坐标依次左乘,从绑定姿势运动到目标姿势过程中,各骨骼相对于父骨骼的变换矩阵,即可求出顶点v在目标姿势模型空间的坐标。其中Kj为蒙皮矩阵
骨骼中的目标姿势
在3D动画中,除了“绑定姿势”之外,还有一个重要的概念是“目标姿势”(Target Pose)。目标姿势指的是骨骼在特定时间点应该达到的姿势,这是动画序列中的一个关键帧姿势,用于定义角色或对象的具体动作和位置。
目标姿势的作用
- 动画定义:目标姿势是动画中的一个或多个关键帧,定义了角色或对象在特定时间点的具体形态。通过设置序列中的多个目标姿势,动画系统可以插值(通常是线性或非线性插值)这些关键帧,创建平滑的动画效果。
- 动作控制:目标姿势允许动画师精确控制角色的动作,通过详细定义每个关键帧,动画师可以精确地表达角色的动作意图和情感表达。
- 交互反馈:在交互式应用(如视频游戏)中,目标姿势可以根据玩家的输入动态生成,提供即时的视觉反馈,增强游戏的沉浸感和响应性。
目标姿势与绑定姿势的关系
目标姿势和绑定姿势虽然是两个不同的概念,但它们在动画制作中是紧密相关的:
- 绑定姿势是模型的初始参考状态,所有的骨骼变换都是相对于这个状态进行的。
- 目标姿势是从绑定姿势经过一系列变换后的结果,这些变换定义了角色或对象在特定时间点的具体姿态。
实现目标姿势
在技术实现上,目标姿势通常通过修改骨骼的变换矩阵来实现。这些变换矩阵包括平移、旋转和缩放,它们可以单独应用或组合应用到骨骼上。在3D动画软件或游戏引擎中,这些变换通常通过以下步骤实现:
- 设置关键帧:动画师在时间线上为特定的骨骼设置关键帧,定义骨骼在这些帧中的位置和方向。
- 插值计算:动画系统在关键帧之间自动计算插值,生成平滑的过渡动画。这种插值可以是线性的,也可以是基于更复杂曲线(如贝塞尔曲线)的非线性插值。
- 渲染动画:最终的动画是通过在每一帧中应用计算出的骨骼变换矩阵到模型的顶点上,然后渲染出结果。
应用示例
在实际的动画项目中,目标姿势的设置通常涉及到详细的动作设计和预可视化。例如,在制作一个跑步动画时,动画师会设置多个目标姿势来定义腿部的运动、身体的倾斜和手臂的摆动。通过精确控制这些目标姿势,可以创造出自然流畅的运动效果。
蒙皮矩阵
在计算机图形学和动画领域,“蒙皮矩阵”(Skinning Matrix)通常用于描述在骨骼动画(skeletal animation)中,如何将模型的顶点附着到骨骼上,并随着骨骼的移动而移动。这种技术也被称为蒙皮(skinning)或骨骼蒙皮(skeletal skinning)。蒙皮矩阵是实现这一过程的关键数学工具。
蒙皮矩阵的作用
蒙皮矩阵用于将模型的顶点从它们的初始位置(通常是模型空间)转换到受骨骼影响的最终位置(世界空间或相机空间)。每个顶点可以被一个或多个骨骼影响,这种影响通过权重来衡量。
蒙皮矩阵的计算
- 骨骼变换矩阵:每个骨骼都有一个变换矩阵,描述了骨骼从其初始(绑定)位置到当前动画帧的位置和方向的变换。
- 绑定姿势逆矩阵:每个骨骼还关联一个绑定姿势逆矩阵,这是骨骼在模型的初始绑定姿势下的逆变换矩阵。
- 蒙皮矩阵的计算:对于每个顶点,其蒙皮矩阵是通过将影响该顶点的每个骨骼的骨骼变换矩阵与其对应的绑定姿势逆矩阵相乘,然后根据骨骼对顶点的影响权重进行加权平均得到的。
数学表达
![如果顶点 ( v ) 受到 ( n ) 个骨骼的影响,每个骨骼 ( i ) 有一个权重 ( w_i ),骨骼变换矩阵 ( B_i ),和绑定姿势逆矩阵 ( B_i^{-1} ),那么顶点 ( v ) 的蒙皮矩阵 ( S ) 可以表示为:
[ S = \sum_{i=1}^{n} w_i (B_i B_i^{-1}) ]
这里,( B_i B_i^{-1} ) 表示将顶点从模型空间转换到骨骼 ( i ) 的当前动画姿势下的空间。](https://i-blog.csdnimg.cn/direct/85d7ce23667b4d1aa07ecbfd02e4abd9.png)
应用
在实际的图形渲染过程中,顶点着色器(Vertex Shader)通常会使用这些蒙皮矩阵来计算顶点的最终位置,从而实现模型的动画效果。这种技术广泛应用于游戏和电影中,用于创建复杂的动画和真实的角色动作。
蒙皮矩阵的正确计算和应用是实现高质量骨骼动画的关键,它使得动画角色能够以自然和真实的方式移动。
在一些关节的连接处,一个顶点的位置可能同时受到多个骨骼的影响。这时使用加权的方式处理,即影响这个顶点的骨骼的蒙皮矩阵各乘以一个权重值,求出蒙皮矩阵的加权平均数再求出骨骼的目标位置。
求出蒙皮矩阵的加权平均数
蒙皮矩阵(Skinning Matrix)在计算机图形学中用于角色动画,特别是在使用骨骼动画时。它通常是通过将骨骼的变换(位置、旋转、缩放)与权重结合来计算的。加权平均数在这里指的是根据每个骨骼对顶点的影响权重来计算最终的变换矩阵。
蒙皮矩阵的计算

具体步骤


注意事项
- 确保所有权重的和为 1,以保持变换的正确性。
- 在实际应用中,可能需要考虑矩阵的逆变换(例如,将模型空间转换为骨骼空间),具体取决于使用的坐标系和变换方式。
通过以上步骤,你可以计算出蒙皮矩阵的加权平均数,从而实现角色的平滑动画效果。




权重和绑定姿势下顶点在模型空间的坐标是已知的。也就是说,我们只要计算出每根骨骼在每一帧的蒙皮矩阵K。就可以求出顶点在目标姿势的模型空间下的坐标。
我们将骨骼排好序,并记录骨骼序号。对于每个顶点,我们将影响其位置的骨骼序号和权重记录到顶点属性中。
在离线状态下,我们播放骨骼动画,按固定帧率记录每根骨骼的位置、旋转、缩放信息,并计算出该骨骼相对于父骨骼的TRS矩阵。用该骨骼的BindPoses矩阵,依次左乘各父骨骼的TRS矩阵,直到根骨骼。即可求出该骨骼在该帧的蒙皮矩阵K。并将这些蒙皮矩阵记录到一个纹理中。蒙皮矩阵是4x4的TRS矩阵,纹理中一个像素包含argb四个通道,可以存储TRS矩阵的一个列向量。由于TRS矩阵最后一列固定是(0,0,0,1),可以不必存储。所以我们用3个像素就可以存储1个蒙皮矩阵。
骨骼空间
在计算机图形学和动画中,骨骼空间(Bone Space)是一个重要的概念,尤其是在使用骨骼动画(Skeletal Animation)技术时。以下是对骨骼空间的详细解释:
骨骼空间的定义
骨骼空间是指与骨骼系统相关的坐标空间。在这个空间中,骨骼的变换(位置、旋转、缩放)是相对于其父骨骼或根骨骼的。每个骨骼都有自己的局部坐标系,通常称为局部空间(Local Space),而整个骨骼系统的坐标系则称为全局空间(Global Space)或世界空间(World Space)。
骨骼空间的层次结构
-
根骨骼(Root Bone):
- 骨骼层次结构的起始点,通常是整个骨骼系统的父骨骼。所有其他骨骼都是相对于根骨骼进行变换的。
-
子骨骼(Child Bones):
- 每个骨骼可以有一个或多个子骨骼。子骨骼的变换是相对于其父骨骼的。
-
局部空间与全局空间:
- 每个骨骼都有自己的局部空间,局部空间的原点通常是骨骼的根部。全局空间则是整个场景的坐标系,所有骨骼的变换都可以转换到全局空间中。
骨骼空间的变换
在骨骼动画中,顶点的变换通常涉及以下几个步骤:
-
从模型空间到骨骼空间:
- 顶点的初始位置通常在模型空间中。通过将顶点位置乘以模型的变换矩阵(通常是模型的世界矩阵),可以将其转换到骨骼空间。
-
应用骨骼变换:
- 在骨骼空间中,使用蒙皮矩阵(Skinning Matrix)对顶点进行变换。蒙皮矩阵是根据骨骼的变换和权重计算得出的。
-
从骨骼空间到世界空间:
- 最后,将变换后的顶点位置从骨骼空间转换回世界空间,通常通过将其乘以根骨骼的变换矩阵来实现。
示例
假设我们有一个简单的骨骼结构,包含一个根骨骼和一个子骨骼。根骨骼的位置在世界空间中是 ((0, 0, 0)),而子骨骼相对于根骨骼的位置是 ((1, 0, 0))。


总结
骨骼空间是骨骼动画中一个关键的概念,它帮助我们理解如何将顶点从模型空间转换到骨骼空间,并应用骨骼的变换。通过这种方式,角色的动画可以根据骨骼的运动进行动态更新,从而实现平滑的动画效果。
蒙皮矩阵记录到一个纹理中
在高级的计算机图形应用中,尤其是在游戏和实时渲染环境中,将蒙皮矩阵存储到纹理中是一种优化技术,这种方法可以有效地利用GPU的纹理缓存和并行处理能力,从而提高动画的渲染效率。这种技术通常被称为“纹理蒙皮”或“GPU蒙皮”。下面是这种技术的基本概念和实现步骤:
为什么要将蒙皮矩阵存储到纹理中?
- 性能优化:GPU对于纹理数据的读取非常高效,因为纹理缓存(texture cache)是为高速数据访问优化的。通过将蒙皮矩阵存储在纹理中,可以减少顶点着色器中的计算量和常规内存访问,从而提高渲染性能。
- 减少带宽消耗:传统的蒙皮方法需要将大量的骨骼变换矩阵从CPU传输到GPU,这可能会占用大量的带宽。将这些矩阵存储在纹理中可以一次性上传,并在需要时由GPU读取。
- 支持更复杂的动画:使用纹理存储蒙皮矩阵可以支持更多的骨骼和更复杂的动画,而不会对性能产生太大影响。
实现步骤
- 矩阵编码:首先,需要将每个蒙皮矩阵编码到纹理的像素中。由于每个矩阵是4x4的,通常需要使用四个纹理像素来存储一个矩阵(每个像素可以存储一个4元素的向量)。
- 纹理格式选择:选择合适的纹理格式是关键,通常需要使用高精度的浮点格式(如RGBA32F),以确保矩阵数据的精度和正确性。
- 上传纹理:将编码后的矩阵数据上传到GPU的纹理单元。
- 顶点着色器修改:在顶点着色器中,根据顶点的骨骼索引和权重,从纹理中读取相应的矩阵数据,进行矩阵运算,计算最终的顶点位置。
示例代码(GLSL)
uniform sampler2D skinningTexture;
uniform int bonesPerVertex;
void main() {
vec4 skinVertex = vec4(0.0);
for (int i = 0; i < bonesPerVertex; ++i) {
int boneIndex = int(aBoneIndices[i]);
float weight = aBoneWeights[i];
mat4 boneMatrix = fetchBoneMatrix(skinningTexture, boneIndex);
skinVertex += weight * (boneMatrix * vec4(aPosition, 1.0));
}
gl_Position = modelViewProjectionMatrix * skinVertex;
}
mat4 fetchBoneMatrix(sampler2D texture, int index) {
// 计算纹理中的偏移位置
// 返回矩阵
}
注意事项
- 精度问题:使用纹理存储矩阵时,需要注意数据精度和格式选择,以避免渲染错误。
- GPU支持:确保目标平台的GPU支持所需的纹理格式和操作。
通过将蒙皮矩阵存储在纹理中,可以显著提高大规模动画的渲染性能,特别是在处理大量骨骼和复杂动画时。这种方法在游戏和虚拟现实应用中尤其有用,因为它们通常需要实时渲染高质量的动画。
继续实现细节
纹理布局
在实际应用中,如何布局纹理是一个关键问题。通常,每个骨骼的矩阵(4x4)会被分解为四个vec4,每个vec4存储在纹理的一行中。如果有N个骨骼,那么纹理至少需要4N行。例如,如果有50个骨骼,至少需要200行。
纹理读取
在顶点着色器中,根据传入的骨骼索引和权重,从纹理中读取相应的矩阵数据。这通常通过计算纹理坐标来实现,纹理坐标需要根据骨骼索引和矩阵行号来计算。
mat4 fetchBoneMatrix(sampler2D texture, int index) {
float baseY = float(index * 4); // 每个骨骼矩阵占4行
mat4 boneMatrix;
boneMatrix[0] = texture2D(texture, vec2(0.5, (baseY + 0.5) / textureHeight));
boneMatrix[1] = texture2D(texture, vec2(0.5, (baseY + 1.5) / textureHeight));
boneMatrix[2] = texture2D(texture, vec2(0.5, (baseY + 2.5) / textureHeight));
boneMatrix[3] = texture2D(texture, vec2(0.5, (baseY + 3.5) / textureHeight));
return boneMatrix;
}
性能优化
- 纹理尺寸:选择合适的纹理尺寸以优化GPU的纹理缓存利用率。通常,尽量保持纹理的宽度和高度为2的幂。
- 纹理过滤:由于矩阵数据需要精确读取,应使用
GL_NEAREST过滤模式来避免插值带来的误差。 - 纹理格式:使用高精度浮点格式(如RGBA32F)以保持矩阵变换的精度。
兼容性和跨平台
在使用纹理蒙皮技术时,需要考虑目标平台的支持情况。不是所有的硬件平台都支持高精度浮点纹理,或者可能在性能上有所不同。因此,开发时需要测试不同的硬件平台,确保动画的兼容性和性能。
通过这种方法,可以有效地利用GPU的并行处理能力,提高动画的渲染效率,尤其是在处理具有大量骨骼的复杂模型时。这种技术已经在多个高端游戏引擎中得到应用,帮助它们在保持高性能的同时,实现视觉上令人印象深刻的动画效果。
蒙皮矩阵纹理
Unity中使用GpuSkinning+GpuInstance实现大规模骨骼动画的渲染
leojdli
2020-12-01 17:59
461
0
13
分享
AI摘要
| 导语 Unity中骨骼动画使用SkinnedMeshRenderer渲染,无法合批,一个骨骼动画就是一个DrawCall。当场景中有数量比较多的骨骼动画时,会为游戏带来渲染压力。如果将骨骼动画数据烘焙到一张纹理中,在GPU中计算模型各顶点位置,使用Mesh渲染骨骼动画,配合GpuInstance,可以实现大规模的骨骼动画的渲染。
线上效果
《英雄杀》世界玩法中的军队就是使用GpuSkinning+GpuInstance技术实现的。游戏高峰时期,地图中有300+士兵进行混战。在华为P9等低端机器上依然能够流畅运行,帧率达到45帧左右。
骨骼动画原理
首先,我们了解一下传统骨骼动画的原理。传统骨骼动画,模型动画的相关计算在CPU中完成。模型由一组顶点组成,这些顶点互相连接组成mesh。如下图:模型由1186个顶点和1732个面片组成。
动画就是控制这些顶点的位置,使模型看起来在运动。模型中有一些长条装的物体称为骨骼,顶点绑定到骨骼上。当骨骼运动时,带动顶点运动。而模型摆成的双臂展开的姿势被成为T-Pose,又称为绑定姿势(bind position)。是模型制作时的默认姿势。之后在计算骨骼动画时,具有重要作用。
我们以模型的一只手臂的运动为例来讲解骨骼动画的原理。
假设手臂从绑定姿势B运动到目标姿势T,设骨骼j0,j1,j2。已知顶点v在绑定姿势下模型空间中的坐标
V
M
B
V
M
B
,各骨骼相对于父骨骼的位移和旋转,求顶点v在目标姿势下模型空间中的坐标
V
M
T
V
M
T
。
首先求出顶点v在j2骨骼空间的坐标。
骨骼的逆绑定姿势可以将顶点从模型空间变换到骨骼空间。即顶点v在模型空间的坐标左乘绑定姿势的逆变换矩阵BindPoses。
绑定姿势的逆变换矩阵又称为Bone OffsetMatrix,是T-Pose阶段,SkinMesh空间到某个骨骼空间的转换矩阵,用于将顶点从 SkinMesh空间转到骨骼空间矩阵。BindPoses在Unity里是bone.bindpose,是个Matrix4x4,包含平移、旋转、缩放,每个骨骼有自己的BindPoses。在3DMax中 模型坐标系不一定与世界坐标系重合,所以 BindPoses其实是一个复合的矩阵,包含顶点从Skinmesh空间变换到世界空间 * 从世界空间变换到某一个bone空间。
bindPoses[i] = bones[i].worldToLocalMatrix * transform.localToWorldMatrix;
在3Dmax制作过程中,在T-POSE阶段,程序已经帮我们计算出来结果了,存储于模型里的骨骼信息。
然后顶点在骨骼空间的坐标依次左乘,从绑定姿势运动到目标姿势过程中,各骨骼相对于父骨骼的变换矩阵,即可求出顶点v在目标姿势模型空间的坐标。其中Kj为蒙皮矩阵
在一些关节的连接处,一个顶点的位置可能同时受到多个骨骼的影响。这时使用加权的方式处理,即影响这个顶点的骨骼的蒙皮矩阵各乘以一个权重值,求出蒙皮矩阵的加权平均数再求出骨骼的目标位置。
权重和绑定姿势下顶点在模型空间的坐标是已知的。也就是说,我们只要计算出每根骨骼在每一帧的蒙皮矩阵K。就可以求出顶点在目标姿势的模型空间下的坐标。
我们将骨骼排好序,并记录骨骼序号。对于每个顶点,我们将影响其位置的骨骼序号和权重记录到顶点属性中。
在离线状态下,我们播放骨骼动画,按固定帧率记录每根骨骼的位置、旋转、缩放信息,并计算出该骨骼相对于父骨骼的TRS矩阵。用该骨骼的BindPoses矩阵,依次左乘各父骨骼的TRS矩阵,直到根骨骼。即可求出该骨骼在该帧的蒙皮矩阵K。并将这些蒙皮矩阵记录到一个纹理中。蒙皮矩阵是4x4的TRS矩阵,纹理中一个像素包含argb四个通道,可以存储TRS矩阵的一个列向量。由于TRS矩阵最后一列固定是(0,0,0,1),可以不必存储。所以我们用3个像素就可以存储1个蒙皮矩阵。
蒙皮矩阵在纹理中的排列格式如下:
蒙皮矩阵纹理类似于下面
在运行时,cpu将当前帧数传递给GPU。在GPU中每个顶点从自己的顶点属性中取出骨骼序号和权重。根据帧数、骨骼序号到纹理中取蒙皮矩阵的值,即可计算当前帧顶点在模型空间的位置。
由于使用MeshRenderer渲染,再配合GpuIntance即可实现相同骨骼动画实例的合批渲染。
比如地图中有50个士兵,士兵的DrawCall只有1个
如果Shader中使用UNITY_DEFINE_INSTANCED_PROP属性,为每个intance单独设置帧数𝑡,每个动画实例可以播放动画的不同帧。如果一张纹理中存储多个动画的蒙皮矩阵,通过设置不同的帧数𝑡,还可以实现每个动画实例播放不同的动画。这样可以避免军队动作过于整齐单一,同时还不影响合批。
性能对比
相比于普通骨骼动画,GpuSkinning+GpuInstance方案不但能提高渲染效率,还具有内存占用少,CPU消耗低等特点。因为普通骨骼动画每个动画实例的动画数据都要占用一份内存,而GpuSkinning+GpuInstance所有实例动画数据只占用一份内存。普通骨骼动画顶点的位置计算在CPU中完成,耗时随动画实例数量线性增长。GpuSkinning+GpuInstance计算在GPU中进行,GPU具有并行性。
2814

被折叠的 条评论
为什么被折叠?



