Unity中的批处理优化与GPU Instancing【转】

我们都希望能够在场景中投入一百万个物体,不幸的是,渲染和管理大量的游戏对象是以牺牲CPU和GPU性能为代价的,因为有太多Draw Call的问题,最后我们必须找到其他的解决方案。

在本文中,我们将讨论两种优化技术,它们可以帮助您减少Unity游戏中的Draw Call数量以提高整体性能:批处理和GPU Instancing。

批处理
开发者在日常工作中遇到的最常见的问题之一是性能不足,这是由于CPU和GPU的运行能力不足。一些游戏可以运行在PC上,但是在移动设备上不行。游戏运行时运行是否流畅受Draw Call数量的影响很大。有几个解决方案能帮助您解决这个问题。最常见的是批处理,包括Static Batching和Dynamic Batching。

Static Batching可以让引擎降低任何尺寸网格的Draw Call,如下图所示:

<ignore_js_op>

要让场景中的物体使用Static Batching,需要将其标记为Static,并在Mesh Renderer中共享相同的材质,因为Static Batching不会在CPU上做顶点转换,所以它通常比Dynamic Batching更有效。不过它会使用更多的内存,例如你的场景中有相同物体的多个副本,Unity会将它们组合成一个大网格并可能会增加内存使用。Unity将尽可能多的网格结合到一个静态网格中,并将其作为一个Draw Call提交。这种方法的缺点是:标记为Static的物体在其生命周期中不能移动。

Dynamic Batching启用时,Unity将尝试自动批量移动物体到一个Draw Call中。要使物体可以被动态批处理,它们应该共享相同的材质,但是还有一些其他限制:

  • 顶点数量:Dynamic Batching场景中物体的每个顶点都有一定的开销,因此批处理只适用于少于900个顶点属性的网格物体。举个例子,如果你的着色器使用顶点位置,法线和一个UV,那么你可以动态批处理多达300个顶点;而如果你的着色器使用顶点位置,法线,UV0,UV1和切线,那么只有180个顶点。值得注意的是,属性计数限制可能会在将来更改。
  • 镜像信息:如果物体包含的Transform具备镜像信息,例如A物体的大小是(1f, 1f, 1f),而B物体的大小则是(-1f, -1f, -1f),则无法做批处理。
    材质:如果物体使用不同的材质实例,即使它们本质上相同,也不会被批量处理。而Shadow Caster Rendering是个例外。
  • 渲染器:拥有光照贴图的物体有其他渲染器参数,例如光照贴图索引或光照贴图的偏移与缩放。一般来说,动态光照贴图的游戏对象应该指向要批量处理的完全相同光照贴图的位置。
  • 不能使用Multi-pass着色器的情况:几乎所有的Unity着色器都支持多个灯光的正向渲染模式(Forward Rendering),这要求额外的渲染次数,所以绘制 “额外的每像素灯”时不会被批处理;Legacy Deferred(Light Pre-Pass)渲染路径不能被动态批处理,因为它必须绘制物体两次。

Dynamic Batching通过将所有物体的顶点转换为CPU上的世界空间来工作,所以它只能在渲染Draw Call的工作量小于CPU顶点转换工作量的时候,才会起到提高性能的作用。当用游戏机或如Metal这样的现代API,Draw Call的开销通常低得多,Dynamic Batching就无法提高性能了。了解到以上限制后,如果明智地使用批处理,可以显著提高您游戏的性能。

GPU Instancing
提高图形性能的另一个好办法是使用GPU Instancing。GPU Instancing的最大优势是可以减少内存使用和CPU开销。当使用GPU Instancing时,不需要打开批处理,GPU Instancing的目的是一个网格可以与一系列附加参数一起被推送到GPU。要利用GPU Instancing,您必须使用相同的材质,且可以传递额外的参数到着色器,如颜色,浮点数等。

Unity从5.4版本开始支持GPU Instancing。 唯一的限制是在游戏物体上要使用相同的材质和网格。 目前支持以下平台:

  • Windows DX11/DX12 和 SM 4.0 或更高/OpenGL 4.1 或更高
  • OS X and Linux:OpenGL 4.1 and above
  • 移动:OpenGL ES 3.0 或更高/Metal
  • PlayStation 4
  • Xbox One

如果您想要进行进一步的优化,例如减少管理场景物体的开销,您也可以使用Graphics.DrawMeshInstanced方法。 您只需要传递您的网格,材质和附加属性来绘制您的物体。现在的限制是一次最多1023个实例。在Unity 5.6中,我们添加了Graphics.DrawMeshInstancedIndirect的新方法,可以用来指定需要渲染的实例数量。

GPU Instancing案例
要创建支持GPU Instancing的基本标准表面着色器,可以在您的项目里面点击:
Create->Shader->StandardSurfaceShader(Instanced)。

<ignore_js_op>

然后,在材质属性中选择新创建的着色器。

<ignore_js_op>

虽然实例化的物体共享相同的网格和材质,但您可以使用MaterialPropertyBlock API为每一个物体设置单独的着色器属性。

如果一个游戏对象被标记为“Static”并且打开了Static Batching,那么这个游戏对象就不能进行GPU Instancing,检视器中会出现一个警告框,提示“静态批处理”标志可以在播放器设置(Player Settings)中取消。如果游戏对象支持Dynamic Batching,但是它使用的某个材质可以进行实例化,那么这个游戏对象将不会被批处理,并且将被自动实例化。

当使用Forward Rendering渲染模式,受多个灯光影响的物体无法有效地实例化。只有Base Pass可以有效地利用实例化,而不是添加的Pass。此外,使用光照贴图或受不同光或Reflection probe影响的物体无法实例化。如下图所示,您可以在Frame Debug中发现和GPU Instancing相关的Draw Call被标记为“Draw Mesh(Instanced)”。

<ignore_js_op>

GPU Instancing是一个非常强大的功能。在Unity 5.6中,您可以使用Graphics.DrawMeshInstancedIndirect绘制大量网格。在Mac Pro中,我们能够画出约68万个具有不同颜色的移动立方体并保持稳定的60帧每秒的帧率。

下图是一个示例场景,超过6千个包子在天空中围绕一个大碗飞翔,它们都投射和接收阴影。由于使用了GPU Instancing,几乎没有性能开销。这里的包子模型使用了StandardSurface Shader(Instanced)。

<ignore_js_op>

总结
在本文中,我们描述了用于优化渲染性能的两种最流行的技术:批处理和GPU Instancing。我们向您展示了如何在实践中使用它们并讨论可能的应用。正因为有诸如批处理和GPU Instancing等优化技术的存在,我们能够绘制大量的对象并保持稳定的性能。

想要及时获得更多有关Unity的技术分享,请扫描下方二维码,关注“Unity官方平台”微信公众号!

<ignore_js_op>

转载请注明来源:Unity官方中文社区 (forum.china.unity3d.com)。请勿私自更改任何版权说明信息。

时间: 2024-10-02 23:03:48

Unity中的批处理优化与GPU Instancing【转】的相关文章

【Unity技巧】Unity中的优化技术

写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得的~Digital Tutors是一个非常棒的教程网站,包含了多媒体领域很多方面的资料,非常酷!除此之外,还参考了Unity Cookie中的一个教程.还有很多其他参考在下面的链接中. 这篇文章旨在简要地说明一下常见的各种优化策略.不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料. 还有一些我认为非常好的参考文章: Performance Optimization for Mobile Devices

(转)【Unity技巧】Unity中的优化技术

写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得的~Digital Tutors是一个非常棒的教程网站,包含了多媒体领域很多方面的资料,非常酷!除此之外,还参考了Unity Cookie中的一个教程.还有很多其他参考在下面的链接中. 这篇文章旨在简要地说明一下常见的各种优化策略.不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料. 还有一些我认为非常好的参考文章: Performance Optimization for Mobile Devices

Unity教程之再谈Unity中的优化技术

这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点处理“一项.这里的几何体就是指组成场景中对象的网格结构. 3D游戏制作都由模型制作开始.而在建模时,有一条我们需要记住:尽可能减少模型中三角形的数目,一些对于模型没有影响.或是肉眼非常难察觉到区别的顶点都要尽可能去掉.例如在下面左图中,正方体内部很多顶点都是不需要的,而把这个模型导入到Unity里就会是

Unity中的GC以及优化

[简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译文搬运了过来,作为上面思维导图的知识点补充. [介绍] 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使用的过程. Unity中将垃圾回收当作内存管理的一部

【原创翻译】初识Unity中的Compute Shader

一直以来都想试着自己翻译一些东西,现在发现翻译真的很不容易,如果你直接把作者的原文按照英文的思维翻译过来,你会发现中国人读起来很是别扭,但是如果你想完全利用中国人的语言方式来翻译,又怕自己理解的不到位,反而与作者的愿意相悖.所以我想很多时候,国内的译者也是无奈吧,下次再看到译作也会抱着一些感同身受的态度去读.这是我第一次翻译整篇文章,能力有限,望见谅,翻译不好的地方也希望大家指出来. 其实ComputeShader在Unity中出现已经有蛮长的一段时间了,因为自己一直对Shader比较感兴趣,所

Unite 2018 | 《崩坏3》:在Unity中实现高品质的卡通渲染(下)

http://forum.china.unity3d.com/thread-32273-1-1.html 今天我们继续分享米哈游技术总监贺甲在Unite Beijing 2018大会上的演讲<在Unity上实现高品质卡通渲染的效果>下篇,上篇请点击此处阅读. 下面为演讲内容: 接下来我们就来介绍一下头发的渲染.头发是卡通渲染角色较为重要且独特的部分.我们想要实现根据光源动态变化的高光和阴影渐变,并且这个实现还应具备直观的所见即所得的色彩调节能力. 和皮肤的材质一样,对于头发的漫反射渲染我们同样

高速上手Unity中最好的补间动画插件DFTween

?? 出处:http://blog.csdn.net/u010019717 author:孙广东      时间:2015.3.17   23:00 DFTween 是一个在 Unity 游戏引擎中高速和easy使用的animation动画库. 它支持不论什么对象的tweening补间的属性, 并能够轻松地进行工作与您自己自己定义数据类型.API 非常简单可是功能非常强大,使其易于创建复杂的tweens补间和sequences序列.它已被优化从优秀性能.同一时候具有低内存和低CPU 要求. ·高

浅谈Flink批处理优化器之Join优化

跟传统的关系型数据库类似,Flink提供了优化器"hint"(提示)以告诉优化器选择一些执行策略.目前优化提示主要针对批处理中的连接(join).在批处理中共有三个跟连接有关的转换函数: join:默认为等值连接(Equi-join),维基百科将其归类为内连接(inner join)的一种 https://en.wikipedia.org/wiki/Join_(SQL): outerJoin:外连接,具体细分为left-outer join.right-outer join.full-

菜鸟学习 - Unity中的热更新 - Lua和C#通信

孙广东 2015-4-6 热更新我是个菜鸟,感谢网上的各位的奉献,这次又当一回搬运工. 准备: 1.了解Lua的语法 推荐书籍<Lua程序设计 第二版> 2.使用ULua插件进行通信 尽量早上真机.因为Bug问题特别多. 大杂烩: 更新LUa其实也是更新资源. Lua被看作一个资源么.Lua代码都是运行时才编译的,不运行的时候就如同一张图片.一段音频一样,都是文件资源:所以更新逻辑只需要更新脚本,不需要再编译,因而Lua能轻松实现"热更新".运行效率由于使用反射,所以成为它