静态合批和动态合批

news/2024/10/6 3:18:45/文章来源:https://www.cnblogs.com/Zhaolongtao/p/18444231

动态合批与静态合批其本质是对将多次绘制请求,在允许的条件下进行合并处理,减少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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/806789.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

05-LoadBalancer负载均衡

1.Ribbon目前也进入维护模式 1.1 Ribbon介绍 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时,重…

PbootCMS错误提示:执行SQL发生错误!错误:no such column: def1

问题描述 在PbootCMS v3.0.5及以下版本升级到v3.0.6后,后台栏目管理操作中出现提示:“执行SQL发生错误!错误:no such column: def1”。原因是升级过程中 SQL 语句未执行成功,导致程序报错。 解决方案手动执行SQL脚本下面是适用于SQLite数据库的升级脚本,用于添加缺失的字…

pbootcms编辑器过滤div代码解决办法

在使用PbootCMS建站时,如果需要在专题内容中加入含有HTML代码的文字,但发现编辑器将 div 标签转换成了 p 标签,可以通过以下步骤进行修改。 修改步骤修改 ueditor.all.js 文件找到 core->extend->ueditor->ueditor.all.js 文件。 在大约第 10830 行,将 allowDivTr…

PbootCMS如何重置程序后台的文章id,从1开始

在 PBootCMS 中,如果你需要重置程序后台的文章 ID 使其从 1 开始,可以使用 SQL 语句来实现这一目标。以下是一个详细的步骤说明和示例 SQL 语句。 步骤说明备份数据库:在执行任何操作前,务必先备份数据库,以防数据丢失。清空文章表:使用 TRUNCATE 语句清空文章表。重置自…

PbootCMS建站系统怎么修改域名授权提示信息

在 PBootCMS 中,如果你上传网站到服务器后使用域名访问,但没有获取到官方的域名授权码,系统会提示未授权的相关信息。为了避免客户看到这些提示信息,官方提供了一个简单的解决方案,即在网站根目录下创建一个 sn.html 文件,并编写自定义的提示信息。 解决方案创建 sn.html…

pbootcms修改后台文章显示最大数量

如果你想修改 PBootCMS 后台文章列表每页显示的数量,可以通过修改后台相关代码来实现。以下是具体的步骤和示例代码。 步骤打开相关文件:打开文件 \APPs\admin\view\default\content\content.html。修改每页显示数量:在文件中搜索 “每页显示数量”,找到对应的代码片段,并…

解决 PBootCMS 网站迁移后出现的 “No input file specified” 错误

1. 检查 .user.ini 文件进入网站根目录:使用 FTP 客户端或 SSH 连接到服务器,进入网站根目录。查找 .user.ini 文件:使用命令 ls -la 查看隐藏文件。shls -la删除 .user.ini 文件:如果存在 .user.ini 文件,删除它。shrm .user.ini2. 重启服务器重启 Apache 服务:使用以下…

找到并修复 SQL 脚本中的重复字段问题。确保每个字段定义唯一,避免出现 duplicate column name 的错误

假设你的 SQL 脚本如下:-- 创建表 CREATE TABLE articles (id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255) NOT NULL,content TEXT,picstitle VARCHAR(255),picstitle VARCHAR(255) -- 这里重复了 picstitle 字段 );-- 插入数据 INSERT INTO articles (id, title, co…

准确地判断用户是否登录,并避免由于 Cookie 过期但仍显示已登录的问题

在 PBootCMS 中,判断用户是否登录通常使用 {pbOOT:ISLOGIN} 标签。然而,如果发现该标签不够准确,尤其是在本地 Cookie 已经过期但仍然显示已登录的情况,可以通过更精确的方式来判断用户登录状态。 解决方案检查 Session 和 Cookie:确认用户的 Session 和 Cookie 是否有效。…

PBOOTCMS判断登录是否登录代码

修改控制器文件:在 IndexController.php 文件中添加 isUserLoggedIn() 方法,用于判断用户是否登录。修改模板文件:在模板文件中引入控制器类,并实例化控制器对象。 使用 isUserLoggedIn() 方法来判断用户是否登录,并输出相应的信息。优点更准确的判断:通过检查 Session 和…

pbootcms自动清理runtime缓存文件释放你的空间压力

在使用 PBootCMS 配合阿里云虚拟主机时,确实可能会遇到运行时缓存文件过多的问题。以下是一种解决方案,通过自动清理缓存文件来解决这一问题。 步骤一:修改 ExtLabelController.php 文件打开文件:打开 apps/home/controller/ExtLabelController.php 文件。添加清理脚本:在…

中缀表达式和后缀表达式

算术表达式中缀表达式转后缀表达式栈的深度 栈的深度就是指栈中元素的个数 后缀表达式求值