优化学习_笔记_
知乎文章: Unity3D性能优化——渲染篇 作者:朔宇
UnityShader入门精要_冯乐乐
B站视频学习地址:【百人计划】图形 5.8 合批原理讲解
- 合批优化,
- overdraw优化,
- 带宽优化。
overDraw 特效部分讲过的 学习跳转链接:待添加
问题:什么是带宽?
什么是带宽的瓶颈?
我们在读取贴图,游戏模型,从内存拿东西的过程中,如果整个通道比较拥挤,
那么拿取到这块内存里的内容时,取出的速度就会很慢。 有着带宽的限制,从而导致下一步没办法执行。 常见带宽的优化方法,优化资源大小,贴图压缩,
合批:动态合批,静态合批
CPU设置渲染状态 (Set Pass call) 然后提交渲染命令(Draw call) ,将前两者提交给GPU(Batch)
当材质球产生切换,或者材质球才生pass的切换,会进行一次Set pass call (设置渲染状态)
通常一个Drawcall对应一个Batch,当做了优化之后,会出现多个DrawCall 对应一个Batch的情况
Set pass call相当于,在Ps里面进去了设置画布大小,分辨率等过程
DrawCall 是做的在画布里做了几个图片
Batch就相当于是从打开PS,设置,然后画画,保存,关闭的整个过程。
没有优化的话,每次打开PS,设置,画一张画,然后保存,关闭;
优化之后,打开一次PS,设置,画了很多张画,然后一起保存,关闭。
实时运行时 做Mesh合批的处理
通过把细碎的,少量的同材质的Mesh,从CPU提交到GPU之前,由CPU快速合并为一个大的Mesh,一起提交给GPU的方式
一般适用于一些动态生成的少量Mesh,动态生成的面片
比如说,粒子特效:生成的闪电面片,生成镜头光晕等等,都可以通过动态合批的方式进行优化。
这里的动态,是指实时的动态合并。
动态批处理是一种绘制调用批处理方法,将移动的游戏对象进行批处理以减少绘制调用次数。
动态批处理在Unity动态生成的网格和几何体之间的工作方式有所不同,例如粒子系统。
有关网格和动态几何体之间内部差异的信息,请参阅网格的动态批处理和动态生成几何体的动态批处理。
注意:网格的动态批处理是为了优化旧的低端设备上的性能而设计的。在现代消费硬件上,动态批处理在CPU上的工作量可能大于绘制调用的开销。这对性能产生负面影响。有关详细信息,请参阅网格的动态批处理。
使用动态批处理
要将网格使用动态批处理,您可以按照以下步骤进行操作:
- Go to Edit > Project Settings > Player.
- In Other Settings, enable Dynamic Batching.
- 如果移动网格满足常见使用信息中描述的条件,Unity 会自动将移动网格批量到同一绘制调用中。
网格的动态批处理
对于网格的动态批处理,是通过将所有顶点转换为世界空间进行的,而这是在CPU上完成的,而不是在GPU上。这意味着,动态批处理只有在变换工作比执行绘制调用更轻资源密集时才是一种优化。
绘制调用的资源需求取决于许多因素,主要是图形API。 例如,在主机或现代API(如Apple Metal)上,绘制调用的开销通常较低,动态批处理通常不会提供性能增益。 要确定在您的应用程序中使用动态批处理是否有益,请使用和不使用动态批处理对应用程序进行性能分析。
Unity可以对投射阴影的动态批处理进行使用,即使它们的材质不同,只要Unity在阴影通道所需的材质值相同即可。 例如,多个箱子可以使用具有不同纹理的材质。尽管材质资源不同,但这种差异对于阴影投射器通道是无关紧要的,Unity可以在阴影渲染步骤中对箱子游戏对象的阴影进行批处理。
动态生成几何体的动态批处理
以下渲染器会动态生成几何体,比如粒子和线条,您可以使用动态批处理进行优化:
与对网格的动态批处理不同,对于动态生成的几何体,Unity的动态批处理工作方式如下:
- 对于每个渲染器,Unity将所有可以进行动态批处理的内容构建成一个大的顶点缓冲区。
- 渲染器为批处理设置材质状态。
- Unity然后将顶点缓冲区绑定到GPU。
- 对于批处理中的每个渲染器,Unity更新顶点缓冲区中的偏移量并提交新的绘制调用。
这种方法类似于Unity如何为静态批处理提交绘制调用。
Draw call batching_Unity官方文档(英文)_跳转链接
Draw call batching 是一种绘制调用优化方法,它合并了网格,使得 Unity 能够以更少的绘制调用来渲染它们。Unity 提供了两种内置的绘制调用合并方法:
- Static batching: 对于静态的 GameObject,Unity 将它们合并并一起渲染。
- Dynamic batching: 对于足够小的网格,它在 CPU 上转换它们的顶点,将相似的顶点组合在一起,并在一个绘制调用中渲染它们。
Unity 的内置绘制调用合并相对于手动合并网格具有一些优势,最显著的是 Unity 仍然可以单独剔除每个网格。然而,它也有一些缺点:静态合批会产生内存和存储开销,而动态合批会产生一些 CPU 开销。
Using draw call batching
以下的使用信息对于静态和动态合批都是相关的。有关每种绘制调用合并方法的特定信息,如如何启用和使用每种方法,请参阅静态合批和动态合批。
Mesh Renderers、Trail Renderers、Line Renderers、Particle Systems 和 Sprite Renderers 都支持绘制调用合并。不支持其他类型的渲染组件,包括 Skinned Mesh Renderers 和 Cloth。Unity 仅合批相同类型的 Renderers,例如 Mesh Renderers 与 Mesh Renderers。
Unity 合批使用相同材质的 GameObject 的绘制调用。这意味着为了从绘制调用合并中获得最佳结果,请在尽可能多的 GameObject 之间共享材质。如果有两个除了纹理外完全相同的材质资源,可以将纹理合并成单个更大的纹理。这个过程被称为纹理图集。有关更多信息,请参阅维基百科上关于纹理图集的文章。当纹理在同一个图集中时,可以使用单个材质资源。
在内置渲染管道中,可以使用 MaterialPropertyBlock 来更改材质属性而不破坏绘制调用合并。 CPU 仍然需要进行一些渲染状态的更改,但使用 MaterialPropertyBlock 比使用多个材质更快。如果您的项目使用脚本渲染管道,请不要使用 MaterialPropertyBlock,因为它们会删除材质的 SRP Batcher 兼容性。
Transparent shaders 通常需要 Unity 以从后到前的顺序渲染网格。为了批处理透明网格,Unity 首先将它们从后到前排序,然后尝试将它们合并。由于 Unity 必须以从后到前的顺序渲染网格,它通常不能批处理与不透明网格一样多的透明网格。
Unity 无法对包含在其 Transform 组件中具有镜像的 GameObject 应用动态合批。例如,如果一个 GameObject 的比例为 1,另一个 GameObject 的比例为 –1,则 Unity 不能将它们合并。
如果无法使用绘制调用合并,手动合并靠近的网格可能是一个不错的替代方法。有关合并网格的更多信息,请参阅合并网格。
警告:当您从 C# 脚本访问共享材质属性时,请确保使用 Renderer.sharedMaterial 而不是 Renderer.material。 Renderer.material 会创建材质的副本并将副本分配回 Renderer。这会阻止 Unity 合批该 Renderer 的绘制调用。