当前位置: 首页 > 编程日记 > 正文

(转)Unity3D - 性能优化之Draw Call

Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎首先经过简单的可见性测试,确定摄像机可以看到的物体,然后把这些物体的顶点(包括本地位置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好,然后通知图形API——或者就简单地看作是通知GPU——开始绘制,GPU基于这些数据,经过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。

在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐个物体进行的,对于每个物体,不只GPU的渲染,引擎重新设置材质/Shader也是一项非常耗时的操作。因此每帧的Draw Call次数是一项非常重要的性能指标,对于iOS来说应尽量控制在20次以内,这个值可以在编辑器的Statistic窗口看到。

Unity内置了Draw Call Batching技术,从名字就可以看出,它的主要目标就是在一次Draw Call中批量处理多个物体。只要物体的变换和材质相同,GPU就可以按完全相同的方式进行处理,即可以把它们放在一个Draw Call中。Draw Call Batching技术的核心就是在可见性测试之后,检查所有要绘制的物体的材质,把相同材质的分为一组(一个Batch),然后把它们组合成一个物体(统一变换),这样就可以在一个Draw Call中处理多个物体了(实际上是组合后的一个物体)。

但Draw Call Batching存在一个缺陷,就是它需要把一个Batch中的所有物体组合到一起,相当于创建了一个与这些物体加起来一样大的物体,与此同时就需要分配相应大小的内存。这不仅会消耗更多内存,还需要消耗CPU时间。特别是对于移动的物体,每一帧都得重新进行组合,这就需要进行一些权衡,否则得不偿失。但对于静止不动的物体来说,只需要进行一次组合,之后就可以一直使用,效率要高得多。

Unity提供了Dynamic Batching和Static Batching两种方式。Dynamic Batching是完全自动进行的,不需要也无法进行任何干预,对于顶点数在300以内的可移动物体,只要使用相同的材质,就会组成Batch。Static Batching则需要把静止的物体标记为Static,然后无论大小,都会组成Batch。如前文所说,Static Batching显然比Dynamic Batching要高效得多,于是,Static Batching功能是收费的……

要有效利用Draw Call Batching,首先是尽量减少场景中使用的材质数量,即尽量共享材质,对于仅纹理不同的材质可以把纹理组合到一张更大的纹理中(称为Texture Atlasing)。然后是把不会移动的物体标记为Static。此外还可以通过CombineChildren脚本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手动把物体组合在一起,但这个脚本会影响可见性测试,因为组合在一起的物体始终会被看作一个物体,从而会增加GPU要处理的几何体数量,因此要小心使用。

对于复杂的静态场景,还可以考虑自行设计遮挡剔除算法,减少可见的物体数量同时也可以减少Draw Call。

总之,理解Draw Call和Draw Call Batching原理,根据场景特点设计相应的方案来尽量减少Draw Call次数才是王道,其它方面亦然。

转载于:https://www.cnblogs.com/wonderKK/p/3918052.html

相关文章:

Drill storage plugin实现原理分析

Drill Storage Plugin介绍 Drill是一个交互式SQL查询引擎,官方默认支持的数据源有hive、hbase、kafka、kudu、mongo、opentsdb、jdbc等,其中jdbc storage plugin可以覆盖所有支持jdbc协议的数据源,如:mysql、oracle等关系型数据库…

C# 创建控制台应用程序

C#的语法总结将全部通过控制台应用程序总结。 一、文件-》新建项目 二、 三、创建后的界面。 转载于:https://www.cnblogs.com/nevernet/archive/2008/12/08/1350024.html

(C++)1009 Product of Polynomials

笔记:1.如果开三个数组,乘积数组的大小是2*10^3,而不是10^6(汗颜),如果开后者那么大的数组,需要定义在main函数外面了(实现一) 2.注意到double数组可能是非常稀疏的,为了减少运算量…

lispbox 安装运行.sh的时候出现 lispbox.sh: 2: lispbox.sh: Bad substitution

安装lispbox时使用tar命令将压缩文件解压之后cd进入之后在运行.sh文件时出现了如下情况。 $ sh lispbox.sh lispbox.sh: 2: lispbox.sh: Bad substitution 提示 bad substitution 这是因为linux有不同的shell 使用sh运行错误应该使用bash运行即可。 改成bash -x lispbox.sh即可…

Python-字符串操作方法 [转]

Python-String-Function 字符串中字符大小写的变换: * S.lower() #小写 * S.upper() #大写 * S.swapcase() #大小写互换 * S.capitalize() #首字母大写 * String.capwords(S) #这是模块中的方法。它把S用split()函数分开&#xff0…

旅行家的预算[贪心]

题目 Problem description 一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2、出发点每升汽油价格P和…

(C++)1028 人口普查

笔记&#xff1a;把年龄转化成一个七位的整数是创举&#xff0c;但是要想清楚&#xff0c;年龄越大&#xff0c;这个数字越小orz #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;struct person{char n…

说说.net事件和委托。

一说到.net的事件&#xff0c;也许你会想都说教程满天飞&#xff0c;一个被说烂了的东西还有什么可以说的啊&#xff1f;是啊&#xff0c;的确有很多好文章剖析事件&#xff0c;比如张子阳先生的C# 中的委托和事件重温Observer模式--热水器改 这两篇文章让我弄懂了委托、事件和…

【cs229-Lecture2】Linear Regression with One Variable (Week 1)(含测试数据和源码)

从Ⅱ到Ⅳ都在讲的是线性回归&#xff0c;其中第Ⅱ章讲得是简单线性回归&#xff08;simple linear regression, SLR&#xff09;&#xff08;单变量&#xff09;&#xff0c;第Ⅲ章讲的是线代基础&#xff0c;第Ⅳ章讲的是多元回归&#xff08;大于一个自变量&#xff09;。 本…

101种设计模式

https://sourcemaking.com/design-patterns-and-tips

(C++)1032 挖掘机技术哪家强

笔记&#xff1a;考虑到输入只有一所学校&#xff0c;且得分还为0的特殊情况&#xff0c;应该把high初始化为1 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;int grds[100010] {0};int main(){int …

数据库打开报错: 值不能为空

报错信息如下&#xff1a; 数据库客户端打不开 解决方案&#xff1a; 找到下面的目录C:\Users\<username>\AppData\Local\Temp 创建一个空文件夹 名称是&#xff1a; 2 重新打开数据库转载于:https://www.cnblogs.com/Mander/p/3921251.html

学习 JavaScript (四)核心概念:操作符

JavaScript 的核心概念主要由语法、变量、数据类型、操作符、语句、函数组成&#xff0c;前面三个上一篇文章已经讲解完了。后面三个内容超级多&#xff0c;这篇文章主要讲解的是操作符。 操作符 什么叫做操作符&#xff1f; 这是一种工具&#xff0c;帮助我们操作字符串、数字…

(C++)1011 World Cup Betting

笔记&#xff1a;我觉得这一次的代码很优雅 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;int maxPro(double a[3]){//返回值最大的下标 int idx0,max_pro0;for(int i0;i<3;i){if(a[i]>max_pr…

Ext学习-前后交互模式介绍

在前后台交互模式的介绍中&#xff0c;实际上就是Store中Proxy相关的内容&#xff0c;比如Ajax提交。 所以详细的文档请参考&#xff1a; Ext学习-基础概念&#xff0c;核心思想介绍 中关于数据模型和MVC结构部分。 作者&#xff1a;sdjnzqr 出处&#xff1a;http://www.cnblog…

让你彻底明白什么叫游戏引擎(1)

在阅读各种游戏介绍的时候我们常常会碰见“引擎”&#xff08;Engine&#xff09;这个单词&#xff0c;引擎在游戏中究竟起着什么样的作用&#xff1f;它的进化对于游戏的发展产生了哪些影响&#xff1f;希望下面这篇文章能为大家释疑。以希望能够帮助一些刚进入游戏行业的小菜…

185.dubbo 后台管理系统

2019独角兽企业重金招聘Python工程师标准>>> 1. 效果及目的 效果&#xff1a; 目的&#xff1a;查看 管理服务 2. 启动要求 &#xff08;1&#xff09;项目是dubbo &#xff08;2&#xff09;jdk 1.7 (3) dubbo的war要与zookeeper在同一台服务上 3. 安装zookeeper 要…

(C++)1027 打印沙漏

笔记&#xff1a;星号右边的空格不用打印 #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std;int main(){int n;char c;scanf("%d %c",&n,&c);int clock[23];int col;for(int i1;i<…

黑帽大会2014:10个酷炫的黑客工具

http://www.csdn.net/article/2014-08-21/2821304 用于恶意软件分析的Maltrieve 安全研究人员使用Maltrieve工具收集服务器上的恶意软件。通过这个开源工具&#xff0c;恶意软件分析人员可以通过分析URL链表和已知的托管地址获得最新鲜的样本。 Kyle Maxwell是VeriSign的一名威…

C#无符号右移

/// <summary>/// 无符号右移&#xff0c;与JS中的>>>等价/// </summary>/// <param name"x">要移位的数</param>/// <param name"y">移位数</param>/// <returns></returns>public static int …

1027 Colors in Mars

笔记&#xff1a;本题属于进制转换&#xff0c;但是考察的重点不在除基取余上&#xff0c;因为转化得到的数只有两位&#xff0c;很容易得到每位上面应该是什么&#xff0c;但是和其他题不同的地方在于&#xff0c;每位可填的不见得是0~9&#xff0c;还包括ABC&#xff0c;这就…

json对象和json字符串转换方法

在WEB数据传输过程中&#xff0c;json是以文本&#xff0c;即字符串的轻量级形式传递的&#xff0c;而客户端一般用JS操作的是接收到的JSON对象&#xff0c;所以&#xff0c;JSON对象和JSON字符串之间的相互转换、JSON数据的解析是关键。 先明确2个概念例如&#xff1a; JSON字…

python-docx操作

import docx# 读取docx文档内容def readWord():doc docx.Document(demo.docx)fullText []for para in doc.paragraphs:fullText.append( para.text)print(\n . join(fullText))readWord()官方API&#xff1a;https://python-docx.readthedocs.io/en/latest/index.html ;转载…

javascript中FORM表单的submit()方法经验教训.

author songfeng 因为JS内对象的方法实际上是存储语句的一个类似于指针的东西. 其指向了内存的一个位置, 也就是其函数的位置,当然也可以让其指向一个变量值. var foo new Object();foo.bar function() {} //现在foo.bar就是指向了这个函数的内存位置.foo.bar &q…

1058 A+B in Hogwarts

笔记&#xff1a;和乙级的在霍格沃兹找零钱不同&#xff0c;这里不需要判断给出的两个数的大小&#xff0c;也没必要先都换算成最小的单位&#xff0c;可以直接从最低位开始加&#xff0c;如果超过该位的范围&#xff0c;则向上一位进一即可。 #include<cstdio> #includ…

DDD领域驱动设计之聚合、实体、值对象

关于具体需求&#xff0c;请看前面的博文&#xff1a;DDD领域驱动设计实践篇之如何提取模型&#xff0c;下面是具体的实体、聚合、值对象的代码&#xff0c;不想多说什么是实体、聚合等概念&#xff0c;相信理论的东西大家已经知晓了。本人对DDD表示好奇&#xff0c;没有在真正…

C#用 SendKyes 结合 Process 或 API FindWindow、SendMessage(PostMessage) 等控制外部程序

Win32 平台是 消息驱动模式.Net 框架是 事件驱动模式标题所指的 “控制外部程序”&#xff0c;外部程序是指与本程序无内在相关性的另外一个程序 基于上面提到的&#xff0c;对于.NET的winform程序&#xff0c;在默认情况下&#xff08;即未对接收消息的事件做自定义处理&#…

springMVC swagger2

参考地址&#xff1a;https://www.cnblogs.com/exmyth/p/7183753.html https://blog.csdn.net/programmer_sean/article/details/72236948 1. maven 依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId&…

1061 Dating

笔记&#xff1a; 第一个输出根据的是大写字母 第二个输出根据的是0-9andA-N 第三个输出根据的是大写字母和小写字母 知道范围便方便确定边界 两两比对时&#xff0c;先遍历一个字符串&#xff0c;遇到在范围内的字符&#xff0c;看其和第二个字符串同位置的字符是否相等 …

PA 项目创建任务

---- 创建任务 DECLAREp_project_id NUMBER : 155233;p_task_number VARCHAR2(240) : CXYTEST0001;p_task_name VARCHAR2(240) : 接口测试CXYTEST0001;p_task_description VARCHAR2(240) : TASKCXYTEST0001;p_scheduled_start_date DAT…