这个部分目的就是降Drawcall。
Unreal官方没有对这个部分做完整的说明,因此我这边会讲的较详细。主要分为两大部分,首先是静态合批,然后是4.23开始支持移动端的动态合批的使用。
静态合并
这个部分有三种合并方式,具体见开发工具
-
合并相同材质的多个对象为一个
使用:
如图所示我们在场景中放置两个对象,他们的材质是一样的。
这时候我们可以同时选中这两个对象,然后在Merge Actors面板,你就可以看到如下现象。在对参数做确认后即可合并对象。
最后会在资源管理器生成一个新的staticmesh对象。
-
直接合并多个对象为一个,生成新的材质
使用:
如图所示我们在场景中放置两个对象,他们的材质是不一样的。
这时候我们可以把他们合并成ProxyMesh
最终我们会生成一个完整的新对象,包括mesh和材质以及相对应的贴图。
-
静态合批,手动指定哪些对象作为一个批次绘制
这边则不是在修改资源,而是优化渲染的时候的操作。
默认情况下,我们在场景里面添加12个对象,那么绘制的时候就会有12条drawcall。
我们来尝试使用这个工具来做静态合批。
我们在场景里面选中所有的12个对象,打开merge actors界面,我们可以看到如下画面。
系统告知我们所有这些对象可以生成两个instanced static mesh对象,这两个新的instance对象会替代原来的12个静态网格。点击合并以后我们场景里面会增加一个新的InstancestaticMeshComponent对象,同时原有的静态网格对象默认则不显示。
这时候再点击运行画面,则绘制这12个对象我们就只用了两条Drawcall来实现。
上面的Instance选项中,有一个需要特别注意:
- UInstancedStaticMeshComponent(ISM):静态的模型Instance,即我们在书上和其它引擎中最常见的Instance形式——只有位置相异而mesh和材质均完全相同的物体可以合并成一个Actor,在理想情况下只提交一次DrawCall。ISM好处是DrawCall少,坏处是LOD计算,裁剪和OC等等都是按一个对象来做,往往ISM的Drawcall减少了,但提交渲染的三角形却更多了。
- UHierarchicalInstancedStaticMeshComponent(HISM):UE4中的HISM和ISM不同之处是它是基于分层实现。目的是为了满足一个Mesh有大量实例时分区域进行裁剪、计算LOD。UE中的植被就是HISM的子类。看到HISM大量的Console Variable都直接叫Foliagexxx…可以猜到的是HISM大概一开始是为植被系统所准备的。HISM的实现有两部分,一部分是构建分层(自动化的,每次修改它的instance个数、位置等都会触发)并保存到文件中,另一部分则是基于分层的可见性计算、LOD和渲染组织。
总结:通过这三个工具我们可以人为的精确控制场景内所有对象的绘制情况。但是如果对于超大场景的情况下,都这么去控制所有的对象,过程非常繁琐。
植被
Unreal 地形上面实现了一个植被对象 Foliage,用户可以直接拿笔刷刷植被,使用起来很方便。植被的对象数量一般来讲都会很大,因此Unreal的Foliage对象,在绘制的时候采用的就是 UHierarchicalInstancedStaticMeshComponent 这个组件来实现的,可以有效减少DrawCall的数量。
比如这边我们采用刷子刷了近万个方块在场景里。
全场景绘制的时候则是不到100条Drawcall。
动态合批
UE4在4.22中加入了Dynamic Instance功能,但由于RWBufferStructured在移动端未实现而不可用。在4.23时移动端解决了这个问题,在OpenglES3.1以上Feature的移动设备上,也能享受Dynamic Instance所带来的好处了。
做法:
找到项目的 Config 文件夹,为想要添加自动实例化的平台打开相应的 Engine.ini 文件。例如,对于Android编译,可使用 Config/Android/AndroidEngine.ini。
添加:
r.Mobile.SupportGPUScene=1
r.Mobile.UseGPUSceneTexture=1
官方说明:
实际测试:
我们建立了一个场景,一种相同的模型挂三种不同的材质,一共24个立方体。
默认移动平台的绘制:使用了24条Drawcall,每个方块各一条。
PC端,目前默认已经是完全采用了动态合批,上面同样的场景,绘制则是如下:
但是,目前我按照上面官方的讲法,去移动端开启这个功能的时候,绘制没有发生任何的变化,这点后面可能需要跟一下。
如果需要查性能啥的需要对这个机制的实现做了解,可以查看官方的说明:
https://docs.unrealengine.com/zh-CN/Programming/Rendering/MeshDrawingPipeline/index.html