Unity的DrawCall

简介:



图形引擎渲染画面的过程

Unity(或者说基本所有图形引擎)生成一帧画面的处理过程大致可以这样简化描述:

1. 可见性测试

1. 引擎首先经过简单的可见性测试,确定摄像机可以看到的物体

2. 准备好物体的数据

2. 然后把这些物体的顶点(包括本地位置、法线、UV等),索引(顶点如何组成三角形),变换(就是物体的位置、旋转、缩放、以及摄像机位置等),相关光源,纹理,渲染方式(由材质/Shader决定)等数据准备好

3. 通知图形API开始绘制

3. 然后通知图形API——或者就简单地看作是通知GPU——开始绘制,GPU基于这些数据,经过一系列运算,在屏幕上画出成千上万的三角形,最终构成一幅图像。

什么是Draw Call

在Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。

这一过程是逐个物体进行的,对于每个物体,不止GPU的渲染,引擎重新设置材质/Shader也是一项非常耗时的操作。

因此每帧的Draw Call次数是一项非常重要的性能指标,对于iOS来说应尽量控制在20次以内,这个值可以在编辑器的Statistic窗口看到。

Draw Call Batching 技术

Unity内置了Draw Call Batching技术,从名字就可以看出,它的主要目标就是在一次Draw Call中批量处理多个物体。

只要物体的变换和材质相同,GPU就可以按完全相同的方式进行处理,即可以把它们放在一个Draw Call中。

Draw Call Batching的核心

Draw Call Batching技术的核心就是在可见性测试之后,检查所有要绘制的物体的材质,把相同材质的分为一组(一个Batch),然后把它们组合成一个物体(统一变换),这样就可以在一个Draw Call中处理多个物体了(实际上是组合后的一个物体)。

Draw Call Batching的缺陷

但Draw Call Batching存在一个缺陷,就是它需要把一个Batch中的所有物体组合到一起,相当于创建了一个与这些物体加起来一样大的物体。

与此同时就需要分配相应大小的内存。这不仅会消耗更多内存,还需要消耗CPU时间。

特别是对于移动的物体,每一帧都得重新进行组合,

但对于静止不动的物体来说,只需要进行一次组合,之后就可以一直使用,效率要高得多。

这就需要进行一些权衡,否则得不偿失。

Dynamic Batching和Static Batching

Unity提供了Dynamic Batching和Static Batching两种方式。

Dynamic Batching

Dynamic Batching是完全自动进行的,不需要也无法进行任何干预。

对于顶点数在300以内的可移动物体,只要使用相同的材质,就会组成Batch

Static Batching

Static Batching则需要把静止的物体标记为Static,然后无论大小,都会组成Batch。

如前文所说,Static Batching显然比Dynamic Batching要高效得多,于是,Static Batching功能是收费的……

高效利用Draw Call Batching

要有效利用Draw Call Batching,有以下注意点:

1. 首先是尽量减少场景中使用的材质数量,即尽量共享材质,对于仅纹理不同的材质可以把纹理组合到一张更大的纹理中(称为Texture Atlasing)。

2. 然后是把不会移动的物体标记为Static。此外还可以通过CombineChildren脚本(Standard Assets/Scripts/Unity Scripts/CombineChildren)手动把物体组合在一起,但这个脚本会影响可见性测试,因为组合在一起的物体始终会被看作一个物体,从而会增加GPU要处理的几何体数量,因此要小心使用。

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

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

 

参考资料: http://ravenw.com/blog/2011/10/14/unity-optimization-of-draw-call/#sthash.eWSmEU7K.dpuf

理解二:DrawCall

在Unity查看Draw Call

开发游戏时,一定被时时提醒要减少 Draw Call,当然Unity也不例外,打开Game 窗口裡的 Stats,可以看到 Draw Call 与 Batched 的数字。

image

Draw Call 定义

但到底甚麼是 Draw Call?影响的效能是来自 CPU?还是 GPU?
首先,让我们定义何為 “Draw Call”:

 

“一个 Draw Call,等于呼叫一次 DrawIndexedPrimitive (DX) or glDrawElements (OGL),等于一个 Batch”

摸过 DirectX 或 OpenGL 的人来说,对 DrawIndexedPrimitive glDrawElements 这 API 一定不陌生。

当我们准备好资料 (通常为三角面的顶点资料) 要 GPU 划出来时,一定得调用这个函数。

举例说明

换句话说,如果在画面上有一张 “" 椅子、一张 “" 桌子,那理论上就会有两个 Draw Call。

有看到特別指出 “木" 与 “铁" 吗?这代表两物件是使用不同材质球或者不同的 Shader。

在 DirectX 或 OpenGL 里,对不同物件指定不同贴图或不同 Shader 的描述,就会需要呼叫两次Draw Call。

举例代码

复制代码
SetShader( “Diffuse" ); 
SetTexture( “铁" ); 
DrawPrimitive( DeskVertexBuffer );  

SetShader( “VertexLight" ); 
SetTexture( “木" ); 
DrawPrimitive( ChairVertexBuffer );
复制代码

 

每次对 Shader 的更改或者贴图的更改,基本上就是对 Rendering Pipeline 的設定做修改,所以需要不同的 Draw Call 來完成物件的绘制。

現在了解为什麼 UNITY 官方文件里,老是要你尽量使用同样材质球,以减少 Draw Call 数量了吧!

Batch(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:

image

举个例子:如果你的目标是游戏跑30FPS、使用2GHz的CPU、20%的工作量发給Draw Call來使用,那你每秒可以有多少Draw Call呢?

333 Batchs/Frame = 25K * 2 * (0.2/30)

那既然 Batch 是个箱子,里头裝着物件的顶点资料,再依据我們上面的描述,

那将同样材质和Shader 的物件,可以合併成一個 Batch 送往 GPU,这样就是最省事的方法喽?Yes!就是這樣沒錯!

UNITY 在 Player Setting 里的两个功能选项 Static Batching 与 Dynamic Batching。功能描述如下:

image 

Static Batching

Static Batching 是将标明为 Static 的静态物件,如果在使用相同材质球的条件下,UNITY 会自动帮你把这两个物件合併成一个 Batch,送往 GPU 来处理。

这功能对效能上非常的有帮助,所以是需要付费才有的

Dynamic Batching

Dynamic Batching 是在物件小于300面的条件下(不论物件是否不静态或动态),在使用相同材质球下,UNITY就会自动帮你合併成一个 Batch 送往 GPU 来处理。

 

参考资料:http://www.unityin.com/2012/09/draw-call-batch-%E5%82%BB%E5%82%BB%E5%88%86%E4%B8%8D%E6%B8%85%E6%A5%9A/



本文转自赵青青博客园博客,原文链接:http://www.cnblogs.com/zhaoqingqing/p/4623839.html,如需转载请自行联系原作者

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
前端开发 图形学 异构计算
Unity优化之Drawcall
Unity优化之Drawcall
515 0
|
图形学
Unity UGUI如何计算drawcall
Unity UGUI如何计算drawcall
127 0
|
图形学
unity如何计算drawcall
unity如何计算drawcall
189 0
|
前端开发 图形学 异构计算
unity优化之DrawCall
unity优化之DrawCall
245 0
|
Java 图形学 iOS开发
unity3d Drawcall优化方法
unity3D 对于移动平台的支持无可厚非,但是也有时候用3D 开发出来的应用、游戏在移动终端上的运行有着明显的效率问题,比如卡、画质等各种问题。自己在做游戏开发的时候偶有所得。
1471 0
|
图形学 缓存 程序员
[Unity3d]DrawCall优化手记
在最近,使用U3D开发的游戏核心部分功能即将完成,中间由于各种历史原因,导致项目存在比较大的问题,这些问题在最后,恐怕只能通过一次彻底的重构来解决 现在的游戏跑起来会有接近130-170个左右的DrawCall,游戏运行起来明显感觉到卡,而经过一天的优化,Draw...
1074 0
|
4月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
206 6
|
3月前
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
131 4
|
4月前
|
图形学 缓存 算法
掌握这五大绝招,让您的Unity游戏瞬间加载完毕,从此告别漫长等待,大幅提升玩家首次体验的满意度与留存率!
【8月更文挑战第31天】游戏的加载时间是影响玩家初次体验的关键因素,特别是在移动设备上。本文介绍了几种常见的Unity游戏加载优化方法,包括资源的预加载与异步加载、使用AssetBundles管理动态资源、纹理和模型优化、合理利用缓存系统以及脚本优化。通过具体示例代码展示了如何实现异步加载场景,并提出了针对不同资源的优化策略。综合运用这些技术可以显著缩短加载时间,提升玩家满意度。
243 5
|
3月前
|
前端开发 图形学 开发者
【独家揭秘】那些让你的游戏瞬间鲜活起来的Unity UI动画技巧:从零开始打造动态按钮,提升玩家交互体验的绝招大公开!
【9月更文挑战第1天】在游戏开发领域,Unity 是最受欢迎的游戏引擎之一,其强大的跨平台发布能力和丰富的功能集让开发者能够迅速打造出高质量的游戏。优秀的 UI 设计对于游戏至关重要,尤其是在手游市场,出色的 UI 能给玩家留下深刻的第一印象。Unity 的 UGUI 系统提供了一整套解决方案,包括 Canvas、Image 和 Button 等组件,支持添加各种动画效果。
150 3