Unity drawcall批处理

爷,独闯天下 提交于 2020-01-18 23:57:09

一、我们为什么要做DrawCall批处理

什么是drawcall,当我们需要绘制一个物体时,就需要调用底层的图形接口,如OpenGL,DX等;也就是在CPU收集完物体的数据信息后向GPU发起调用的一个过程,过多的drawcall就会造成CPU的性能瓶颈;

Unity提供了两种技术来处理

  • 动态批处理:对足够小的网格,它在CPU层自动转换它们的坐标,将许多顶点组织到一起然后一次绘制;
  • 静态批处理:合并静态也就是不需要移动的游戏对象,合并成一个大的网格,然后快速绘制;

两种批处理的方式都各有负面影响,动态批处理使用不当可能会引起CPU瓶颈,而静态批处理则会造成内存性能问题;

二、批处理中的材质设置

只有当游戏对象拥有相同的材质时,他们才有可能进行合批处理,所以,如果想要进行合批,就需要在尽可能多的游戏对象中共享材质;

如果有两个相同的材质,但是它们纹理不同,这时可以通过合并纹理的方式来解决;一旦纹理在同一个图集中,就可以使用单个材质来完成;

如果需要从脚本中来获取材质信息,那么一定要使用Renderer.sharedMaterial,因为Renderer.material会创建材质的拷贝;

三、动态批处理

Unity可以用同一个drawcall自动批处理移动的游戏对象,前提是它们材质相同并满足一定规范;动态批处理是自动完成的;

  • 合批动态游戏对象需要顶点有限制,网格不得多于900个顶点属性,不得多于300个顶点;如果shader使用了顶点坐标,法线以及UV,则顶点上线为300,如果包含了UV0,UV1和切线等,顶点上线为180;
  • 如果两个游戏对象的transform里包含镜像,则不能合批;
  • 多pass的shader会打断合批

动态批处理是通过将所有的游戏对象在CPU转换到世界空间下,所以只有当这个转换到代价低于drawcall的代价时,它才是有利的;

Dynamic batching(),Particle Systems,Line Renderers,Trail Renderers

  • 对每个兼容的类型,unity会将所有批处理的内容放置到一个大的顶点缓冲区
  • 然后renderer会为合批设置材质状态
  • unity将会绑定顶点缓冲区到图形设备
  • 对每个batch中的renderer,unity会将偏移更新到Vertex Buffer,然后提交一个新的drawcall

参考:知乎-聊聊batch的前世今生

四、静态批处理

静态批处理允许引擎去减少任何大小的几何体的drawcall,只要它共用相同的材质而且不移动;它比静态批处理更高效,因为它不在CPU层做顶点的变换,但是它使用更多的内存;

为了使用静态批处理,我们需要特意标记某个对象是静态的,而且是不能移动的、旋转和缩放的;

但是使用静态批处理要求额外的内存消耗来存储合并的几何体,它的原理是通过转换静态对象到世界空间中,然后建立一个共享的顶点和索引缓冲;

五、其它

1.半透明物体的合批

半透明物体要求对象是从后向前进行渲染的,unity首先会按照顺序对游戏对象进行排序,然后尝试合批,因为需要严格满足渲染顺序,所以半透明物体通常要比不透明物体少很多合批;

2.SpriteRenderer

为什么一个SpriteRenderer材质可以赋值不同的纹理,我们可能有n个不同的spriterenderer对象,有不同的sprite,但是材质只有一个?

MaterialPropertyBlock is used to modify these values

在Sprite Renderer组件下,我们有时会看到如上提示,原因是Sprite Renderer的材质使用了MaterialPropertyBlock去给材质赋予纹理,默认的sprite shader会隐藏_MainTex属性,所以在材质上看不到纹理的槽位;

参考:Unity-Forums:Why do I have "MaterialPropertyBlock is used to modify these values" on all materials?

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!