BlueRoseNote/03-UnrealEngine/性能优化/UE5优化方法与实践笔记.md

210 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: UE5优化方法与实践笔记
date: 2022-09-26 10:06:37
excerpt:
tags:
rating: ⭐⭐
---
## 前言
视频推荐https://www.youtube.com/watch?v=ZRaeiVAM4LI
其他https://zhuanlan.zhihu.com/p/629225258
GPU Visualizer工具显示命令 **ProfileGPU**
### Sample Workflow
1. Run `Stat unit`
- shows the render thread is taking 50 ms.
2. Then run `stat scenerendering`
- shows that 25 ms is in the RenderViewFamily
- leaving us with 25 ms that the render commands are taking up
3. Finally, run `stat sceneupdate`
- we see that there is 25 ms in AddLight RT
- we see that it is being called 10 times a frame
4. We then need to go look at who is calling AddLight via a break point. And see why adding a specific light or lights is so slow. Usually it is the case that a specific light being added in a way that is doing more work than actually needs to be done. (e.g. attaching / reattaching it)
## 优化笔记
r.Lumen.DiffuseIndirect.MeshSDF.RadiusThreshold
让物体包围球的半径大于上述两个决定的数值的时候才参与mesh sdf的软追踪。
某些情况下,创建移除 WPO/PDO 的材质 LOD 可能不切实际,但这些转换的最终效果在远处很小。用于`r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange`设置一个距离(以厘米为单位),超过该距离将忽略这些材质的缓存失效。
为了在这些情况下更好地优化,可以使用启用可选的**单独静态缓存**`r.Shadow.Virtual.Cache.StaticSeparate 1`模式。此模式将物理页面池的大小加倍,以便可以将给定页面中的静态几何与动态几何分开缓存。即使动态几何移动了,也不需要重新绘制静态几何。
### Nanite
r.Nanite.AllowWPODistanceDisable
### 非纳米变形和树叶
可以使用骨骼动画变形的几何体,或使用世界位置偏移或像素深度偏移的材质总是使缓存页面每帧无效。根据定义,这些案例也必须是非 Nanite——这更昂贵——因此确保谨慎使用这些功能并控制边界是极其重要的。
在某些情况下,例如草地,有时是树叶,仅使用[接触阴影](https://docs.unrealengine.com/5.0/en-US/contact-shadows-in-unreal-engine)就足以替代高分辨率阴影贴图。在前景中需要高细节阴影的情况下,请考虑以下内容以帮助降低性能成本:
- 非 Nanite 对象仍然遵守常规阴影 CPU 剔除设置,例如`r.Shadow.RadiusThreshold`. 使用这些来帮助控制将这些对象渲染到虚拟阴影贴图中的成本。
- 在有很多树叶的场景中,强烈建议使用 禁用粗糙页面中的非 Nanite 对象`r.Shadow.Virtual.NonNanite.IncludeInCoarsePages 0`。或者,考虑在不需要时 [完全禁用粗糙页面。](https://docs.unrealengine.com/5.0/en-US/virtual-shadow-maps-in-unreal-engine#coarsepages)
- 在效果不再明显的距离使用网格 LOD 切换到不使用 WPO/PDO 的材料。在某些情况下,可以关闭远处这些对象的动态阴影投射,并完全依赖屏幕空间接触阴影。
对于平行光,还有其他可用选项:
- 距离场阴影接管非 Nanite 几何体,超出由光的级联阴影贴图部分设置的**动态阴影距离可移动光距离。**为远处的非 Nanite 切换到距离场阴影可以显着提高性能,因为该几何体不具有 Nanite 提供的细粒度 LOD 缩放。
- 在某些情况下,创建移除 WPO/PDO 的材质 LOD 可能不切实际,但这些转换的最终效果在远处很小。用于`r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange`设置一个距离(以厘米为单位),超过该距离将忽略这些材质的缓存失效。
如果运动很明显,这可能会导致阴影“模糊”,并且对象会错误地自我形成阴影,但通常这些伪影是性能和便利性的合理折衷。
### 普通植被
普通植被最快最有效的优化方式是做好LOD减少culling distance.除此之外,还有两个因素对性能也有一定的影响。
- foliage actor的范围
foliage actor的默认tile的大小是256如果一个tile下有大量的植被而且植被密度非常浓密的时候这里不仅会引起分区流送引起cluster tree构建的卡顿也会导致gpu下prepass和basspass消耗过高因为默认的剔除盒子太大导致prepass和basspass存在大量的vs的overdraw.
- cluster tree遮挡剔除盒子大小
cluste tree的剔除盒大小决定了这一块instance是否绘制过大的盒子会引起prepass和basspass的vs阶段的overdraw过小的盒子导致存在大量的遮挡剔除查询导致render线程耗时过高而且也会产生过多的drawcall。引擎对于cluster tree的控制参数都是全局的有一些component适用也一些则不合适。过密的component须要提高盒子的粒度过于稀疏而且面数不高的可以减少盒子数。因为如果植被特别影响性能的时候可以修改引擎支持让这些参数跟着component走。引起cluster tree盒子的因素有点多这里主要聊三个。
foliage.MaxOcclusionQueriesPerComponent
控制每个component的最多盒子数
foliage.MinOcclusionQueriesPerComponent
控制每个component的最少盒子数
foliage.MinInstancesPerOcclusionQuery
控制每个盒子最小包含的实例数
如果这个盒子粒度控制好在植被比较多的情况下可以在prepass和basspass省下2MS的预算。
### 贴图优化
具体参看Managing the Texture Streaming Poolhttps://www.youtube.com/watch?v=uk3W8Zhahdg
大致步骤:
- 使用Tools - Audit - Statistics查看贴图占用显存以及场景中的使用数量。
- 通过ViewMode - OptimizationViewModes - RequiredTextureResolution 查看贴图在场景中所需要的占用比例是否合适。
- 使用批量编辑功能修改Texture资产的MaximumTextureSize到指定Mipmap层级的分辨率即可。
另一个种方式就是使用SVT。
## 游戏的优化指标
目标性能30帧 约30ms
2000-3000是合理drawcall次数5000较高10000有问题
### 优化建议
1. 远景或者不太容易见到的灯光不产生阴影
2. Spotlight不要超大开角可以降低阴影分辨率衰减半径不要设置过大只需照亮需要照亮的主题即可如果不投射阴影可以改成点光源。
3. 灯光需要减少级联阴影的使用量,在远景处尽可能得使用距离场阴影
1. 方向光降低DynamicShadowDistanceMoveableLightNum Dynamic Shadow Cascades的值。适当调整DistanceFieldShadowDistance与DistanceFieldTraceDistance。
2. 其他光:降低**Max Draw Distance**,减少渲染范围;控制**Attenuation Radius**、**Cone Angle**减少叠加。具体可以使用**ViewModel - Optimization ViewModes - Light Complexity**来进行检查。
3. 其他光降低ShadowResolutionScale并且调整亮度让玩家看不出阴影质量较低。
4. 对于**非Nanite物体**的阴影,可以使用**r.Shadow.RadiusThreshold**来减少投射阴影的物体数量。
5. VSM
1. 局部光16k8级Mipmap
2. 方向光16k 17级Clipmap
3. 纹理池上限:`r.Shadow.Virtual.MaxPhysicalPages (4096)`
4. Lod精度偏移
1. `r.Shadow.Virtual.ResolutionBiasDirectional`
2. `r.Shadow.Virtual.ResolutionBiasLocal`
5. 减少SMRT的采样次数来提高软阴影的性能。
4. Lumen
1. 距离场的设置![[Lumen_StaticMeshDistanceFieldSettings.png|1000]]
5. Nanite
1. UE5.1针对树等植被采用了直接的建模式树叶而非之前的Mased+卡片的方式实现此时再配合StaticMesh中NaniteSettings的**Preserve Area**。拉远了树木上的树叶就不会消失了。
1. <iframe height=450 width=800 src="https://cdn2.unrealengine.com/p-area-off-opt-0c8757e8275f.mp4" frameborder=0 allowfullscreen> </iframe>
2. <iframe height=450 width=800 src="https://cdn2.unrealengine.com/p-area-on-opt-1s-89bb46d92142.mp4" frameborder=0 allowfullscreen> </iframe>
2. UE5.1支持了WorldPositionOffset但这个效果在远距离下并不明显需要根据距离优化掉。可以通过**View Mode - Optimization View Mode - Evaluate World Position Offset**来查看。
6. 控制RayTracing渲染功能的距离与范围
1. 按角度与距离剔除
1. r.Raytracing.Culling 1
2. r.Raytracing.Culling.Radius 10000 100米
3. r.Raytracing.Culling.Radius 1 5度
2. 设置光追组
1. StaticMeshComponent - RayTracing - Advanced - Raytracing Group Id /Culling Priority
7. 针对粒子特效可以调节Cut Off的裁剪系数Spawn TimeSpawn Rate等等可以在保证效果的同时来降低粒子数量的参数
1. https://www.youtube.com/watch?v=_T-BTiMF7XA
2. https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/Niagara/EmitterReference/RenderModules/
8. 尽可能使用贴花
9. 模型优化
1. 给模型生成LOD以及HLOD
1. Level Of Detail Coloration->Mesh LODs(可以**用红绿蓝三种颜色来**检验不同屏幕尺寸的LOD变化
2. 对于远处会闪烁的模型需要关闭LOD的`自动计算LOD距离`并且手动制作LOD。
2. 模型转换为Nanite后可以使用Nanite Tools来检查Nanite转换是否正确
3. 如果是**大量OverDraw Nanite模型**,可以使用**UE内置建模工具**的**Merge功能**将模型进行合并。
10. 使用剔除功能减少渲染的图元数
1. 使用`Stat InitViews`检查当前渲染图元数,以及之后优化完之后的图元数。**View Visibility**、**Occlusion Cull**为剔除消耗,**Processed**、**Frustum Culled**、**Occluded**剔除前后图元变化。
2. 给模型的LOD选项中设置**MinDrawDistance、DesiredmaxDrawDistance、CurrentMaxDrawDistance让模型在较远处被剔除**,适合一些细小的装饰类模型。
3. 使用剔除用Volumn。
11. 材质、蓝图等等,如果可以创建实例就使用实例
12. 综合优化视频
1. Adjusting Your Content to Perform on Target Hardware https://www.youtube.com/watch?v=Ln8PCZfO18Y
13. 贴图优化
1. 调整贴图的LOD Bias
2. 使用rdTexTools 插件优化贴图
14. 使用MergeActor工具将模型转化成Instance或者将细碎的模型组合成一个模型。
15. 调整材质减少材质复杂度以及使用的材质指令量。EPIC给出的建议300左右正常、**500+优化**、**1000+尽量减少**。
16. HLOD 估计适合组合拼装的房子 https://www.youtube.com/watch?v=WhcxGbKWdbI
1. 知乎介绍文章https://zhuanlan.zhihu.com/p/77509062
2. HLOD需要在世界设置中的LODSystem中打开。
17. 场景模型剔除 推荐视频https://www.youtube.com/watch?v=6WtE3CoFMXU
1. Show-Visualize-Advanced-CameraFrustums可以查看摄像机范围外的物体与遮挡物体。
2. Volumn
1. CullDistanceVolumn 根据对象距摄像机的距离及其尺寸对对象进行剔除即不绘制到屏幕上。当对象小到可被视为不重要时即可不绘制对象从而优化场景。尺寸是按照边界框的最长边计算的而剔除距离是根据与该尺寸最接近的距离计算的。
2. HierarchicalLODVolumn
3. MeshMergeCullingVolumn与HLOD有关
4. PrecomputedVisibilityVolumn这类体积会保存Actor的可视性以了解它们在场景中的位置。应仅将这些体积放置在玩家可以到达的区域。视频是把玩家可以到的地方直接放满了
3. Debug方法
1. FreezeRenderingFoliage.Freeze、FX.FreezeGPUSimulation、FX.FreezeParticleSimulation
2. r.VisualizeOccludedPrimitives1
3. ToggleDebugCamera
18. UE5 OpenWorld WorldComposition Datalayer 里面有附带大世界的HLOD 以及Nanite生成方法以及对应的CommanLethttps://www.youtube.com/watch?v=ZxJ5DG8Ytog
![[UE5 MergeActor使用笔记]]
### DLSS与动态分辨率
DLSS 在5.03上没有效果动态分辨率不支持PC。
https://docs.unrealengine.com/5.0/en-US/dynamic-resolution-in-unreal-engine/
### 蓝图的方法
![900](https://docs.unrealengine.com/5.0/Images/designing-visuals-rendering-and-graphics/rendering-optimization/dynamic-resolution/DynamicResBlueprint.webp)
### c++的方法
```
GEngine->GetDynamicResolutionStatus()->SetEnabled(true);
```
将 _SetEnabled_ 设置为 **false** 可将其禁用。
>在实际启用或禁用动态分辨率时,游戏线程逻辑掌握最终程序控制权限,所以如果你是用蓝图在运行时启动它,这会优先于代码设置。要将游戏用户设置恢复到初始状态,请使用以下命令行:
```
GEngine->GameUserSettings->ApplyNonResolutionSettings();
```
### 命令行
你可以使用 **运算模式Operation Mode** 设置如何在游戏中覆盖和使用动态分辨率设置在游戏中覆盖它和使用它的方式。为了控制这种模式在项目所对应平台Xbox One、PlayStation 4等的平台配置描述或设备描述你可以使用下列控制台命令
```
r.DynamicRes.OperationMode
```
使用下列数值之一来设置运算模式如何针对项目的平台工作:
- **1** 是根据游戏用户设置状态在C++或蓝图中设置)启用动态分辨率。
- **2** 是无论游戏用户设置状态如何都启用动态分辨率。
启用动态分辨率后,下列控制台变量会设置屏幕百分比的最大值和最小值,以及在降低分辨率之前任何给定帧的最大预算。如果你不设置,这些变量都有默认值:
| 控制台变量 | 默认值 | 描述 |
| -------------------------------- | ------ | ------------------------------------------ |
| r.DynamicRes.MinScreenPercentage | 50 | 设置要使用的最小屏幕百分比。 |
| r.DynamicRes.MaxScreenPercentage | 100 | 设置用于分配渲染目标的最大主要屏幕百分比。 |
| r.DynamicRes.FrameTimeBudget | 33.3 | 设置帧预算(以毫秒为单位)。 |
你可以使用Unreal Engine中的"设备描述Device Profiles"窗口设置和管理配置文件。可以通过"文件File"菜单选择 **编辑Edit> Developer Tools开发者工具> Device Profiles设备描述** 来访问此窗口。
### 暂停和恢复动态分辨率
有时你可能需要为项目启用动态分辨率,但你又不想对主大厅之类的区域启用。动态分辨率可以随运作模式暂停和恢复。下列控制台变量可用于设置动态分辨率的运算模式:
```
r.DynamicRes.OperationMode
```
| 数值 | 描述 |
| ---- | ------------------------------------------ |
| 0 | 禁用(默认) |
| 1 | 根据GameUserSettings中使用的设置启用。 |
| 2 | 无论GameUserSettings中的设置如何都会启用。 |
## DLSS 与 FSR
UE5使用DLSS时需要关闭TAA并且调整[[ScreenPercentage与描边宽度问题解决]]
### DLSS
- 下载地址https://developer.nvidia.com/rtx/dlss/get-started#ue-version
### FSR
- 使用方法与参数详解https://zhuanlan.zhihu.com/p/437537928
- 下载地址https://gpuopen.com/learn/ue-fsr2/