Render- Animation Instancing

『技巧 | 经验』 版权:禁止匿名转载;禁止商业使用。

894 0 0 2019-04-16 举报

CG素材

未设置职业

我们经常会通过使用GPU Instancing 来对一些户外的场景(如花草、树木)进行批量优化处理。但是对于游戏中的角色(绑有 SkinnedMeshRenderer 组件的对象),我们无法通过GPU Instancing 来优化,原因是大量的 skinning(蒙皮)计算发生在 CPU 中,然后相关顶点数据流逐个地被提交到 GPU 再进行渲染计算。一般情况下,CPU是无法一口气把所有的角色数据提交到渲染管线。当一个场景中有大量挂有SkinnedMeshRenderer的对象时,将会产生大量的Draw Call(简称DC) 和动画的计算。





原文的作者提供了一种方法来减少CPU环节的开销,这种技术称之为 “ Instancing”,通过对GPU Instancing的特性进行扩充。但是,这个解决方案还处于试验阶段。如果使用中有问题,欢迎猛戳 这里





目前来说,Animation Instancing 支持的特性包括:Root Motion, Attachment, Animation Events,暂不支持:Transitions(动画过渡),Animation Layer(动画层级)。此外,目前移动平台只支持 OpenGL ES3.0及更新的版本。








接下来,我们来看一下如何使用?





Animation Generation
在我们对角色进行 Instancing 之前,我们需要将角色的动画信息制作成纹理,这种纹理我们叫做Animation Texture(动画纹理),是GPU用来进行蒙皮所使用的纹理。





Animation Instancing 的 Generator窗口工具
这个生成器还支持从指定的GameObject对象所挂载的动画组件上收集动画数据以及动画事件。

当我们完成生成动画纹理后,Animation Instancing脚本会在运行时加载动画纹理。需要注意的是,这里的动画数据并不是animation clip动画片段。





Instancing
Animation Instancing脚本使用起来很方便,只需要将它挂在我们场景中要处理的对象上。其中Bone Per Vertex 这个参数用来控制每一个顶点缓存对应需要计算的骨骼数。这个参数越小,GPU的性能表现就越好,但是渲染出来的精度就越低。









Animation Instancing脚本


接下来,我们需要修改shader来使得它支持我们的Animation Instancing。其实,你只需要把下面两行代码加到你的shader中就可以。它不会影响你的shader工作,只是增加一个用来蒙皮的顶点着色器。





#include “AnimationInstancingBase.cginc” #pragma vertex vert

性能分析
我们可以通过unity提供的动画案例来进行测试,资源下载地址请见“Animation Instancing 工程源码”。

接下来,我们将它放到iphone6设备机上进行测试,并且看一下profiler视图上的对比数据





    CPU

一开始,我们在场景中放300个角色,而我们的FPS只有15帧。如果需要达到至少30帧的话,我们需要减少我们的角色数量到150。但是使用了Animation Instancing以后,我们在场景中放了900个角色,可以看到,帧数依然稳定在30帧。





未使用Instancing的效果






正如你所看到的,由于CPU的计算量导致了帧数下降。









使用了Animation Instancing的效果








使用了Animation Instancing以后,我们减少了动画部分的计算量(骨骼与蒙皮),这减轻了CPU大部分的开销,这样我们可以使用比原来多5、6倍的角色。

在刚才的测试场景中,周围场景的渲染大概在80个DC左右,每个角色由3个材质,也就意味着渲染一个角色至少要3个DC。





如果不使用Animation Instancing,我们放置250个角色,那么需要花费1100个左右的DC(3*250 角色 + 他们的阴影)。

当使用了Animation Instancing以后,即使放置800个角色,DC只有50个左右。因为,4800多个DC被合批到了48个batch(3*8 角色 + 3*8 阴影)中发送给GPU。基本上每1个batch包含了100个角色的渲染信息。













FrameDebugger信息对比
    GPU

这种技术稍微提高了GPU的开销,因为我们把蒙皮的处理放到了GPU环节。如果角色有阴影,我们就会在shadow pass中对角色再次进行蒙皮计算。这是一种权衡行为,由于这种情况,因为减少了CPU的开销而提高了帧率,收益大于损耗。






    内存

这种技术会占用一些额外的内存来存储 Animation Texture 动画纹理。这种纹理将蒙皮使用的数据以矩阵形式存储。纹理格式 我们使用 RGBAHalf。设想一下,如果一个角色有N根骨骼,每个骨骼占4个像素(一个矩阵);如果我们生成的动画有M关键帧,那么一个动画将花费N*4*M*2 = 8NM字节空间。如果一个角色有50根骨骼,生成的动画占30帧关键帧,一个动画将占用6000个像素(50*4*30),那么一张1024*1024的纹理可以存储174个动画数据。


重要的事情说三编,工程源码:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

让资源更有价值

  • Archiver|
  • 手机版|
  • 小黑屋|
  • CG素材网
  • 蜀ICP备18003526号-3
  • Powered by Discuz! X3.4
  • © 2001-2017 Comsenz Inc.
  • GMT+8, 2024-5-3 18:08 , Processed in 0.309827 second(s), 34 queries .

 关注CG资源素材

快速回复 返回顶部 返回列表