UGUI优化篇--UGUI合批

UGUI合批

  • UGUI合批规则概述
  • UGUI性能查看工具
  • 合批部分的特殊例子
    • 一个白色image、蓝色image覆盖了Text,白色image和Text哪个先渲染
  • Mask合批
    • Mask为什么会产生两个drawcall
    • Mask为什么不能合批
    • Mask注意要点
  • RectMask2D
    • 为什么RecMask2D比Mask性能更好
    • 主要代码
    • RectMask2D注意要点
  • 根据应用场景选择使用哪个(Mask、RectMask2D)
    • 只需要一个遮罩
    • 需要多个遮罩,遮罩下有多个子物体

UGUI合批规则概述

  1. 遍历所有UI元素

  2. 根据深度Depth(优先级最高,-1表示不用渲染)、材质ID、图片ID、渲染顺序对所有UI进行排序

  3. 进行合批处理,比如UI1和UI2(两者必须是紧挨着的)是相同材质、相同图片就可以进行合批,如果UI1和UI2之间有一个中间层UI3(根UI1和UI2材质不同),就会打断合批
    在这里插入图片描述

  • Text必须文字的网格覆盖到image上面才算相交,Rect Transform框框相交不算
  • 白色image的深度为0,最先渲染,然后判断Text是否相交,再判断材质ID和图片ID是否相同,如果相同则可以合批,因为不相同,所以Text深度为白色image+1为1(如果Text底下有很多image,则取最大的深度+1)
  • 红色image因为底下有Text和白色image,所以计算出两个深度值分别1和0,取最大值加1,就是2
  • 黄色和蓝色image会进行合批测试操作,深度值都是2(这里只是测试是否能合批,并还没有真正合批)
  • 最后会得到一个排序数组list并把所有深度为-1的值剔除掉,0、1、2、2、2,传给合批部分的程序进行合批操作,判断相邻的元素是否能进行合批,通过判断数组的值是否相等

UGUI性能查看工具

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

合批部分的特殊例子

一个白色image、蓝色image覆盖了Text,白色image和Text哪个先渲染

在这里插入图片描述

  1. 根据分析工具可以看到白色image先渲染,文本后渲染(白色图片ID小一点)
  2. 这样得到的数组list,会先是白色image、Text、蓝色image,导致白色和蓝色无法合批
  3. 解决办法是把白色image和蓝色image赋值同一个texture
    在这里插入图片描述
  4. 只要是满足合批条件,合批数组紧挨着,虽然没有覆盖,也可以合批
  5. 能不能合批,在最后合批数组上才能决定

Mask合批

  1. mask无法跟mask外的物体进行合批,但是mask之间可以合批

  2. mask本身会产生两个drawcall,性能损耗

Mask为什么会产生两个drawcall

  1. 第一个drawcall是mask在设置模板缓存产生的
  2. 第二个drawcall是mask在还原模板产生的
  3. mask之间可以进行合批,设置模板缓存和还原模板时候,因为图片ID和材质是一样的,所以可以合批
  4. 设置模板缓存时候,会把需要显示部分的缓存值设置为1,遮罩的部分设置为0,在渲染的时候会取出我存在当前像素当中的一个模板缓存值,然后判断它呢是否为一。如果为一的话,才进行渲染,如果不为一,就不不渲染了
  5. 每一个像素点上,创建了一个这样类似于一个数据缓存,通过它的模板缓存值来判断是否显示,都是像素级别的单位
  6. 模板还原也要产生一次drawcall,把每个像素点的模板缓存清除

Mask为什么不能合批

因为Mask会产生一个特殊的材质,材质不同就不能合批
在这里插入图片描述

    public virtual Material GetModifiedMaterial(Material baseMaterial){if (!MaskEnabled())return baseMaterial;var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas);if (stencilDepth >= 8){Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObject);return baseMaterial;}int desiredStencilBit = 1 << stencilDepth;// if we are at the first level...// we want to destroy what is thereif (desiredStencilBit == 1){// StencilMaterial.Add是最主要的方法,这里添加了特殊的材质,因为材质不同,所以不能和mask外的物体合批var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0);StencilMaterial.Remove(m_MaskMaterial);m_MaskMaterial = maskMaterial;var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0);StencilMaterial.Remove(m_UnmaskMaterial);m_UnmaskMaterial = unmaskMaterial;graphic.canvasRenderer.popMaterialCount = 1;graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);return m_MaskMaterial;}//otherwise we need to be a bit smarter and set some read / write masksvar maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));StencilMaterial.Remove(m_MaskMaterial);m_MaskMaterial = maskMaterial2;graphic.canvasRenderer.hasPopInstruction = true;var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));StencilMaterial.Remove(m_UnmaskMaterial);m_UnmaskMaterial = unmaskMaterial2;graphic.canvasRenderer.popMaterialCount = 1;graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);return m_MaskMaterial;}

Mask注意要点

  1. Mask剔除的部分还是会影响深度计算的,从而影响合批,增加drawcall次数
  2. Mask剔除的部分还是会drawcall,只不过mask把绘制的像素剔除了
  3. Mask下的子物体可以正常进行合批
  4. mask之间只要满足合批条件,那么他们之间的元素也是能够进行合批的
    在这里插入图片描述

RectMask2D

  1. RectMask2D本身不占用drawcall
  2. 因为实际的具体逻辑是在canvas render里进行的,涉及到渲染具体的操作都是内部用c++类做的,性能更好,这里通过性能分析渲染的面和点判断遮盖的部分是否被渲染出来
    在这里插入图片描述

为什么RecMask2D比Mask性能更好

  1. RectMask2D本身不占用drawcall,Mask本身有两次drawcall
  2. RectMask2D对于被遮罩的部分并不会绘制,Mask是把遮罩的部分剔除了

主要代码

public virtual void PerformClipping()
{if (ReferenceEquals(Canvas, null)){return;}//TODO See if an IsActive() test would work well here or whether it might cause unexpected side effects (re case 776771)// if the parents are changed// or something similar we// do a recalculate hereif (m_ShouldRecalculateClipRects){MaskUtilities.GetRectMasksForClip(this, m_Clippers);m_ShouldRecalculateClipRects = false;}// get the compound rects from// the clippers that are validbool validRect = true;// 获取需要剪切的区域Rect clipRect = Clipping.FindCullAndClipWorldRect(m_Clippers, out validRect);// If the mask is in ScreenSpaceOverlay/Camera render mode, its content is only rendered when its rect// overlaps that of the root canvas.RenderMode renderMode = Canvas.rootCanvas.renderMode;bool maskIsCulled =(renderMode == RenderMode.ScreenSpaceCamera || renderMode == RenderMode.ScreenSpaceOverlay) &&!clipRect.Overlaps(rootCanvasRect, true);if (maskIsCulled){// Children are only displayed when inside the mask. If the mask is culled, then the children// inside the mask are also culled. In that situation, we pass an invalid rect to allow callees// to avoid some processing.clipRect = Rect.zero;validRect = false;}if (clipRect != m_LastClipRectCanvasSpace){foreach (IClippable clipTarget in m_ClipTargets){//设置剪切效果clipTarget.SetClipRect(clipRect, validRect);}foreach (MaskableGraphic maskableTarget in m_MaskableTargets){maskableTarget.SetClipRect(clipRect, validRect);maskableTarget.Cull(clipRect, validRect);}}else if (m_ForceClip){foreach (IClippable clipTarget in m_ClipTargets){clipTarget.SetClipRect(clipRect, validRect);}foreach (MaskableGraphic maskableTarget in m_MaskableTargets){maskableTarget.SetClipRect(clipRect, validRect);if (maskableTarget.canvasRenderer.hasMoved)maskableTarget.Cull(clipRect, validRect);}}else{foreach (MaskableGraphic maskableTarget in m_MaskableTargets){//Case 1170399 - hasMoved is not a valid check when animating on pivot of the objectmaskableTarget.Cull(clipRect, validRect);}}m_LastClipRectCanvasSpace = clipRect;m_ForceClip = false;UpdateClipSoftness();
}

RectMask2D注意要点

  1. 遮罩的部分因为没有绘制,所以不影响深度计算,不影响合批
  2. 会打断合批,一个RectMask2D下的子物体不可以跟另一个RectMask2D下的子物体进行合批,但RectMask2D下的子物体可以进行合批
  3. RectMask2D组件的Image之间可以进行合批

根据应用场景选择使用哪个(Mask、RectMask2D)

只需要一个遮罩

选择用RectMask2D性能更好

需要多个遮罩,遮罩下有多个子物体

选择用Mask可以对不同Mask之间的子物体进行合批,这种情况就会比RectMask2D性能更好

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

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

相关文章

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门&#xff08;一&#xff09;&#xff1a;从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫&#xff1f;1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP&#xff1f;2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.2 CSS3.…

vue3知识

目录 基础vue开发前的准备vue项目目录结构模板语法属性绑定条件渲染列表渲染通过key管理状态事件处理事件传参事件修饰符数组变化侦测计算属性Class绑定style绑定侦听器表单输入绑定模板引用组件组成组件嵌套关系组件注册方式组件传递数据Props(父传子)组件传递多种数据类型组件…

电影院售票网站

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM框架 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 用户管理界面 正在上映管…

Vue---vue3+vite项目内使用devtools,快速开发!

背景 我们在前期开发时&#xff0c;一般使用chrome或者edge浏览器&#xff0c;会使用vue-devtools或react-devtools&#xff08;此插件个人未使用&#xff0c;可百度下是否可内嵌入项目&#xff01;&#xff09;来审查vue项目&#xff1b;这个需要安转浏览器插件才可支持&…

大模型llama结构技术点分享;transformer模型常见知识点nlp面经

1、大模型llama3技术点 参考&#xff1a;https://www.zhihu.com/question/662354435/answer/3572364267 Llama1-3&#xff0c;数据tokens从1-2T到15T;使用了MHA&#xff08;GQA缓存&#xff09;&#xff1b;上下文长度从2-4-8K&#xff1b;应用了强化学习对其。 1、pretraini…

RedHat9 | Ansible 处理任务失败

环境版本说明 RedHat9 [Red Hat Enterprise Linux release 9.0]Ansible [core 2.13.3]Python [3.9.10]jinja [3.1.2] 1. 忽略任务失败 Ansible评估各任务的返回代码&#xff0c;从而确定任务是成功还是失败通常而言&#xff0c;当任务失败时&#xff0c;Ansible将立即在该主…

可以免费合并pdf的软件 合并pdf文件的软件免费 合并pdf的软件免费

在数字化办公的今天&#xff0c;pdf格式因其稳定性和跨平台兼容性被广泛使用。然而&#xff0c;当我们需要将多个 pdf 文件合并为一个时&#xff0c;却往往感到力不从心。本文将为你介绍几款强大的pdf文件合并软件&#xff0c;让你轻松管理文档。 方法一、使用pdf转换器 步骤1…

爬虫 APP 逆向 ---> 粉笔考研

环境&#xff1a; 粉笔考研 v6.3.15&#xff1a;https://www.wandoujia.com/apps/1220941/history_v6031500雷电9 模拟器&#xff1a;https://www.ldmnq.com/安装 magisk&#xff1a;https://blog.csdn.net/Ruaki/article/details/135580772安装 Dia 插件 (作用&#xff1a;禁…

后端开发刷题 | 笔试

Linux 中&#xff0c;下面哪个选项不是 inode 中记录的数据&#xff08;&#xff09; A 最后一次读取时间 B 最近修改的时间 C 该文件的实际内容 D 该文件的容量 正确答案&#xff1a;C 解析&#xff1a;储存文件的元信息&#xff0c;比如文件的创建者、文件的创建日期、文件的…

MySQL-视图、存储过程和触发器

一、视图的定义和使用 视图是从一个或者几个基本表&#xff08;或视图&#xff09;导出的表。它与基本表不同&#xff0c;是一个虚表,视图只能用来查询。不能做增删改查(虚拟的表) 1.视图的作用 简化查询重写格式化数据频繁访问数据库过滤数据 2.创建视图 -- 创建视图 -- 语法…

【MATLAB APP】建立独立桌面APP

背景&#xff1a;已有MATLAB APP的.mlapp文件&#xff0c;但客户提出需要可以直接使用的exe文件。 要求&#xff1a;点开即用&#xff0c;无需下载MATLAB。使用者无法修改APP的代码。 一、环境配置 APP创建者&#xff1a;安装MATLAB R2023a&#xff0c;配置Application Compile…

【开源库编译 | zlib】 zlib库最新版本(zlib-1.3.1)在Ubuntu(Linux)系统下的 编译 、交叉编译(移植)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

通信原理-实验六:实验测验

实验六 实验测验 一&#xff1a;测验内容和要求 测试需要完成以下几个步骤&#xff1a; 配置好以下网络图&#xff1b;占总分10%&#xff08;缺少一个扣一分&#xff09;根据下面图配置好对应的IP和网关以及路由等相关配置&#xff0c;保证设备之间连通正常&#xff1b;占总…

【学一点儿前端】本地或jenkins打包报错:getaddrinfo ENOTFOUND registry.nlark.com.

问题 今天jenkins打包一个项目&#xff0c;发现报错了 error An unexpected error occurred: "https://registry.nlark.com/xxxxxxxxxx.tgz: getaddrinfo ENOTFOUND registry.nlark.com". 先写解决方案 把yarn.lock文件里面的registry.nlark.com替换为registry.npmmi…

【计算机网络】期末实验答辩

注意事项&#xff1a; 1&#xff09;每位同学要在下面做过的实验列表中选取三个实验进行答辩准备&#xff0c;并将自己的姓名&#xff0c;学号以及三个实验序号填入共享文档"1&#xff08;2&#xff09;班答辩名单"中。 2&#xff09;在答辩当日每位同学由老师在表…

【React】事件绑定:深入解析高效处理用户交互的最佳实践

文章目录 一、什么是事件绑定&#xff1f;二、基本事件绑定三、绑定 this 上下文四、传递参数五、事件对象六、事件委托七、常见事件处理八、优化事件处理 React 是现代前端开发中最受欢迎的框架之一&#xff0c;其组件化和高效的状态管理能力使得构建复杂的用户界面变得更加容…

**卷积神经网络典型CNN**

SeNet SeNet(Squeeze-and-Excitation Networks)是ImageNet 2017年分类任务冠军&#xff0c;核心思想是&#xff1a;Squeeze(挤压、压缩)和Excitation(激励)两个操作&#xff0c;其主要目的是通过显示的构建特征通道之间的相互依赖关系&#xff0c;采用特征重定向的策略&#x…

光明乳业:以科技赋能品质,引领乳业绿色新未来

近日&#xff0c;光明乳业再次成为行业焦点&#xff0c;其在科技创新与绿色发展方面的卓越表现赢得了广泛赞誉。作为中国乳制品行业的领军企业&#xff0c;光明乳业始终坚守品质至上的原则&#xff0c;不断探索科技创新之路&#xff0c;致力于为消费者提供更高品质、更健康的乳…

webStorm 实时模板笔记

文章目录 1、单斜杠效果 2、双斜杠效果 3、控制台打印效果 1、单斜杠 /** $END$ */效果 2、双斜杠 /*** $END$* author Ikun* since $DATE$ $TIME$ */DATE date() ✔ TIME time() ✔效果 3、控制台打印 console.log("███████$EXPR_COPY$>>>>&a…

Internxt:适用于Linux开源安全云存储平台

有无数的云存储平台为您的文件提供安全可靠的存储空间。可在 Linux 上安装的热门云存储应用程序包括Dropbox、Nextcloud和Google Drive&#xff0c;遗憾的是&#xff0c;后者迄今为止不提供 Linux 客户端。 其他自托管选项包括OwnCloud、Pydio Cells、Seafile、Resilio和Synct…