ngui 合并drawcalll的规则 是怎么样的

浅谈Draw Call和Batch的区别 | Unity3D教程手册
当前位置 :
>> 浅谈Draw Call和Batch的区别
浅谈Draw Call和Batch的区别
开发游戏时,一定被时时提醒要减少 Draw Call,当然Unity也不例外,打开Game Window里的 Stats,可以看到 Draw Call 与 Batched 的数字。但到底什么是 Draw Call?影响的效能是来自 CPU?还是 GPU?
浅谈Draw Call和Batch的区别
首先,让我们定义何为 “Draw Call”:
“一个 Draw Call,等于呼叫一次 DrawIndexedPrimitive (DX) or glDrawElements (OGL),等于一个 Batch”
摸过 DirectX 或 OpenGL 的人来说,对 DrawIndexedPrimitive 与 glDrawElements 这
API 一定不陌生。当我们准备好资料 (通常为三角面的顶点资讯) 要 GPU 划出来时,一定得呼叫这个函式。换句话说,如果在画面上有一张 “木"
椅子、一张 “铁" 桌子,那理论上就会有两个 Draw Call。
有看到特别点出 “木" 与 “铁" 吗?这代表两物件是使用不同材质球或者不同的 Shader。在 DirectX 或 OpenGL
里,对不同物件指定不同贴图或不同 Shader 的描述,就会需要呼叫两次Draw Call。Procedure code如下:
&&&1SetShader( “Diffuse" );2SetTexture( “铁" );3DrawPrimitive( DeskVertexBuffer );4&5SetShader( “VertexLight"&);6SetTexture( “木" );7DrawPrimitive( ChairVertexBuffer );
每次对 Shader 的更动或者贴图的更动,基本上就是对 Rendering Pipeline 的设定做修改,所以需要不同的 Draw
Call 来完成物件的绘制。现在了解为什么 Unity 官方文件里,老是要你尽量使用同样材质球,以减少 Draw Call 数量了吧!
再来谈到 Batch,其实也是 Draw Call 的另一种称呼。你可以想成每一次的 Draw Call 会产生一个 Batch,而
Batch 里装的是物件顶点资料,Batch 由 CPU 透过 “驱动程式” 将顶点资料送往
GPU,GPU接手后将物件画在画面上。由此可知,越多 Draw Call,CPU 就越忙碌。这下更清楚知道 Draw Call 数量所影响的是
CPU 效能而非 GPU。
NVIDIA 在 GDC 曾提出,25K batchs/sec 会吃满 1GHz 的 CPU,100的使用率。所以他们推出了一条公式,来预估游戏中大概可以 Run 多少个 Batch:
浅谈Draw Call和Batch的区别
举个例子:如果你的目标是游戏跑30FPS、使用2GHz的CPU、20š„工作量拨给Draw Call来使用,那你每秒可以有多少Draw Call呢?
&333 Batchs/Frame = 25K * 2 * (0.2/30)
那既然 Batch 是个箱子,里头装着物件的顶点资料,再依据我们上面的描述,那表示同样材质或 Shader 的物件,可以合并成一个 Batch 送往 GPU,这样就是最省事的方法!
Unity在 Player Setting 里的两个功能选项 Static Batching 与 Dynamic Batching。功能描述如下:
Static Batching 是将标明为 Static 的静态物件,如果在使用相同材质球的条件下,Unity 会自动帮你把这两个物件合并成一个 Batch,送往 GPU 来处理。这功能对效能上非常的有帮助,所以是需要付费才有的。
Dynamic Batching 是在物件小于300面的条件下(不论物件是否为静态或动态),在使用相同材质球下,Unity就会自动帮你合合并成一个 Batch 送往 GPU 来处理。
根据上述的说明,相信大家对降低 Draw Call 这件事有更深一层的认识吧!还有什么不清楚或者错误的地方,还请大家能够留言回复。
相关文章:
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!求大神看看关于DrawCall的问题【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:71,931贴子:
求大神看看关于DrawCall的问题收藏
如图,我3个物体使用了同一个材质,第一、第二个物体是用Mesh Renderer,第三个是用Skinned Mesh Renderer,当我激活第二个的时候DrawCall并没有增加,当我激活第三个的时候DrawCall增加了,请问大神这是什么原因,是因为蒙皮渲染器的原因吗?还是我unity哪里设置不对?
可有解决的办法?
火星{游戏原画培训}费用性价比No1,9大专业,55门课程免费试学.还有震撼助学金计划.选择火星时代,做高端游戏设计师!现在还可享受0利息学费,你学习,我付息
可能是用了不同组件的原因吧。
如果是不同组件的原因的话,那我再复制一个使用蒙皮渲染器的物体后应该是不会增加DrawCall吧,但事实上还是造成了DrawCall+1
如果移动的对象共享同一材质,且符合其他标准,Unity 可自动将移动的对象批处理为同样的绘制调用。动态批处理可自动完成,无需进行任何其他操作。提示:批处理动态对象中的每个顶点都存在开销,因此,批处理只应用到包含的顶点属性少于 900 个的网格。如果着色器正在使用顶点位置 (Vertex Position)、法线 (Normal) 和单个 UV,那么您最多可以批处理 300 个顶点;然而,如果着色器正在使用顶点位置 (Vertex Position)、法线 (Normal)、UV0、UV1 和切线 (Tangent),那么最多只可以批处理 180 个顶点。请注意: 属性限制在将来可能有所更改一般而言,对象应使用相同的变换范围。非统一测量的对象属于例外;如果多个对象拥有不同的非统一范围,它们依然可以批处理。使用不同材质实例的对象不会同时批处理,即使这些实例从本质上来说一样。带光照贴图的对象还有其他渲染器参数: 光照贴图指数和光照贴图的偏移量/范围。因此,通常动态光照贴图对象应指向同样的光照贴图位置才能进行批处理。多通道着色器将打断批处理。几乎所有 unity 着色器都在正向渲染中支持多种光照,为其有效提供额外的通道。“其他逐像素光照”的绘制调用将不会批处理。收到实时阴影的对象将不会分批处理。
你的物体都没有勾static,那么Unity只能是运行时动态批处理了(Dynamic Batching).但是动态批处理有很多限制条件的,楼上说了一些了,不过你的Plane1和Plane2很简单,应该是符合要求的,所以他们会被优化成一个DrawCall。但是由于你的Plane3中使用了Skinned Mesh Renderer。目前Unity只对Mesh Renders和粒子进行Batching。对于蒙皮,布料和拖尾效果并未进行Batching。
谢谢大神的指点,按照您的说法我的问题应该是出在顶点数量上了,可是我让美术弄了一个最简单的正方形模型,顶点只有12个,还是会发生DrawCall增加的情况啊
谢谢5楼大神的解答
我记得凡是用Skinned Mesh Renderer就需要一个drawcall吧。
登录百度帐号推荐应用Pages: 1/2
主题 : 【基本解决】请教Cocos2dx3.0新渲染器合并draw call的规则&&多格table的性能优化
级别: 新手上路
UID: 141838
可可豆: 35 CB
威望: 35 点
在线时间: 27(时)
发自: Web Page
来源于&&分类
【基本解决】请教Cocos2dx3.0新渲染器合并draw call的规则&&多格table的性能优化&&&
在cocos2dx的英文论坛写了一大段英文也没人回复T_T,转战中文论坛求教中。以下问题用cocos2dx3.0 rc版本以及正式版都测试过~~~~我们游戏有很多场景是一个大table里面有若干个组成复杂但是相互类似的格子(比如图鉴),为此我做了一个简单的测试,放了3个相同的item(复制粘贴出来的),每个item由6个不同贴图的sprite组成(我知道碎图合并可以减少draw call,此例只为测试,而且最后我们也无法合并到只用一张图),没有用batchnode,因为我理解新的renderer会自动把同样贴图同样深度的sprite合并drawcall的,最后应该只有6个draw call,可是测试下来发现一共有18个draw call,并没有发生合并。然后我研究了一下render部分的代码,发现最后在绘制的时候会判断一下当前command和前一个command的material是否一致,一致则合并,但是我的command是1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6,所以全部都无法合并。我自己暴力的在排序的时候,对z=0的queue(18个command都在这)按照material排了下序,这样就能够得到想要的6个draw call的效果。我的问题:1. 我的这种情况,期待6个draw call是正确的吗?2. 如果正确,那么是我哪里用法不对造成有18个draw call?3. 如果不正确,那么这个auto-batching是设计来优化什么样子的情形的?4. 像我说的这种情况,比如一页有16个item,有什么高效的做法吗?求指点~~多谢。[ 此帖被cissyhope在 09:41重新编辑 ]
级别: 新手上路
可可豆: 20 CB
威望: 20 点
在线时间: 107(时)
发自: Web Page
这样的期待应该是不正确的,auto-batching是用来处理类似 item1:1,2,3,4,5,6 和 item2:6,5,4,3,2,1 比如先draw item1 ,再draw item2 ,那么auto-batching 的draw call是11,会把两个*****并如果用以前的batchnode,这块地方代码上显然不能把item1 和item2 batch在一起,所以draw call应该是12auto-batching是把所有需要draw的list的里面的东西,能按顺序batch的都batch在一起不过好像其实如果在3.0中使用了batchnode,结果会导致这个batchnode无法被再次auto-batching所以当 batchnode1:1,1,1&&和batchNode2:1,1,1,1他们的draw call还是2,而不是1....这一点让我觉得有点无语...
级别: 新手上路
UID: 141838
可可豆: 35 CB
威望: 35 点
在线时间: 27(时)
发自: Web Page
回 1楼(waiter951) 的帖子
啊,可算有人理了,眼泪哗哗的,太感人了。原来只会合并这么一点啊,那顶锅盖说感觉改进不是特别大啊。
级别: 新手上路
可可豆: 20 CB
威望: 20 点
在线时间: 107(时)
发自: Web Page
回 2楼(cissyhope) 的帖子
batch的主要效果体现在比较大量的sprite的时候,如果本身就只有一点点sprite,那么其实也没有什么特别提示效果
级别: 新手上路
UID: 141838
可可豆: 35 CB
威望: 35 点
在线时间: 27(时)
发自: Web Page
回 3楼(waiter951) 的帖子
那么像原问题里的这种每个item都比较复杂的table,怎么做比较高效呢?
级别: 骑士
UID: 34816
可可豆: 468 CB
威望: 587 点
在线时间: 687(时)
发自: Web Page
没有先后顺序的sprite draw,我觉得11,22,33,44,55,66是值得期待的,可以有个render的状态值开关,告诉这一批的随便排序
级别: 新手上路
UID: 141838
可可豆: 35 CB
威望: 35 点
在线时间: 27(时)
发自: Web Page
回 5楼(lion) 的帖子
因为之前是用unity+NGUI就可以这样合并,所以就这么期待了
级别: 新手上路
可可豆: 20 CB
威望: 20 点
在线时间: 107(时)
发自: Web Page
回 6楼(cissyhope) 的帖子
因为unity主要是3d的,主要使用的jpg,所以可以这样合并如果实在要做得稍微高效一点,而且不更改引擎的前提下,那么这样做:item1 和 item2 只是名义上把它的元素包括起来,但是这些元素并不是直接add到item1 和 item2 上面元素自己手动分层,比如所有1全部都添加到一个只添加1的节点上....这样相当于自己把sprite的顺序理顺,这样引擎就可以batch在一起了
级别: 新手上路
UID: 141838
可可豆: 35 CB
威望: 35 点
在线时间: 27(时)
发自: Web Page
回 7楼(waiter951) 的帖子
嗯,这样就太麻烦了,我觉得还是要求设计改改比较快
unity主要使用的jpg所以可以这样合并是什么意思,没看懂呢?
级别: 新手上路
可可豆: 20 CB
威望: 20 点
在线时间: 107(时)
发自: Web Page
回 8楼(cissyhope) 的帖子
在3d中,一般jpg都有不同的z值,如果相同z值,那么就不知道谁在前面谁在后面了。然后jpg绘制不需要考虑和其他的颜色叠加,因为没有透明度,只要覆盖就行了,而png则因为有透明度,需要和后面的颜色叠加,必须按顺序来
Pages: 1/2
关注本帖(如果有新回复会站内信通知您)
苹果公司现任CEO是谁?2字 正确答案:库克
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 浏览移动版1773人阅读
Unity性能分析及优化(27)
批渲染(Batch)
batch render 是大部分引擎提高渲染效率的方法,基本原理就是通过将一些渲染状态一致的物体合成一个大物体,一次提交给gpu进行绘制,如果不batch的话,就要提交给很多次,这可以显著的节省drawcall,实际上这主要节省了cpu的时间,cpu从提交多次到提交一次,对gpu来说也不用多次切换渲染状态。当然能batch的前提一定是渲染状态一致的一组物体。
Unity3d的批渲染分为两种,动态和静态
要求:必须使用同一张material,然后在编辑器里设置为static batching的。
特点:静态批是无法运动的。
所以一般制作流程上,对于场景这些静态的物体都采用静态批,美术会根据场景的规模,将相邻的一片物件的贴图合并到一张或几张的大图上,这样这些物件可以使用同一个material,就可以静态批在一起,大幅节省dc。
静态批的时候Unity3d会在运行时生成一个合并的大模型,并且为这个模型指定一张共同的贴图,所以这个批在一起的数量是有限的,如果批在一起的定点数过多,它就会自动分成两个批,一个静态批的上限我自测大约在60000多个顶点单元。
场景中不能移动的物件可以使用静态合并,它不受顶点数的限制,可以大幅减少DrawCall。但为了将元素合并到一个大模型中,这项技术需要额外的内存。主要的内存消耗在于共享多边形会在内存中重复创建。因此有时候需要牺牲渲染效率来避免静态合并,来保证内存够小。例如在茂密的树林中使用这项技术会导致大量的内存消耗。
动态批是对那些没有标记成static batching的物体在runtime unity自动将他们批在一起,这个是可以支持运动物体的,但是限制较为严格:
动态合并在满足以下条件时是自动完成的:
1.一个批次总顶点单元少于900 (模型总顶点数小于900)
2.批在一起的所有的模型应用同样的缩放值(不包含镜像transform改变。不改变Scale)
3.使用相同的材质
4.相同的一张lightmap(如果使用动态lightmap需要指定正确)
5.不能使用多pass的shader
6.不能接收阴影
由于需要在合并时通过CPU计算转为世界坐标,这项技术只在CPU消耗比DrawCall消耗“便宜”时才值得。这个衡量标准会根据平台产生差异,例如苹果平台上DrawCall的消耗便宜,就不应该使用这项技术。这个功能可以在Editor-&Project Setting-&Player中进行设置打开与关闭。
所以一般是小的运动的模型才比较容易动态批在一起,当然unity又说可能在后续版本放宽这个限制
NVIDIA 在GDC上曾提出 25k batch/sec的渲染量会使1GHz的CPU达到100%的使用率,因此使用公式
25K*n(GHZ)*Percentage/Framerate=Batch/Frame
可以推算出某些CPU可以抗多少Batch。例如红米手机CPU为1.5GHz,假设分出20%资源供渲染,希望游戏跑到30帧。那么能抗多少DrawCall? 25k * 1.5 * 0.2 / 30 = 250。因此从这方面也能看出,如果CPU不能分出更多的资源供渲染计算,能抗的DrawCall就会变少。
Unity5.0及以上,如果场景中有3个对象,且都用同一个shader(材质),这三个对象模型的总顶点数多于900个,则需要进行两次合批,每次合批都会调用三次DrawCall,但CPU的状态不会改变,既不用进行状态的检查(CPU的计算绝大多数时间花在了状态检查上),速度会快很多;(DrawCall数会多于batches数)
Unity5.0以下,每次合批,只会生成一个DrawCall;
对于Unity5.0及以上,可以通过判断两个物体的shader(材质)是否相同,若相同,则使这两个物体具有相同的MeshRenderer组件,则可以达到合并DrawCall的目的,以减少DrawCall。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:71309次
积分:1544
积分:1544
排名:千里之外
原创:39篇
转载:260篇
评论:15条
(5)(12)(21)(96)(36)(19)(13)(17)(42)(32)(23)posts - 273,&
comments - 12,&
trackbacks - 0
Unity性能优化之Draw Call
Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:引擎首先经过简单的可见性测试,确定摄像机可以看到的物体,然后把这些物体的顶点(包括本地位置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好,然后通知图形API&&或者就简单地看作是通知GPU&&开始绘制,GPU基于这些数据,经过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。
在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。这一过程是逐个物体进行的,对于每个物体,不只GPU的渲染,引擎重新设置材质/Shader也是一项非常耗时的操作。因此每帧的Draw Call次数是一项非常重要的性能指标,对于iOS来说应尽量控制在20次以内,这个值可以在编辑器的Statistic窗口看到。
Unity内置了技术,从名字就可以看出,它的主要目标就是在一次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次数才是王道,其它方面亦然。
阅读(...) 评论()

我要回帖

更多关于 缠论k线的合并规则 的文章

 

随机推荐