首页 > 其他分享 >静态合批和动态合批

静态合批和动态合批

时间:2024-10-01 22:44:20浏览次数:10  
标签:合批 缩放 静态 物体 批处理 顶点 动态

动态合批与静态合批其本质是对将多次绘制请求,在允许的条件下进行合并处理,减少cpu对gpu绘制请求的次数,达到提高性能的目的。

两者是否开启都可以在Project Settings -> Player -> Other Settings 下的 Static Batching 和 Dynamic Batching

1.静态合批是将静态(不移动)GameObjects组合成大网格,然后进行绘制。静态合批使用比较简单,PlayerSettings中开启static batching,然后对需要静态合批物体的Static打钩即可,unity会自动合并被标记为static的对象,前提它们共享相同的材质,并且不移动,被标记为static的物体不能在游戏中移动,旋转或缩放。但是静态批处理需要额外的内存来存储合并的几何体。注意如果多个GameObject在静态批处理之前共享相同的几何体,则会在编辑器或运行时为每个GameObject创建几何体的副本,这会增大内存的开销。例如,在密集的森林级别将树标记为静态可能会产生严重的内存影响。此时就必须去权衡利弊,为了更少的内存占用,可能需要避免某些GameObjects的静态批处理,尽管这必须要牺牲一定的渲染性能。
静态合批在大多数平台上的限制是64k顶点和64k索引(OpenGLES上是48k索引,macOS上是32k索引)。

2.动态合批是将一些足够小的网格,在CPU上转换它们的顶点,将许多相似的顶点组合在一起,并一次性绘制它们。
无论静态还是动态合批都要求使用相同的材质,动态合批有以下限制:

  • 动态合批处理动态的GameObjects的每个顶点都有一定的开销,因此动态合批处理仅应用于包含不超过900个顶点和不超过300个顶点的网格。

    • 如果shader中使用Vertex Position, Normal和single UV,可以批量处理最多300个顶点,而如果shader中使用Vertex Position, Normal, UV0, UV1和Tangent,则只能使用180个顶点。
    • 注意:将来可能会更改属性计数限制。
  • 如果GameObjects在Transform上包含镜像,则不会对其进行动态合批处理(例如,scale 为1的GameObject A和scale为-1的GameObject B无法一起动态合批处理)。

    • 为了验证此说法,笔者亲自做了测试,对于两个同样的物体:
      a.一个物体保持scale为(1,1,1),改变另一个物体的scale:
      1).当三个轴向的缩放值为负数(简称负缩放)的个数为偶数时可以合批处理,即scale为(1,1,1)和scale为(-1,-2,3)、(-1,2,-3)、(2,-3,-4),此时三个轴向的负缩放的个数为0个、2个、2个和2个,均为偶数个,可以合批处理,注意正负号,缩放数值可以随便更改;
      2).当三个轴向的负缩放的个数为奇数时可以不能合批处理,即scale为(-1,1,1)、(1,-2,3)、(1,2,-3)和(-2,-3,-4),此时三个轴向的负缩放的个数为1个、1个、1个和3个,均为奇数个,不可以合批处理。
      b.同时改变两个物体的缩放,仍然符合上述的三个轴向的负缩放的个数为奇数个时不合批,偶数个时合批:
      1).A物体(1,2,3),B物体(-1,2,3)、(1,-2,3)、(1,2,-3),奇数个负缩放不合批
      2).A物体(-1,2,3),B物体(-1,2,3),奇数个负缩放不合批,其他组合类似
      3).A物体(-1,-2,3),B物体(1,2,3)、(-1,2,-3),偶数个负缩放,其他组合类似
      总结为:对于两个相同的物体,当两个物体三个轴向的负缩放的个数为偶数个时(0个,2个),可以合批,当两个物体中任意一个物体或者两个物体同时三个轴向的负缩放的个数为奇数个时,不合批。此前有很多文章说对于不同缩放的物体,无论是否为负缩放,均不会合批处理,笔者使用的unity版本是unity2019.1.7f1,可能是因为unity在某个版本已经修复了该问题,有知道的朋友,请告知一声,谢谢。
  • 使用不同的Material实例会导致GameObjects不能一起批处理,即使它们基本相同。阴影渲染(shadow caster)是一个例外,下文会解释为什么。

  • 带有光照贴图的GameObjects有额外的渲染器参数:保存光照贴图的索引和偏移/缩放。一般来说,动态光照贴图的GameObjects应指向完全相同的光照贴图位置才能被动态合批处理。

  • 使用多个pass的shader不会被动态合批处理。

    • 几乎所有Unity Shaders在forward rendering(前向渲染)中都支持多个灯光 ,为了他们有效地进行额外的传递。额外的pre-pixel lights的绘制调用不会被动态合批处理,这个在移动平台上比较少遇到。
    • The Legacy Deferred (light pre-pass) rendering path 中禁用动态批处理,因为它必须绘制两次GameObjects。

github 上Unity官方总结了25种不能被合批处理的情况, Unity-Technologies/BatchBreakingCause

动态合批处理的工作是在cpu上将所有GameObject顶点转换到世界空间,因此,如果该工作小于执行绘制调用,则这是一个优势。绘制调用的资源需求取决于多方面的因素,主要是使用的图形API。例如,在 consoles or modern APIs,比如Apple Metal,绘制调用开销通常要低得多,此时动态合批处理就不再是优势了,所以动态合批处理并不是万能的啊。

动态合批处理(Particle Systems, Line Renderers, Trail Renderers)
对于Unity动态生成的几何体的组件,动态合批处理与网格相比有不同的工作方式。

  • 对于每个兼容的渲染器类型,Unity将所有可混合内容构建为1个大型顶点缓冲区(Vertex Buffer)。
  • 渲染器为批处理设置材质的状态。
  • Unity将顶点缓冲区(Vertex Buffer)绑定到图形设备。
  • 对于动态合批处理中的每个渲染器,Unity将偏移更新到顶点缓冲区(Vertex Buffer),然后提交新的绘制调用。

在评估图形设备调用的成本时,渲染组件的最慢部分是材质状态的设置。相比之下,将不同的偏移绘制调用提交到共享顶点缓冲区的速度非常快。

注意:
1.不同材质的阴影会动态合批,只要绘制阴影的 pass是相同的,因为阴影跟其他贴图等数据无关
2.目前,只有 Mesh Renderers, Trail Renderers, Line Renderers, Particle Systems和Sprite Renderers支持合批处理,而skinned Meshes,Cloth和其他类型的渲染组件不支持合批处理。
3.渲染器仅与其他相同类型的渲染器进行合批处理。
4.对于半透明的GameObject,按照从前到后的顺序绘制,Unity首先按这个顺序对GameObjects进行排序,然后尝试对它们进行批处理,但由于必须严格满足顺序,这通常意味着对于半透明的材质更少使用合批处理。
5.手动的合并GameObject是代替合批处理的好办法,比如使用Mesh.CombineMeshes,或者直接在建模时将多个网格合并成单个网格。

 转载>>>>>>>>>>>>>>>>>>>https://www.jianshu.com/p/a3087f31ff88

标签:合批,缩放,静态,物体,批处理,顶点,动态
From: https://www.cnblogs.com/Zhaolongtao/p/18444231

相关文章

  • PbootCMS伪静态怎么设置?(PbootCMS模板安装后内页打开404错误的解决方法)
    1.后台配置参数-URL规则选择伪静态模式登录PbootCMS后台。进入“系统设置”或相应的配置管理界面。在URL规则设置中选择“伪静态模式”。保存设置。2.根据服务器环境添加伪静态规则Apache环境:将网站根目录下的.htaccess文件复制到根目录。确认.htaccess文件内容正......
  • 动态规划
    动态规划这一篇完全写不完,只能把今天回顾的内容记录一遍,所以之后肯定会补充。概念性知识(使用条件)最优子结构即:一个情形面前只有有限个抉择,那么要想让当前得到的结果最优,那么一定会去贪心地做出选择。无后效性把问题划分成阶段,那么按照逻辑顺序,当前阶段的决策不会受到之后所......
  • 反射 动态代理
    出自https://www.bilibili.com/video/BV1ke4y1w7yn1.反射1.1反射的概述:​ 专业的解释(了解一下):​是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;​对于任意一个对象,都能够调用它的任意属性和方法;​这种动态获取信息以及动态调用对......
  • 每日OJ题_牛客_DP2跳台阶_动态规划_C++_Java
    目录牛客_DP2跳台阶_动态规划题目解析C++代码Java代码牛客_DP2跳台阶_动态规划跳台阶_牛客题霸_牛客网题目解析        当前值只和数组的前两个值有关,在往前面的就无关了,所以没必要申请一个数组,直接使用两个变量即可,这样空间复杂度就满足要求了。C++代码......
  • [rCore学习笔记 028] Rust 中的动态内存分配
    引言想起我们之前在学习C的时候,总是提到malloc,总是提起,使用malloc现场申请的内存是属于堆,而直接定义的变量内存属于栈.还记得当初学习STM32的时候CubeIDE要设置stack和heap的大小.但是我们要记得,这么好用的功能,实际上是操作系统在负重前行.那么为了实现动态内存分配功......
  • leetcode刷题day34|动态规划Part03 背包问题(01背包问题 二维、01背包问题 一维、416.
    0-1背包问题二维动规五部曲1、确定dp数组以及下标的含义dp[i][j]表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。(取物品时可以是取0-i的任意一个,或者是他们的组合)2、确定递推公式不放物品i:背包容量为j,里面不放物品i的最大价值是dp[i-1][j]......
  • leetcode刷题day33|动态规划Part02(62.不同路径、63. 不同路径 II、 343.整数拆分、96.
    62.不同路径机器人从(0,0)位置出发,到(m-1,n-1)终点。动规五部曲1、确定dp数组(dptable)以及下标的含义dp[i][j]:表示从(0,0)出发,到(i,j)有dp[i][j]条不同的路径。2、确定递推公式想要求dp[i][j],只能有两个方向来推导出来,即dp[i-1][j]和dp[i][j-1]。dp[i]......
  • jdk动态代理
     1.定义接口2.实现接口的具体类3.创建InvocationHandler实现importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;publicclassMyInvocationHandlerimplementsInvocationHandler{privateObjecttarget;publicMyInvocationH......
  • JavaScript 网页设计案例 简单的电商案例 页面切换 数据搜索 动态网页
    JavaScript网页设计案例简单的电商案例页面切换数据搜索动态网页1.案例描述以下是一个简单的产品展示网页,用户可以通过点击不同的产品类别按钮来查看相应的产品,且在鼠标悬停时显示产品详情。页面还将包含一个搜索框,用户可以输入关键词来筛选产品。2.文件结构-......
  • 数据通信——动态路由协议RIP
    目录一.动态路由协议分类二.距离矢量路由协议(理解)三. 链路状态路由协议(理解)四.RIP的工作原理五.路由表的形成过程 六.RIP的度量值(条数)cost七.RIP的版本(v1和v2)八.RIP解决路由环路(2)水平分割:从一接口上学到的路由信息,不会再从这个接口上发出去(3)毒性逆转(与水平分割......