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.mzph.cn/news/876463.shtml

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

相关文章

Golang | Leetcode Golang题解之第295题数据流的中位数

题目&#xff1a; 题解&#xff1a; type MedianFinder struct {nums *redblacktree.Treetotal intleft, right iterator }func Constructor() MedianFinder {return MedianFinder{nums: redblacktree.NewWithIntComparator()} }func (mf *MedianFinder) AddNum(…

基于STM32的多协议通信系统设计与实现

在现代电子系统中&#xff0c;多协议通信能力是一种宝贵的资产&#xff0c;它允许设备与使用不同通信协议的多种外围设备进行交互。STM32微控制器因其强大的处理能力和丰富的外设支持&#xff0c;非常适合构建多协议通信系统。本文将探讨如何设计和实现一个基于STM32的多协议通…

MySQL中多表查询之外连接

首先先来介绍一下我做的两个表&#xff0c;然后再用他们两个举例说明。 -- 创建教师表 create table teachers( id_t int primary key auto_increment, -- 老师编号 name_t varchar(5) -- 姓名 ); -- 创建学生表 create table students( id_s int primary key auto_increment,…

数据结构——单链表OJ题(下)

目录 一、链表的回文结构 思路一&#xff1a;数组法 &#xff08;1&#xff09;注意 &#xff08;2&#xff09;解题 思路二&#xff1a;反转链表法 &#xff08;1&#xff09; 注意 &#xff08;2&#xff09;解题 二、相交链表 &#xff08;1&#xff09;思路&#…

优化算法:1.遗传算法(GA)及Python实现

一、定义 遗传算法就像是在模拟“优胜劣汰”的进化过程&#xff0c;通过选择最优秀的个体&#xff0c;交配产生下一代&#xff0c;并引入一定的变异&#xff0c;逐步优化解决问题。 二、具体步骤 初始化种群(Initialization)&#xff1a; 假设你要找到一个迷宫的最佳出口路径。…

CTF-NSSCTF[GKCTF 2021]

[GKCTF 2021]easycms 考察&#xff1a; 用扫描工具扫描目录&#xff0c;扫描到后台登录界面/admin.php 题目提示了密码是五位弱口令&#xff0c;试了试弱口令admin和12345直接成功了 任意文件下载 点击设计-->主题然后随便选择一个主题&#xff0c;点击自定义&#xff0…

故障诊断 | 基于Transformer故障诊断分类预测(Matlab)

文章目录 预测效果文章概述程序设计参考资料预测效果 文章概述 Transformer故障诊断/分类预测 | 基于Transformer故障诊断分类预测(Matlab) Transformer 模型本质上都是预训练语言模型,大都采用自监督学习 (Self-supervised learning) 的方式在大量生语料上进行训练,也就是…

CTF之网站被黑

简单看一下网页和源码没发现什么明显漏洞 那就扫描一下目录 发现了/shell.php文件&#xff0c;访问一下&#xff0c;发现是一个后台管理登录页面 别无他法只能爆破喽&#xff0c;爆破后发现密码是hack flag{25891d9e9d377f006eda3ca7d4c34c4d}

@JSONField(format = “yyyyMMddHH“)的作用和使用

JySellerItqrdDataDO对象中的字段为&#xff1a; private Date crdat; 2.数据库中的相应字段为&#xff1a; crdat datetime DEFAULT NULL COMMENT 创建时间,2. 打印出的结果为&#xff1a; “crdat”:“2024072718” 年月日时分秒 3. 可以调整format的格式 4. 这样就把Date类…

RedHat8安装Oracle19C

RedHat8安装Oracle19C 1、 更新yum源 更新yum源为阿里云镜像源&#xff1a; # 进入源目录 cd /etc/yum.repos.d/ # 删除 redhat 默认源 rm redhat.repo # 下载阿里云的centos7源 curl -O http://mirrors.aliyun.com/repo/Centos-8.repo # 替换 Centos-8.repo 中的 $releasev…

Rust:在Ubuntu22.04上安装

1.官方的安装方法&#xff1a; $ curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh 尝试后由于网络原因&#xff0c;无法顺利安装 2.使用国内源进行安装 首先在终端里执行 $ curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs > rust.sh 然后编辑rust.…

初学Mybatis之 Lombok 篇

idea 安装 Lombok 插件&#xff1a; File->Settings->Plugins->搜索 lombok 下载 在项目中导入 lombok 的 jar 包&#xff1a; <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.…

C语言程序设计之数学函数篇

程序设计之数学函数 问题1_1代码1_1结果1_1 问题1_2代码1_2结果1 _2 问题1_3代码1_3结果1_3 问题1_1 函数 f u n fun fun 的功能是计算&#xff1a; s ln ⁡ ( 1 ) ln ⁡ ( 2 ) ln ⁡ ( 3 ) ⋯ ln ⁡ ( n ) s\sqrt{\ln(1)\ \ \ln(2)\ \ \ln(3)\ \ \cdots \ \ \ln(n)\ } …

C#中导出dataGridView数据为Excel

C#中导出dataGridView数据为Excel #region 导出Excel功能函数 /// <summary> /// dataGridView 导出Excel功能函数 /// </summary> /// <param name"dataView">dataGridView数据表</param> /// <param name"filePath">路径…

ReentrantReadWriteLock详解

目录 ReentrantReadWriteLock详解1、ReentrantReadWriteLock简介2、ReentrantReadWriteLock类继承结构和类属性3、ReentrantReadWriteLock的读写锁原理分析4、ReentrantReadWriteLock.WriteLock类的核心方法详解非公平写锁的获取非公平写锁的释放公平写锁的获取公平写锁的释放 …

win11查找句柄泄露

1.打开任务管理器&#xff0c;不会的网上搜 2.选择详细信息 3.注意了 比较坑的一点 win11上详细信息不会默认显示句柄数。&#xff08;默认没有句柄那一列&#xff0c;妈的花了我好长时间找&#xff09; 右键&#xff0c;点击选择列 选择句柄 下面的列表里就能看到进程使用…

【嵌入式】学习路线

嵌入式系统是一种专门为特定任务设计的计算系统&#xff0c;通常嵌入在其他设备中。要学习嵌入式系统&#xff0c;以下是一个系统化的学习路线图&#xff1a; 1. 基础知识 编程语言 C语言&#xff1a;嵌入式开发的主要语言。汇编语言&#xff1a;了解硬件层面的编程。C&#…

显著提升“视触觉传感器耐磨性”的贴金工艺,在植物和古生物化石检测上取得良好的识别效果

贴金&#xff0c;一种古老的技艺&#xff0c;是中华民族民间传统工艺的瑰宝&#xff01;金箔和贴金工艺的结合让朴实无华的工艺品重获新生。正如《天工开物》所述&#xff1a;“凡色至于金&#xff0c;为人间华美贵重&#xff0c;故人工成箔而后施之”。这项古老技艺如今可用于…

PyCharm 常用 的插件

Material Theme UI Lite&#xff1a;‌提供多种不同的页面风格&#xff0c;‌为PyCharm界面增添个性化元素。‌Chinese (Simplified) Language Pack&#xff1a;‌为中文用户提供简体中文的界面、‌菜单、‌提示信息&#xff0c;‌提升使用体验。‌Tabnine&#xff1a;‌基于人…

SSA-GRU(自适应平滑自回归门控循环单元)预测模型及其Python和MATLAB实现

SSA-GRU&#xff08;自适应平滑自回归门控循环单元&#xff09;预测模型是结合了SSA&#xff08;Singular Spectrum Analysis&#xff0c;奇异谱分析&#xff09;和GRU&#xff08;Gated Recurrent Unit&#xff0c;门控循环单元&#xff09;模型的一种时间序列预测方法。以下是…