静态合批

引自:关于静态批处理/动态批处理/GPU Instancing /SRP Batcher的详细剖析 - 知乎 (zhihu.com)

在inspector面板的static打钩,在Build的时候Unity会自动提取这些共享材质的模型的Vertexbuffer和indexbuffer,将这些数据变换到世界空间下,存储在新构建的大VertexBuffer和IndexBuffer中(内存占用翻倍),并且记录每一个子模型的Index buffer数据在构建的大Index buffer中的起始及结束位置。

 

在后续的绘制过程中,一次性提交整个合并模型的顶点数据,根据引擎的场景管理系统判断各个子模型的可见性。然后设置一次渲染状态,调用多次Draw call分别绘制每一个子模型。

或者手动调用 StaticBatchingUtility.Combine(tranHexHolder.gameObject);,在运行时静态合批(对单个物体的shader参数有修改会打断合批),可以在在刷新完所有物体材质状态后再次调用。

调用这个API会将绑定物体的所有子物体的网格合并成一个(不考虑material),但setpasscall还是分成多个,unity还提供了一个可以自己设置哪些物体合并的接口:

StaticBatchingUtility.Combine(GameObject[] gos, GameObject staticBatchRoot); 感觉把相同材质的mesh合并才是最优的,但实测setpasscall略有降低,batch升高很多,要根据项目情况选择哪种方式。

在静态合批后更改材质参数(shader),或者重新赋材质无需重新调用合批函数(网格只需要生成一次),unity会自己根据相同的材质分批发送drawcall,比如合批后十个物体共享两个材质,drawcall显示的2,在运行时将十个物体的材质换成一个,那drawcall显示的是1。

与直接使用大网格的不同

1.静态合批可以主动隐藏部分对象。静态合批在运行时,由于每个参与合并的对象可以通过起始索引等彼此区分,因此可以通过上述多次Drawcall的策略,实现隐藏指定的对象,而大网格不可以。

2.静态合批可以有效参与CPU的视锥剔除。剔除后,被送进渲染管线的顶点数量就会减少,也就意味着顶点着色器处理的顶点会减少,而使用大网格渲染时,由于整个网格都会被送进渲染管线,因此每一个顶点需要被顶点着色器处理,如果摄像机智能照到一点点,那么绝大多数参与计算的顶点都会被裁减掉,有一些浪费。

合批条件:

1.合批的物体不能移动旋转缩放,(更改材质参数会导致创建一个新的材质实例,虽然不会重新创建网格,但会增加drawcall),但是staticBatchRoot 可以移动。

2.只有使用同一材质球实例的物体可以合批。

3.合并后的顶点数最大65535,超过就会自动分成多个。

4.导入的模型需要开启可读写。

原理:

优化点:并不减少drawcall,由于预先把所有子模型的定点变换到世界空间下,运行时cpu不需要再次执行定点变换操作,节约了少量的计算资源,并且这些子模型共享材质,所以在多次drawcall调用间没有渲染状态的切换,commaderbuffer会缓存命令统一传给gpu,起到渲染优化的目的。

 

commaderbuffer动态图:【Unity游戏开发】合批优化汇总 - 知乎 (zhihu.com)

posted @   mc宇少  阅读(165)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示