[david]unity3d绘制调用批处理(draw call batching)

要绘制一个gameobject到屏幕上,unity需要调用图像api(dx,opengl)。
图像api对每一个绘制请求都需要做大量的工作,例如输入资源校验,顶点空间信息转换。
特别是在切换不同材质球的时候,图形api要做的工作更多,因为要 切换状态(透明,不透明,贴图输入,渲染方式,加载shader,调用gpu驱动api前,获取/组织/封装输入参数)。
而图形api(dx,opengl)是在cpu上运行的,所以draw call的调用会增加cpu负载,消耗cpu时间
(unity--draw call-->dx/opengl  || CPU  ||  -->显卡驱动|| GPU ||);

优化思路: 减少draw call 数量,减少状态切换
                每个mesh,每个材质,每个pass 都会产生一个draw call调用。
                所以,最有效的方法是合并mesh来减少draw call数量。
                unity有内置(好处:引擎代码层面可以独立控制每个物体)的两种合并mesh技术:
                    A:针对足够小的动态网格体,使用动态批处理(Dynamic batching),把类似的顶点分组,一次绘制。
                             限制:1、shader中最多使用 900个顶点属性(例如:vert函数输出中有vertex position,normal,uv三个属性,那么输入网格最多能有300个顶点,才能加入到动态批处理)(动态批处理的每个顶点都有开销)
                                     2、空间上存在镜像的多个物体不能一起使用动态批处理(例如:A物体的Transform_scale_x是1,B物体的Transform_scale_x是-1)
                                     3、使用不同的材质实例不能动态批处理,即使是同一材质的不同实例, 原因是阴影投射渲染的异常?    
                                     4、有附加渲染参数(lightmap index offset/scale)的光照贴图游戏物体。 通常动态光照贴图游戏物体应该指向定位在批处理里的相同光照贴图?
                                     5、多pass shader不能批处理。
                                                在前向(forward rendering)渲染模式中,unity shader 支持多灯光,附加像素光源对应的pass不能批处理。
                                                传统的延后(defferred(light pre-pass))渲染不支持批处理,因为延后渲染要绘制物体两次。
                               动态批处理要在CPU上将游戏物体的所有顶点变换到世界空间。这样变换的开销比图形api(dx,opengl )执行draw call的开销更小才有意义。
                                draw call要求的资源受很多因素影响,主要是dx/opengl api使用的资源。例如:主机或苹果平台上draw call的开销较小,动态批处理没有什么优势。
                    B:针对静态物体,合并成一个大网格体,叫静态批处理(static batching)
                          静态批处理会增加内存消耗。即使批处理前共享网格的N个物体,也会增加N-1份内存消耗。
                          例如:茂密的树林,标记为静态,使用静态批处理,就会有大量的内存消耗。这时可以考虑不标记为静态,消耗时间,节省内存开销
                            处理过程:将静态游戏物体转换到世界空间,
                                            创建一个大的顶点集( 64K 顶点数  和索引缓存(64K 索引数(48K opengles,32K macos));
                                            然后,对同意批次中的可见游戏对象,执行一系列简单的,几乎没有状态切换的draw call。
                                            技术上没有减少draw call 数量,当大量减少了 状态切换(dx/opengl重大开销的部分)
                这两种批处理技术能够减少的draw call数的一个重要因素是:合并的物体共享材质的程度。
                因为,不同材质不可能使用同一个draw call(排除阴影绘制)
                只有 共享材质的多个物体,合并成一个大网格体后,才能显著降低draw call数
                例如,10个共享材质(1个pass)的静态物体
                           没有使用静态批处理是10个draw call;
                            使用后为1个draw call,降低了90%的draw call 数。
                可使用批处理的渲染器:Mesh Renderers,Trail Renderers,Line Renderers,PaticleSystems,Sprite Renderers
                不能使用批处理的渲染器:skinned Meshes,cloth,other
                只有同类型的渲染器可以批处理。
                半透明物体比不透明物体更少的机会使用批处理,因为要从后到前的顺序获取半透明物体(确保透明效果),然后才批处理,顺序严格,获得批处理的机会更少。
                通过3d模型软件或Mesh.CombineMeshes手动合并相邻的网格物体是一个替换批处理的好方法。
                例如一个有多个绘制器的静态碗柜合并成一个网格是好的。
结论: 多个物体共享材质(合并贴图,shader减少pass,少分支判断语句),多标为静态物体,是有效减少draw call,state changes,进而减少图形api(dx,opengl)/CPU负载,同时降低GPU负载的有效途径。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值