GPU 加速动画渲染方案
GPU Animator 解决的问题
同屏动画太多导致的 CPU 蒙皮计算压力太大。比如 MOBA 类游戏的几十个小兵,或者竞技场周围的吃瓜群众等等,
这些动画一般不需要很好的效果,可以尝试使用多种优化手段来降低效果(也可以保持效果基本不变)、占用内存、消耗GPU 来降低 CPU 的压力。
GPU Animator 原理
有两种 GPU 加速模式:
- 缓存每一帧顶点坐标,顶点着色器根据帧数和顶点编号获取顶点数据进行渲染,此为方案 A;
- 缓存每一帧骨骼变换矩阵,顶点着色器计算蒙皮,此为方案 B;
方案A
Step1 编辑器每帧运行 AnimationClip,获取转换后的顶点坐标保存到数组中,根据数组长度计算需要的 Texture 最小尺寸,(Texture用来保存顶点数据)。
然后把顶点数据 xyz 当成 rgb,保存到 Texture 中,保存成引擎可以支持的任意资源格式都可以。
Step2 运行时,设置我们想要播放动画的速度,Update 驱动帧 CurrentFrame,计算顶点的开始 Index,设置给 Shader,
Step3 Shader 渲染部分,
SV_VertexID,我们用他来区分每一个顶点,加上我们上一步计算的出来的 PixelIndex,就是我们 Vertex 的坐标,如何转成 UV 呢?
根据我们顶点保存的规则,来计算,很简单,如下
获取 UV 之后,根据 UV 坐标取我们计算好缓存起来的 vertex 坐标输出到片段着色器中。
这个方案:
- 优点几乎不占用cpu和gpu消耗;
- 缺点动画文件体积较大(30帧左右,大概3M大小);
方案B
Step1 类似方案A,记录每一帧的关节 matrix,使用三个 rgb 来保存 matrix 的三行。
最后保存到 Texture 里,不一样的一点是,需要保存一个新的 Mesh 文件,因为骨骼的顺序必须和我们保存的 Texture 对应上。
Step2
perFramePixelsCount,上文我们讲了需要三个像素。totalJoints,是我们Mesh的总关节数。同样的,Update 驱动帧 CurrentFrame。
Step3 Shader 渲染部分,
根据设置的 StartPixelIndex,取Matrix,然后计算顶点、法线等
这个方案:
- 优点动画文件体积比原生动画文件还小,不占用CPU,GPU计算蒙皮;
- 缺点GPU压力;
总结
处理大规模角色,同时不要求动画效果很精细,内存够用的情况,可以采用方案A。
处理逻辑压力大、CPU消耗多并且渲染压力小的情况,可以选择方案B。
For more details see
GPUAnimatorPlugin