您需要 登录 才可以下载或查看,没有账号?注册
x
本期内容:了解什么会导致游戏中出现性能问题 概述可以帮助您发现瓶颈的内置工具 分享一些你应该从哪里开始寻找问题的提示
为什么要控制性能? 内心的平静 它在目标硬件上运行得越好,可以添加到游戏中的内容就越多 易于开发 访问其他平台
应认识到
***避免认为优化是项目中的,后期或最后一步 从一开始到结束,你都必须思考很多优化问题。这不是你可以委托给其他人,给程序员或技术艺术家或类似的人的事情。这应该是整个团队的责任,应该是任何人的责任。它向游戏添加内容,无论内容是什么进入引擎的人必须对此负责 ***认为引擎可以为您优化 这也是一个常见的错误,不光是独立开发者有时候3A开发者也会觉得,引擎能主动为你做优化,没错有时候是这样,但引擎为你做优化的情况非常罕见。但大多数情况下你至少需要知道你有什么问题,这样你才会能够在引擎中设置正确的功能以获得最佳性能,所以别再把所有的Actor、建筑、植被都扔进一个地图里。然后指望着引擎优化你的开放世界游戏。这不管用正如我之前所说的好的优化要从项目的开头开始你做的越早越好。要立即且频繁地做性能分析这是团队中每个人的责任,要避免“两耳不闻窗外事”只要你需要处理游戏中的特定资源就要做好相关的优化工作至少在Epic内部大家是这么做的
我们继续开始正篇
当你开始分析你的游戏时,你会寻找问题所在是什么东西拖累了性能表现呢?你应该问的第一个问题是,我是被GPU还是CPU拖累了?,所以这是这是显卡的问题吗?还是CPU的问题?
识别瓶颈 使用 stat unit,而不仅仅是stat fps stat unit硬件渲染某一帧所需的实际时间也就是那些绿色的数字 最大的数字表示可能的瓶颈 每帧毫秒数: 帧Frame:完成每帧的总时间 游戏Game:C++或BP游戏操作 绘制Draw:CPU渲染时间。 GPU:GPU渲染时间 您还可以使用stat unit Graph,它显示线图播放,主要用于发现重复的故障 这张图中有趣的一点是“帧”的时间并不是其它数字的总和,原因就是这些线程它们都是不同的线程是并行运行的每个线程都是按顺序的,它们需要上一个线程的内容和结果
我们简单介绍这些线程之前我要和你们分享一些知识 游戏的运行环境越接近目标硬件和目标平台,你获得的数据就越准确。如果可能,请避免在编辑器中分析游戏 如果你在主机或移动平台上做开发我得说你更加要避免这么做。因为你不是在实际的运行平台上做调试,虚幻引擎—PC和主机它们在渲染方面非常类似但移动平台它采用正向渲染路径,所以情况完全不同一定要使用合适的打包版本并且在目标硬件上运行,如果你在开发PC游戏并且必须在编辑器里做性能分析那记得 在独立模式下运行 最小化编辑器 确保关闭帧速率、平滑(项目设置) 并用控制台命令r.VSync=0关闭垂直同步
回到这些线程的话题,当游戏按图中的流程执行时 01-“Game”线程会计算所有的游戏逻辑,“Game”线程计算的所有数据都会被储存起来 02-并被“Draw”线程使用它会算出所有不需要渲染的内容这些内容不会显示在屏幕上 03-在这一步完成后“GPU”线程会在屏幕上实际渲染出最终的像素 如果这些线程 这些数据如果它们计算每个线程的这些帧都需要耗费时间,那下一个步骤当然就要等待上一个步骤来完成工作,这样它才能开始工作
那么这些线程具体都是负责什么工作呢? “CPU”线程 “Game”线程正如名字所示负责整个游戏的模拟,所有的东西从游戏逻辑所有Actor的位置,场景中所有物体的位置、动画、实际动画帧、物理效果、AI、一切与场景最终效果有关的计算与场景在某一帧中最终状况有关的计算,在进行处理时都会在“Game”线程中计算明白吗?这步完成后整个游戏世界就被计算完毕了引擎就会知道什么东西该干什么
在下一步 “Dram绘制”线程它会过滤掉、它会剔除掉、所有不在摄像机范围内的却还需要引擎去渲染的对象。(我们之后再深入谈论这个话题)但基本上来说所有不在摄像机范围内的东西都会被我们过滤掉
然后我们创建一个列表包含所有的对象、着色器、材质纹理所有需要发送给GPU的数据然后GPU会处理这些数据包括顶点、着色器、纹理等各种数据。然后在屏幕上绘制最终的像素
有一些工具可以供你们使用:有两条命令 在一段时间内生成图表
【此图表是在 Android 设备上生成的(流媒体)来自过场动画】 获取统计单位非常有用 一段较长时间内的时间 StartFPSChart 和 stopFPSChart(它主要会获取stat unit的输出结果) 生成一个 csv 文件,你可以用自己常用的表格编辑器打开它然后创建一个图表这非常有用可以帮助你找到游戏过场动画中出现卡顿的原因 可以执行一些自动化任务(例如让摄像机扫拍整个关卡然后记录所有数据 并导出到CSV文件中你可以每周或者每晚定期做一次,检查是否有潜在问题或导致性能不稳定的各种问题)后面我们有一期讲解这种方式使用
CPU Profiler也非常有用 你可以利用stat Startfile和stat Stopfile,记录引擎的所有操作引擎侦测到的每条命令,甚至是Dram调用的情况这适用于任何开发版本或测试版本
让我们来谈谈“Game游戏”线程 计算所有游戏逻辑和变换 动画 对象位置 角色移动 物理学 生成 AI
通常 “游戏”线程中的性能问题元凶 都是“Tick”函数中的复杂逻辑,众所周知 “Tick”每一帧都要执行,它实际上就是计算引擎中所有东西状态的函数、但事实是蓝图至少是Gameplay蓝图它们很少需要每帧更新 因为大部分游戏脚本都是基于事件的,或者不一定需要每帧都更新,当然也有例外情况但大部分情况下你不需要那么做。要记住如果你的场景和世界中有许多Actor在“Tick”函数那就会严重拖累游戏的流畅度 默认情况下,每帧计算一次刻度 事实是,默认情况下,蓝图很少需要勾选 太多的参与者会大大减缓项目的进度,因此识别这些因素很重要
你可以用一些命令 stat game:很好用它能查阅游戏逻辑在特定情况下的每帧更新耗时 dumpticks:命令它能列出正在更新的所有Actor以及它们的总数
请注意我的意思不是让你完全不去用Tick,不,我不是这个意思假如你一定要在Tick中实现游戏逻辑,我们只想告诉你一件事那就是在tick函数中添加复杂逻辑之前,要谨慎评估请思考是否真的需要这么做去每帧更新逻辑,有很多替代办法,我刚才说过你可以采用基于事件的方法,因为有些游戏逻辑未必会像你假设的那样频繁更新,或者如果真的需要以固定频率更新,你可以使用计时器甚至降低蓝图Tick函数的调用频率。你可以使用计时器比如也许可以每半帧四分之一甚至十分之一帧更新一次应该是秒不是帧 其中哪些可以由事件或计时器驱动? 勾选的替代方案: 时间表 计时器 禁用那些距离玩家太远的Actor 减少滴答声间隔 事件驱动系统(使用调度程序!)
另外有一些内容例如视觉效果,每帧都更新它们会让我们更舒服这通常要用到Timeline或者tick函数这个函数,在每次更新时会更新材质参数从而实现某些像素着色效果
在游戏开发中我们还会遇到大量的包含简单循环移动逻辑的对象,所以如果是某些和游戏玩法关系不大的逻辑,例如一些和关卡美化有关的逻辑一些让场景更好看的逻辑,你或许就可以考虑把它们改用顶点着色器实现。甚至用原生代码来赋予它们旋转动画效果 C++的“RotatingMovementComponent”就是个很好的方法它用于让对象自旋。但假如你还想进一步榨取性能你就可以用顶点着色器,实现它使用RotateWorldAboutAxis材质函数来实现旋转在Epic内部我们经常这么做
说到性能开销很大的函数一般来说,我不是让你不去用这些函数,如果需要你当然可以用它们但尽量避免使用那些,本来就开销巨大的函数假如你真的要使用这些函数一定要多加谨慎 ***Get All Actors of Class就很能说明这点,如果你是刚接触虚幻引擎你可能会应该说 大家往往都会滥用Get All Actors of Class,如果你真的要调用这个函数请在基于事件的逻辑中调用它比如在游戏启动时调用它或者编写某种基于事件的逻辑在只有需要访问数据的时候才调用这个函数然后把数据全都缓存到数组中所以请记住这些好习惯 ***此外 如果你需要用到For循环尤其是在涉及多重循环时记得要及时中断循环这样等你找到需要的对象后就不用运行其余的循环了生成在最新版的引擎中 ***我们实际上已经完善了许多,但是在生成Actor时还是会占用很多资源,因为这同样需要占用当前平台的IO接口。所以如果你在游戏中需要频繁生成Actor你就要多加小心了,你可以考虑把场景中的Actor保存在缓存池中,还有你要注意构造脚本会增加每个Actor的生成耗时我之前说过。我们的目的并非阻止你在Tick函数中实现复杂的逻辑,如果你真的要在Tick函数中实现复杂算法的和运算,请考虑使用原生代码或者说C++ 明白吗?
当然在制作虚幻引擎游戏时将复杂功能迁移到C++中是个不错的主意,虚幻引擎提供了混合的编程方式你可以混合使用蓝图和C++。你不需要把所有东西都迁移到C++可能只需要把有复杂代码的那部分移过去,因为它们需要做各种复杂计算只把那部分移到C++然后把它作为函数公开给蓝图然后就可以了
动画部分 我不打算围绕动画谈论太多,但总的来说动画在引擎的最近几个版本动画蓝图在性能表现上有了许多提升。如果你制作的3D游戏会用到动画蓝图,记得要使用Fast Path基本上 动画蓝图中的这种闪电图标越多就越好
“Draw”线程:接下来“绘制”线程是干什么的呢? 我说过 “Draw”线程会获取游戏世界的计算结果也就是“Game”线程的计算结果这个结果,包含了整个游戏世界的逻辑计算结果“Draw”线程会过滤掉所有不需要渲染的内容其中会用到多种技巧,比如“视锥剔除” 根据平台不同我们还能使用硬件遮挡查询,这在移动平台上行不通一般来说场景中的对象越多你的问题就越多,所以要谨慎控制对象的数量 这在开放式或大型场景中尤为重要,总的来说你应该知道如今的硬件极限是渲染10000到15000个对象,接着在引擎获知要渲染哪些对象后,它就会创建一个命令列表并发送给GPU让它去渲染这些命令会渲染场景的这一部分 视锥体剔除检查相机前面的内容,而硬件遮挡查询基于场景深度缓冲区 物体过多(10-15k+)可能会影响性能 对于具有开放/更大环境的游戏至关重要
一个接一个的绘制调用那什么是绘制调用呢? 我喜欢用不同的方式来解释绘制调用的意思,我经常会用画布来比喻绘制调用设想一下你有左边这个场景。它主要由天空构成地板浅灰色的有三个圆柱体三种不同的对象三种不同的Actor三个圆柱体采用相同的材质 GPU是如何绘制这些的呢?GPU默认的绘制方式大概是这样的: 例如我先从天空开始绘制想象一个白色的画布,然后想象一盒笔刷每个笔刷代表一种颜色我需要绘制蓝色的天空,我就找到盒子拿出蓝色笔刷回到画布上把它画出来。很好现在我要绘制地板浅灰色的找到盒子把笔刷,把蓝色笔刷放下拿起浅灰色笔刷回到画布画出地板,现在开始绘制柱子圆柱体,同样的找到笔刷拿起黑灰色笔刷回到画布。 然后我来绘制第一个圆柱体,圆柱体第三个绘制调用在这里你可能会想“好吧!既然有了浅灰色黑灰色笔刷应该就能绘制其它圆柱体了”然而并不事情不是这样的,实际情况是我通常必须如果这些是分开的物体,我必须回到我的画笔放下我的灰色画笔,再拿起同样的笔刷回到画布执行第四个绘制调用,这是按顺序执行的事实是每个绘制调用都有固定的开销绘制调用越多你来回绘制所耗费的时间就会呈线性增加情况会越来越糟糕 即使你只有一个模型例如右边的情况只有一个模型,但有两种材质有两种着色器虽然是同一个模型但有两种着色器,我仍然必须来回拿放笔刷你应该能理解了
总体上就像我说的这样绘制调用会对性能造成极大影响,这方面要小心在来回调用时每当渲染器需要发送命令或者你增加了开销,它实际上的影响有时比多边形数量的影响还要严重。要想知道场景的绘制调用情况一个好的入手点就是使用stat scenerendering 绘制线程 绘制调用 绘制调用对性能有很大影响。 每次渲染器完成后,它都需要从渲染线程接收命令,这会增加开销。 在许多情况下,Draw调用的影响要比polycount大得多
还有一个很好的工具你可以用RenderDoc(后面单独出一期如何使用)来调试绘制调用,这里给你大概展示一下这里有数百万个三角形但只有3000次绘制调用你的帧率还可以例如33FPS;右边的场景有44000次绘制调用而场景中的多边形数量少得多,但基本上只能以4FPS运行,因为场景中的每个三角形都采用了不同的材质
我该如何避免绘制调用呢? 大体上为了减少绘制调用,我们目前唯一的方法就是使用更少、更大的模型把不同的模型,把不同的对象合并成一个模型。这是此类情况的常用解决办法,但问题是你不能做得太过分,因为这基本上会影响到游戏的方方面面。它可能会不利于对象剔除,所以假设你在制作一个开放世界游戏想象一下你有一栋建筑一栋巨大的建筑是一个完整的模型,即使你只是靠近大门口观察一下引擎也需要计算它所有需要渲染的多边形仅仅因为你只看到了它的一小部分。但事实上 这个模型很大它没法、引擎没法将模型拆分成多个部分因为这是一个完整的模型,这对光照贴图不利如果你使用了静态光照,你就需要更大的光照贴图以便显示细节效果。这对碰撞计算不利因为相比拆分成多个小型模型碰撞效果的精度会差一点,当然这对内存也不利你要加载更大的资源可能会导致卡顿 减少绘制调用 为了降低draw calls,最好使用更少的大型模型,而不是使用许多小型模型 然而,你不能做太大模型,因为它会对其他所有事情产生负面影响 •更糟糕的遮挡 •更糟糕的是光照贴图 •更糟碰的撞计算 •更糟糕的内存
我们会介绍一些引擎中的功能来帮你搞定它 首先要讲的是细节级别也就是大部分人知道的LOD,它们主要用来减少场景和模型的复杂度 以及模型的顶点复杂度。但LOD也可用于减少绘制调用在常见的流程中某个网格体上往往会有多种材质,通常我会用树来举例子,树的树干是一种材质叶子是一种材质。它们有不同的光照效果有了LOD你就能在模型不断远离视野的过程中选择呈现不同的材质,你不仅可以减少多边形,如果树离得很远我就没必要再使用靠近摄像机时使用的材质,我会让整棵树同时使用一种材质包括叶子和树干。这样能维持大略一致的外观而且有助于如果你的游戏有很多植被这有助于减少绘制调用数量 详细程度(LOD); •在给定条件下简化一个模型或一组模型 •本质上将一个模型换成另一个更简单的模型 •通常意味着模型在远处变得更低多边形 •也可用于在多材质网格和单一材质之间切换
模块性:当你构建关卡时 模块性是个好东西,它能让不同物体的混合变得更简单,从而打造出色的关卡它能节省很多时间但问题是它会增加绘制调用数量。因为你的关卡中要有很多对象,如果你采用模块化网格体的流程关卡中的一些部分,就可以被合并成一个网格体虚幻引擎有一个很棒的工具它能够合并网格体也能合并不同的Actor“合并Actor”工具很擅长干这个,它不仅能把所有网格体合并成一个资源还能合并指定材质的纹理图集。自动为你创建更简单的材质还能把所有纹理合并成一张图集变成一张纹理,然后你就能确保这里只有一次绘制调用。还要记得在你这么做的时候你要先启用“合并材质”选项才行 使用模块化来构建级别是一种常见的技术。它节省了工作时间和内存 然而,这增加了绘制调用 Draw 如果使用模块化网格工作流,您可以在以后根据需要合并网格
实例化渲染 总体上引擎在渲染方面,如果你的关卡有很多静态网格体它们都是一样的是同样的网格体 同样的材质那引擎就会执行自动实例化,并将它们作为同一批次发送给GPU但在某些情况下事情可能不是这样 为什么这么说呢?因为结果可能不符合你的预期,所以你需要手动设置它们我们在后台有一些特定的功能会用到实例化的网格体,例如“植被”工具每当你在虚幻引擎里绘制需要用到“植被”工具的对象时该工具就会为你自动实例化那些网格体还有“草地”工具,这有些不同但它终究也要用到实例化网格体。对,虚幻引擎为你提供了一些工具帮助你做到这些,但也允许你在必要时手动操作,从而在场景里设置一些实例化网格体Actor 你也可以进行实例化渲染 •自动将模型分组为单绘制调用 •4.21+在自动实例化相似网格方面做得很好,但它不是一个确定性解决方案 •在某些情况下,手动设置实例化网格是理想的
HLOD 它基本上会把关卡中的不同模型划分为多个群组以减少绘制调,用它的原理就和“合并Actor”差不多它实际上会用到那个功能,但重点是它会自动执行它是100%非破坏性的设想一下这个场景:你有这些椅子基本上我想让虚幻引擎做的是把它们分成两组椅子并放置在两片区域中,只要我按下“烘培HLOD”按钮虚幻引擎就会自动创建合并后的网格体用来代步所有的椅子,当我远离这个区域也就是关卡的这一部分它就会自动切换到HLOD切换成它刚创建的合并网格体最棒的是 它是100%非破坏性的,假如关卡师需要修改椅子只需找到椅子移动旋转缩放然后在点击构建就好了。然后虚幻引擎就会自动为你构建HLOD 绘制线程 减少绘制调用 分层详细级别(HLODs): •将模型分组,以减少RAW调用。 •组合材质和纹理(atlas) •使用组合静态网格自动替换多个模型。 •100%无损检测
我们继续来讲“GPU”线程 那么“GPU”线程 我们终于要在屏幕上绘制最终像素了要想找出这个阶段中的问题,一个简单的办法就是关掉各个功能特性:关掉静态网格体、关掉骨骼网格体、关掉粒子效果、ShowFlag命令对此非常有用,如果你开发的是PC项目也许你可以把这些操作都绑定上快捷键,然后把它们混合搭配试着找出可能导致GPU问题的原因,另外我有个建议给你不在这张幻灯片上,如果你设置帧缓冲区总之如果你把帧缓冲区设置为0这就能直截了当地显示可能存在的填充率问题
Gpu Profiling
有一个专门的命令叫做ProfileGPU,你不仅可以在编辑器里运行它还能在开发版本里运行ProfileGPU会生成一个文件,所有发送给GPU的命令它的时间戳都会显示在其中让你轻松检查特定帧的每一步渲染过程,它会按照时间顺序排列命令以及那一帧的耗时也许你就能找到场景中某个特定部分的问题原因,它也可以通过快捷键Ctrl+Shift+; 来打开,能帮你找出游戏中的后期处理反射或者体积雾是否会导致问题 ProfileGPU命令允许您快速识别各种过程的GPU (有时甚至是绘制调用) 数据基于GPU时间戳,通常非常准确 也可以通过快捷方式访问:Ctrl+Shift+;
这个额外的知识是我从Chris Murphy还有Marco Swatsner那里听来的他们是Epic的工程师 如果你使用这些命令使用ProfileGPU命令你就可以进行性能分析,现在它显示了平均每个材质的绘制调用数量,它目前仅在桌面上运行但它真的很棒 现在GPU配置文件显示了每种材料的成本 它只是桌面的,不总是精确的,但这是一个很好的早期测试
如果你需要了解每个材质的具体绘制开销的话 GPU上常见的问题是过度着色,我们都知道在屏幕上绘制像素时对于GPU要绘制的每一个像素屏幕上只能同时显示一个多边形中的一部分,我们还没开发出从中间切分像素的技术。可能永远都不会这么做但无论你的模型有多精细,如果它离玩家离摄像机很远的话它就只占屏幕的一小部分,但你仍然需要处理所有的顶点从而绘制出少数的像素或者说一堆你最终无法看到的细节,所以解决过度着色的通用方式就是使用LOD 我们已经提到过了 一个像素只能同时显示一个(或部分)多边形。 我们知道 1 个像素永远不会代表超过 1 个多边形。 从远处看到的 100k 多边形模型仍会处理 100k 多边形以显示几个像素。 使用 LOD 和剔除可以大大减少过度着色
对于美术师来说解决过渡着色的一大方法 是在检查创作内容时,使用所谓的“四边形过度绘制”模式,这个模式还能在很多其它平台上运行,它基本上会显示它基本上会显示所有,可以用LOD简化的区域以及需要用LOD大量优化的区域。它是一个渐变的形式从蓝到白越接近白色情况就越糟糕你就越要注意 showFlag.四边形绘制 所有像素均以4像素的四边形渲染。 四边形Overdraw视图模式用于说明GPU必须绘制每个四边形的次数 当场景中的顶点变得更密集时,它们的绘制也会增加
“着色器复杂度” 也很好用它能将你在屏幕上绘制的每个像素的着色器的复杂度以视觉化形式呈现出来,它还能视觉化呈现潜在的过度绘制问题,过度绘制不仅有可能在你处理屏幕上众多顶点时发生也有可能在你使用很多alpha通道时,在你需要处理alpha通道的各个图层时发生,引擎并不知道哪个在哪个的下面,所以我们会处理所有的表面才能绘制像素的最终色彩,所以着色器复杂度可以用来显示着色器的开销,你可以看到要尽量避免红色和白色斑块的出现因为它们会导致性能问题 ShowFlag、着色器复杂性 显示着色器的成本 允许可视化正在使用的阴影指令的数量 非常适合识别透支问题 避免出现较大的红色和白色斑点
这里说几个解决着色器复杂度问题的技巧 要计算的内容越多着色器越复杂它的函数也越多。所以要避免这样但是这么做的时候一定要谨慎程序化函数,例如噪点程序化噪点可能会开销很大。如果你在开发PC游戏并且你知道你面向的是高端平台那这没什么问题。如果你面向移动平台或低端主机,你可能就要改为使用烘培纹理以达到效果。 众所周知If语句的开销很大一个很重要的事情是Allen Dutch,你可能应该大量使用特性级别开关和开关参数,因为这能让你让你在想登陆的平台上实现最佳的着色器效果。但同时提供了备选方案让你的游戏能在移动平台或低端电脑上流畅运行,所以要善用这些功能而引擎会帮你做很多优化。因为到最后这个内容可能有点太技术性了,当你针对你面向的特定平台编译游戏时引擎只会使用与那个平台相关的路径和着色器代码从而运行它请记住这点! 注意: •太多的数学和纹理 •程序功能(噪声等) •lf判断语句 将灰度贴图压缩为单个纹理 使用功能级别开关和开关参数来关闭不需要的功能
有一个通用的原则 尽量将复杂运算用顶点着色器而非像素着色器实现,这在移动平台上挺重要的在移动平台上挺有用,因为移动平台你用的屏幕更小。所以很难看到所有的着色器效果细节,但这也对PC游戏很有用这取决于它所创建的效果种类,你不用修改模型和着色器的每一个像素。你可以通过顶点来进行所有的插值计算,这样可以省去很多算力“VertexInterpolator”节点很适用于这点。但有一些框架有一些工作流程例如你在做曲面细分或者你在使用位移,你仍然需要采用自定义UV流程基本上就是你要选择材质节点添加几个自定义UV。然后做很多运算那些UV的输出结果会采用纹理坐标将它指定给执行计算的UV,然后你就得到了结果能够继续做各种事情 考虑将复杂计算移动到基于顶点,而不是基于像素 VertexlInterpolator节点为顶点和像素工作之间的值插值提供了更好的控制 顶点插值器输出仅在像素着色器中可用,因此在进行细分和置换时,仍然需要自定义UV工作流
极少数引擎能为你自动优化的东西之一 使用粒子效果时一般来说粒子效果是网格体或带透明纹理的平面。这时可以让引擎自动裁切图像,让图像更贴近对应的alpha通道,图像这样过渡绘制的概率会更低或者说你至少能够减少那个特定粒子效果的过度绘制 所以记得利用这点这个道理也适用于草地平面哪怕引擎不会为你自动做到这点,这也是个值得效仿的好做法。如果你的游戏里有很多植被,例如草地你需要在游戏里模拟草地,那最好裁剪哪怕你要添加更多的多边形也没关系。只要记住你要裁剪草地的平面纹理让它更接近草地的实际形状。这样就能减少它的过度绘制,有时有些游戏甚至会完全不使用半透明材质纯粹是为了降低开销。 当然这取决于具体的游戏取决于你用的平台,但有时候对于一些平台最好进行一些删减。让草地和植被模型完全不用半透明材质只用普通的着色器就行了,在有些情况下你可以获得更好的性能表现 利用 Particle Cutout 属性。Feedit 纹理,它会自动裁切图像 可以切割草平面以几乎完全匹配草纹理 alpha 的轮廓 或者您可以尝试对低端平台完全不使用半透明
最后一部分 我想简单聊聊“光照复杂度”,光照会让游戏的GPU开销大幅增加“光照复杂度”视图模式非常适合用来发现问题,光照方面的性能问题最重要的是你能鉴别游戏中所有已知的静态、动态和固定光源。你可能已经知到了颜色越接近大红色场景的光照就越复杂,这样就便于美工和其他人发现问题 showFlag光复杂性 显示影响几何体的非静态灯光的数量 这对于跟踪照明成本非常有用 影响表面的光越多,遮蔽的成本就越高
关于光照复杂度通用的建议 ***显然要尽量减少动态光源的数量它们是实时渲染的,每帧都是GPU需要做大量处理和运算才能得出像素在光照影响下的最终色彩。所以要尽量减少动态光源的数量,如果要用或许你应该尽量缩小它的范围,这样它只会照亮对你比较重要的区域也就是关卡的某一部分。你还可以减少动态光源所影响的对象数量你可以让对象和光源使用光照分层功能。阴影投射的开销也很大所以如果你有动态光源但又不是真的需要投射阴影那就关掉它 ***再来谈谈固定光源,尽量避免固定光源的范围发生重叠。最多只能有三个重叠的固定光源,如果你再添加一个引擎就会显示一个红X标志它的大概意思就是它现在会变成动态光源它的开销会大很多 ***我们也可以尽早地剔除动态光源我们在《堡垒之夜》里经常这么干,我们在建筑里设置了一些动态光源。但玩家一旦远离它们或者到了建筑外部,我们基本上就会把它们都关掉。它们就不渲染了它们不会被计入渲染过程,没错总体上如果你用的静态光源越多性能表现就越好,当然静态和动态之间的取舍关系是,静态光源你使用越多就意味着你需要将光照贴图写入硬盘增加内存使用量所以这是一种取舍和平衡你需要把握好这种平衡 尽量减少动态灯光的数量 烘焙照明比动态和固定照明便宜得多 最小化动态光半径-越小越好 尽量减少动态灯光的效果从尽可能少的动态灯光投射阴影 动态阴影投射灯是最昂贵的 注意固定光重叠 尽早剔除动态灯光 尽早为资源剔除阴影 视频版/图文方便随时查阅与复习 视频来自 Unreal Indie Dev Days 2019:
https://www.youtube.com/watch?v=EbXakIuZPFo&t=457s 好!本期分享就到这里 后续,我们会更详细分享引擎中的各种功能对性能的影响如:灯光、模型、裁切方式、材质、贴图、反射、雾、后效等。在这期间我们还会复习一下有关计算机图形学知识笔记,性能与优化这一块的内容,如果能更多掌握一些图形学知识会对我们更有帮助。 记得关注!我们下期见! 公众号地址:https://mp.weixin.qq.com/s/NNWcW3yMMLlhrdynUdsuqA
!更多精彩+++关注联系我们
下期见,学习不止,不止学习
|