如何降低Unity程序的unity降低drawcalll

求教大场景优化的问题,主要是模型太多drawcall爆表【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:77,598贴子:
求教大场景优化的问题,主要是模型太多drawcall爆表收藏
先一直做游戏,没有太多模型,ui的话用nguidrawcall也不多,目前暂时做的一个虚拟,模型很多,很多时候摄像机照射范围内drawcall涨到5000+都有我目前只知道的优化场景就是bake光影 但是如何减drawcall真心不知道了
51CTO学院11年行业品牌,1400万用户选择,中国专业IT技能学习平台,unity能做什么.通过在线学习的方式,帮助广大技术人员实现技能提升,高薪就业的职业梦想,unity能做什么.
自认为200就不得了了
大神,解决了吗
登录百度帐号推荐应用unity--优化CPU之DrawCall - 简书
unity--优化CPU之DrawCall
CPU准备数据并通知GPU渲染的过程就是一次DrawCall,如果这个过程出现的次数太多,就会影响CPU的执行效率,就会出现卡顿。
当然,影响CPU的不仅仅只有DrawCall,还有物理组件、GC(垃圾对象太多,造成GC负担,影响CPU的执行效率)、代码质量。
Draw Call Batching
在屏幕上绘制一个物体,U3D引擎必须向绘图API(openGL或者D3D)发起一次DrawCall。这些DrawCall往往是昂贵的,当绘图API为每个DrawCall做一些重要的事情,引起GPU的性能消耗较高。这些消耗大部分是因为DrawCall结束的状态切换引起的(比如,从一个材质切换到另一个材质),因为这会引发昂贵显卡驱动的验证和变换步骤。
Unity使用多种技术来解决这个问题:静态Batching:把静态的物体合并成一个大meshes,然后用更快的方法渲染他们。动态Batching:对于足够小的meshes,在CPU上变换他们的顶点,将一些相似的组合到一起,在一次中绘制。
内建的Baching相对于手动合并物体到一起有几个好处(值得注意的是,这些对象仍可以被单独销毁)。但是他也有它的缺点(静态Batching会导致内存和存储的开销,动态Batching会导致CPU开销)。
Material Setup For Batching(合并材质)
只有共享同一个材质的物体才能被Batched在一起。如果,你想达到一个好的batching,你需要竟可能多的在不同物体中共享材质。如果你有两个同样的材质但是他们的textures不同,你可以合并这些textures到一个大texture - 这个过程经常被叫做texture atlasing。一旦textures在同一个图集中,你就可以使用一个材质来代替了。如果你需要在脚本中访问共享了的材质,有一个很重的点需要注意:修改Renderer.material属性会创建一个当前材质的副本。所以,作为替换方案,你应该使用Rednerer.sharedMaterial以保证材质被共享。当渲染阴影投射的时候,即使他们的材质是不同的,也经常被batched到一起。只要材质中的数值在shadow pass是相同的,即使阴影投射有不同的材质,他们也可以使用动态batching。举个例子,许多箱可以使用具有不同的texture的材质,但对于阴影投射渲染 texture是不相关 - 在这种情况下,他们可以被batched到在一起。
Dynamic Batching(动态批处理)
Unity可以自动batch移动物体到相同的draw call,如果它们具有相同的材质和满足其它标准。动态Batching是自动完成的,不需要你做额外的事情。Batching 动态的物体每个顶点会有某些开销,所以batching只适用于顶点数小于900的meshes。如果你得shader使用了顶点位置,法线和单独的UV,那么你可以batch 300 个顶点;如果你得shader使用了顶点位置,法线,UV0,UV1,和正切,只能batch 180个顶点。
这个限制的数量将来有可能会变化。
如果物体包含镜像变换,他们将不会被batched,例如,object A 的scale 为 +1 object B 的scale 为-1,就不能batched到一起。
使用不同材质的实例,即使他们实质上是相同的,也会导致两个物体不能被batched到一起。阴影投射除外。
具有光照贴图的对象有额外的渲染参数:光照索引和 偏移/放缩 的光照。所以一般动态lightmapped对象应指向完全相同的光照贴图位置然后再进行batch。
多通道的shader将不会被batching几乎所有的Unity shader都支持前置渲染几个灯光,有效的为他们做更多的通道。“额外的逐像素的灯光”的draw call 将不会被batched。
传统的延迟渲(逐通道光照)染通道禁用了动态batching,因为它必须绘制两次。
由于它的工作原理是变换所有的物体的顶点到CPU的世界坐标中,所以它仅仅在它的工作(变换到cpu的世界坐标)比做一次“draw call”小的时候才能起到好的作用。究竟一个DrawCall有多昂贵取决于诸多因素,主要是所用的绘图API。例如,在控制台或当前流 行的APIs例如Apple Metal DrawCall的开销一般比较低,所以一般动态batching不会达到好的效果。
Static Batching(静态批处理)
静态batching允许引擎减少draw call适用于任何大小的几何对象(假设没有移动和共享材质)。大部分情况下他比动态batching更高效 ,但是它会占用更多的内存。为了使静态batching更好的获益,你需要明确的指定游戏中某些物体是静态的而且不会移动,旋转或者缩放。这样做,你可以在Inspector界面中的“Static”选项(chekbox)标记物体为static:
使用静态batching将需要额外的内存来存储合并后的几何信息。如果几个物体在静态batching之前共享同一个几何图元,那么这个几何图元将会为每个物体复制一份,无论在Editor中还是runtime中都是如此。这不是一个好方法 - 有时候为了保持更小的内存占用量,你必须牺牲渲染性能为了避免一些物体的静态batching。例如,在一个稠密的森林中,标记树木为static会产生严重的内存影响。在内部,静态batching的原理是变换这些静态物体到世界控件然后为他们建立一个很大顶点+索引 缓冲区。然后所有显示的物体都放到一个batch,一系列“便宜的”draw call就完成了,这期间几乎没有状态切换(state change)。所以 从技术上来讲 这并没有节省“3D API draw call”,但是他节省了他们之间的状态切换(状态切换才是罪魁祸首)。
Other Batching Related Tips
目前,只有网格渲染才被batched。像 skinned meshes,cloth,拖尾渲染器(Trail Renderer)和其他类型的渲染组件是不被batched的。半透明shader为了做透明度的工作,经常需要物体以从后到前的顺序进行渲染。Unity首先会对物体进行排序,然后试着batch他们 - 因为这个顺序是严格限制的,这就意味着 相对于不透明物体来说,会有很少的batching产生。相对调用draw call来说,手动合并比较近的物体可能是一个非常不错的选择。例如,许多抽屉的静态柜子合并成一个mesh经常是有道理的,无论是在3D建模软件中还是使用bineMeshaes.
试着做一个有态度的人【风宇冲】Unity3D性能优化:DrawCall优化
原创文章如需转载请注明:转载自
DrawCall优化
二 Skinned Mesh
三 合并要求对比
五 场景制作建议
DrawCall优化合并,也叫批处理,即DrawCall
Batching. 通过减少Draw call数提高性能。
分为Dynamic Batching和 Static Batching
不需要任何操作,只要共享材质(即使是不同的Mesh模型也可以),就会自动被合并。可以自由移动旋转。但有以下使用要求:
(1)单个Mesh的vertex attribute总数不超过900.
即 vertex* attributeCount & 900
例如一个Mesh有pos,uv,normal,那么attributeCount为3,
也就是顶点数量不超过300个。
(2)游戏对象使用相同模型和材质时,只有相同缩放(即xyz等比缩放,浮点尾数可以有细微差)的会被合并。
(1,1,1)与(1,1,1)
(2,2,2)与(2,2,2)
(0.5,0.5,0.5)与 (0.5,0.5,0.5)
(2,2,2)与(2,2,2.0001)
(3)场景烘焙:烘焙后同材质将不会被烘焙。lightmap
有隐藏的材质参数:offset/scale, 所以使用lightmap的物体不会被合并
(4)Shader不能使用多Pass:多Pass的Shader会破坏Dynamic Batching
运行游戏后将一组游戏对象的多个模型会被动态合并为1个。这组游戏对象所有使用同一材质的在一个DrawCall来完成。这些游戏对象运行后无法移动缩放旋转。但是Drawcall一定是最大化合并的,并且不受动态合并的诸多限制(见下文详述)。
注意:即使物体都使用了同样的模型,在batch后每一个物体都会创建一份模型对应的geometry,在新的Combined
Mesh里。所以过多的batch会增加内存占用。例如场景里的树群就不适合Static Batch,而适合动态合并。
(1)MeshRenderer勾选Batching Static: 勾了即可
(2)代码中使用UnityEngine.StaticBatchingUtility实现(可以在任何平台调用):
& & 1)将所有要合并的静态物体(不须勾Batching
Static)放入统一一个root
2)StaticBatchingUtility.Combine(root);
之后就合并好了!
勾选Batching Static:
完全自动合并,在MeshFilter里显示的是 Combined
Mesh(root:scene)。合并后不能移动
StaticBatchingUtility:
合并到一个游戏对象下。合并后可以移动父节点游戏对象
Skinned Mesh Renderer
Unity对Skinned Mesh Renderer没有任何batching, 但插件Mesh
Baker可以对Skinned Mesh进行合并。
(1)修改Renderer.material将会创建一份新的material,应使用Renderer.sharedMaterial来保持材质公用。
(2)可以使用Mesh.Optimize()&优化模型。导入模型不需要调用此接口,在导入模型至Unity3d时已自动处理。
代码创建的模型有可能需要调用此接口来优化。
三 合并要求对比
只能是MeshRenderer不能是SkinnedMeshRenderer
2 Shader必须是单Pass
3 不能被场景烘焙(不能标注为Light map
4 网格模型文件总点数要求
5 网格模型单个文件点数要求
6 限制缩放
7 限制位移旋转
另外Unity中任何Mesh的面 有65536的面数限制
三种方式:
1 动态合并
&&& 优点:
内存消耗小
可以自由位移旋转
&&& 缺点:
要求众多()
2 标记Light map static合并
&&& 优点:
最方便快捷,要求最少
&&& 缺点:
完全不能移动
&内存有消耗
只能处理在Scene中默认放置的物体
3 代码StaticBatchingUtility合并
&&& 优点:
&方便快捷,要求少
可整体移动
可处理代码动态加载的场景或物体
&&& 缺点:
内存有消耗
代码合并是要求最少的,并可以整体移动。而动态合并可以移动旋转,并做Animation动画。故推荐StaticBatchingUtility
+ 动态合并。
五 场景制作建议
美术人员在制作某场景时,尽量:
静态物体:使用静态合并
1 用Mesh Renderer,也就是不绑定骨骼
2 不是Wrap循环UV的贴图,尽量合并到一张大图集
标注Batching Static即可
动态物体:使用动态合并,动画可以用Unity的动画去做
2 不参与场景烘焙
3 相同物体相同缩放
4 单个Mesh的vertex attribute总数不超过900.
5 Shader单Pass
满足条件Unity自动优化
(不满足动态合并要求的。场景动画可以用骨骼动画去做。但应尽量避免或者少的使用这种方式。因为没有Drawcall优化效率较低)
要关闭动态合并在subshader里加以下代码即可
Tags&{&"DisableBatching"&=&"true"&}
如果是非Mobile端可以考虑使用GPU Instancing
如果是有超级多的人,可考虑使用顶点动画提高性能。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。unity 移动开发 在手机上的流畅呢? drawcall要控制在多少合适 - 知乎16被浏览2088分享邀请回答13 条评论分享收藏感谢收起41 条评论分享收藏感谢收起写回答在5中减少Draw Calls(SetPass Calls)
我一直工作于支持的Standard Shader(标准着色器)上,并且做了一些关于如何有效地减少draw call的测试,在Unity5全新的standard shader上,实际成果相当可观。
我们先科普一下standard shader。Standard Shader是个基于物理的着色器,&物理渲染和当今的主流光照计算最大的区别就是,当今的lambert blinn phone基本上是基于模拟的模型,就是尽可能的去模拟我们看上去的物体反射的颜色,甚至可以说是拍脑袋的模型,用于欺骗我们的眼睛,而基于物理的光照计算则是依据了光线传播的物理特性,更加贴近于真是的光照情况,虽然在实现上还是用了一些近似计算。所以物理渲染在表现自然界的物体时尤其的看上去更加真实。
这是个小视频介绍了下standard shader可以实现的效果,官方的U5Shader视频
这个standard shader&变化&是变得更快还是更慢,取决于贴图你使用的texture slots。尽管如此,这两种着色器是不同的(即使他们使用的都是standard shader):
&ignore_js_op&&
这两个shader(即使他们是&Standard shader&)
当渲染场景时他们是完全不同的shader,因此如果我们想减少一些draw call(setpass call),必须采用完全不同的处理方式。
在谈到如何在Unity5减少draw call之前,我将探讨无论shader是否被使用时怎样减少draw calls,然后讨论在Unity5中使用Standard shader减少draw calls.
在Unity中用手动方式降低Draw Call
如果我们想减少draw call,在Unity中或者在其他引擎上,可以尽量减少使用的material(材质)。基本上,这些可以还原为这些简单的步骤:
1.整理所有的material并且通过他们的shader类型收集他们
2.第二步:对于使用相同shader的材质,将他们的贴图做成一个图集(Atlas)
3.创建一个material,它将包含shader和图集(Atlas)
4.网格的所有UV重新映射,使用Shader适配图集的坐标
5.用映射的网格创建出步骤3的material
第一步:整理所有的material,并收集它们的shader类型
我打算用一个简单的场景解释,这个场景所有网格使用的是相同类型但不同texture的material.
在我们的情况下,我们将使用这个场景(其中包含4个material,其中每一个都具有Bumped Diffuse shader):
& &&&ignore_js_op&&& && && &
注意SetPass calls:4& && && &
所以我们要对这一场景的这些material进行处理:& &
第二步:对于使用相同shader的材质,将他们的贴图做成一个图集(Atlas)
在我们的例子中,我们有2个texture,每一个着色的漫反射贴图使用一个正常的法线贴图和一个基本texture,所以我们需要做的是将这两个texture这样设置:& && && &
&&&&ignore_js_op&&
保存这些texture在项目视图中,我们一会儿将需要它们:
&ignore_js_op&&& && && && &
第三步:创建一个material,它将包含shader和图集(Atlas)
创建一个material,并将两张贴图和Shader(Bumped Diffuse)赋予给材质:& && &
&&&&ignore_js_op&&& && && && &
第四步:网格的所有UV重新映射,使用Shader适配图集的坐标
这个修改可以用任何建模软件(Maya/ 3D studio / Max / Blender /等)来操作。
这是很无聊的又很必要的步骤,包括修改网格的UV坐标并且使它们适配texture图集(我们第二步创建的texture图集)。
所以我们要做的是,将每一个UV坐标设置为[ 0,0&1,1 ],我们可以将他们重新定位在一个[ 0,0-1,1 ]的较小的子范围中,这样就与步骤2中创造的图集相匹配。
&ignore_js_op&&& && && &&&
接着&&我们为每个网格共享相同的shader。& && && && &
第五步:用你映射的网格创建出步骤3的material& && && &
我们基本上完成了!我们还有几步要做:& && && && &
1。选择你所有的UV映射网格,用他们替换旧网格的位置并且停用旧的网格
2。将步骤3创造的材质赋予所有的UV映射网格。& &
&ignore_js_op&&& && && &
到了这里,我们就结束了!,现在让我们点击play看看:
& && && && &
&ignore_js_op&&& &&&
在优化前,如果你回到步骤1,我们有4个SetPass call,现在优化已经完成,我们最终就有1个 SetPass call!太惊人了!在这种情况下,它的75%draw call减少了。& && && && &
在Unity5中减少绘制调用的标准着色& && &&&
在这里,你应该知道多了解些在standard shader上优化过程是如何做的。我在开头写了,standard shader内部&变化&和越来越快/慢,取决于你使用的texture slots。就是说,我们必须收集我们对象的material,如果他们使用了texture也使用的Standard shader。
通过使用的texture归类这些对象,我们只需要遵循我们用于所有shader的以下几个步骤:
& && && && &
1.整理所有的material并且通过他们的shader类型收集他们
2.第二步:对于使用相同shader的材质,将他们的贴图做成一个图集(Atlas)
3.创建一个material,它将包含shader和图集(Atlas)
4.网格的所有UV重新映射,使用Shader适配图集的坐标
5.用映射的网格创建出步骤3的material
& && && &&&
这是我为测试创建的一个小场景:
&ignore_js_op&&& && && &
如果你比较原始场景的draw call(91)和优化后场景的draw call(22),你可以看到,有75%draw call减少了!,太惊人了!& &
此外,如果你可以尝试尽可能多的组合网格,这也有很多帮助!。& && && && &
原文链接:
阅读(...) 评论()

我要回帖

更多关于 降低drawcall 的文章

 

随机推荐