BlueRoseNote/03-UnrealEngine/Rendering/RenderFeature/VirualShadowMap优化笔记.md

179 lines
13 KiB
Markdown
Raw Permalink Normal View History

2023-06-29 11:55:02 +08:00
---
title: VirualShadowMap优化笔记
date: 2023-02-08 12:29:43
excerpt:
tags: VSM Nanite
rating: ⭐
---
# 前言
VirualShadowMap与Nanite关系很大如果场景中有很多非Nanite物体就需要将其都穿成Nanite之后可以用Nanite Tool或者VirualShadowMap Cache显示模型来检查场景具体可以参考[[Nanite学习笔记]]。具体优化步骤可以参考[[#优化案例]]。
# 相关命令某个A站作品使用的参数
## VT
- r.VT.MaxUploadsPerFrameInEditor 8
- r.VT.MaxUploadsPerFrame 8
- r.VT.MaxContinuousUpdatesPerFrameInEditor 2
- r.VT.MaxContinuousUpdatesPerFrame 2
- r.VT.MaxAnisotropy 8
## Lumen相关命令
- r.MeshDrawCommands.DynamicInstancing 0
- r .Shadow.Virtual.NonNanite.IncludeInCoarsePages 0
- r.Lumen.Reflections.DownsampleFactor 1.98
- r.Lumen.ScreenProbeGather.Temporal.DistanceThreshold 1.7
- r.RayTracing.NormalBias 5.0
- r.Lumen.ScreenProbeGather.MaxRayIntensity 10
- r.Lumen.ScreenProbeGather.ScreenTraces.HZBTraversal 0
- r.Lumen.Reflections.HierachicalScreenTraces.MaxIterations 4
## VirualShadowMap
- r.Shadow.RadiusThreshold 0.05
- r.ShadowVirtualClip .LastLevel 15
- r.Shadow.Virtual.ResolutionLodBiasDirectional -1.1
- r.Shadow.Virtual.Clipmap.UseConservativeCulling 0
- r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange 3500
- r.Shadow.Virtual.ForceOnlyVirtualShadowMaps 1
- r.Shadow.Virtual.0.CulingFarCulingFar
# 其他优化思路
其次local灯光的数量对VSM的性能有较大影响。一方面可以考虑减少不必要的局部光源数量此外可以尝试使用One Pass Projection功能实验性来提高性能。开启方法如下
- `r.UseClusteredDeferredShading 1`
- `r.Shadow.Virtual.OnePassProjection 1`
然后还可以通过调整下列CVar默认值16到更小的数字来强行限制每个像素受到影响的灯光数量来提高性能。
`r.Shadow.Virtual.OnePassProjection.MaxLightsPerPixel`
此外,还有一些实践思路供参考,例如:
减少屏幕上大面积像素受到多个大范围局部灯光的影响(**减少多个局部灯光重叠影响同一片大面积区域**
​减小局部灯光的**Source Radius**属性和方向光的**Source Angle**属性可以降低**VSM Ray的数量**
关闭数量庞大的**次要模型的投影**
​关闭**超远距离**的背景物体模型的**投影**等;
# VirualShadowMap使用笔记浓缩自官方文档
启用**VirualShadowMap**之后:
1. 无论距离如何,**Nanite几何体**始终使用**虚拟阴影贴图**渲染阴影,因为这是性能最高的选项,可提供最高质量。可以通过控制台变量 `r.Shadow.Virtual.UseFarShadowCulling 0` 使非Nanite几何体的行为方式与Nanite相同。
2. **静态烘焙阴影**将会失效。
3. **距离场阴影**主要作用于非Nanite物体比如大量植被超出**动态阴影距离可移动光源Dynamic Shadow Distance Movable Light** 距离的阴影渲染。
4. 局部光源(**点光源和聚光光源**)不受影响,依然会使用**距离场阴影**进行渲染。
5. **光线追踪阴影**的优先级仍然高于VSM
## 相关命令
- r.Shadow.Virtual.ResolutionLodBiasLocal调整分辨率。
- r.Shadow.Virtual.NonNanite.IncludeInCoarsePages 0 尝试禁止非Nanite对象渲染到CoarsePages。
- 可视化参数
- r.Shadow.Virtual.Visualize [mode] 在Virtual Shadow Map可视化模式下此命令指定要显示的通道。**Cache** 和 **vpage** 是用于可视化的两个常用选择,**none** 可禁用vsm可视化。
- mask
- Mip
- vpage
- cache
- raycount
- clipmapvirtual
- ShowFlag.VisualizeVirtualShadowMap指定可视化模式时启用虚拟阴影贴图可视化。
- r.Shadow.Virtual.Visualize.Layout选择虚拟阴影贴图可视化的布局。
- **0** 表示全屏
- **1** 表示缩略图
- **2** 表示分屏
- r.Shadow.Virtual.Visualize.DumpLightNames将带有虚拟阴影贴图的当前光源列表输出到控制台。
- r.Shadow.Virtual.Visualize.LightName [光源名称]:按名称指定光源,接受部分或全部匹配。
- r.Shadow.Virtual.Cache.DrawInvalidatingBounds 1显示缓存失效边界。
- r.Shadow.Virtual.Cache 0禁用缓存。
## 相关可视化
- View Modes-Virtual Shadow Map在大纲中选中光源可以查看对应光源的渲染信息。
- Show > Visualize > **仅绘制导致VSM失效的几何体Draw only Geometry Causing VSM Invalidation** 
- r.ShaderPrintEnable 1显示计数器
- r.Shadow.Virtual.ShowStats 1或2以仅显示页统计数据
## 非Nanite多边形渲染
可变形多边形SkeletalMesh、WorldPositionOffset、PixelDepthOffset都会使**VirtualShadowCache** 失效。
在某些情况下,例如草,有时是植被,仅使用[接触阴影](https://docs.unrealengine.com/5.1/zh-CN/contact-shadows-in-unreal-engine)足以替代高分辨率阴影贴图。如果前景中需要细节丰富的阴影,请考虑以下事项以帮助降低性能开销:
- 非Nanite对象仍然遵循常规的阴影CPU剔除设置例如 `r.Shadow.RadiusThreshold`。使用这些来帮助控制将这些对象渲染到虚拟阴影贴图的开销。
- 在有大量植被的场景中,强烈建议使用 `r.Shadow.Virtual.NonNanite.IncludeInCoarsePages 0` 禁用粗页中的非Nanite对象。或者如果不需要请考虑[完全禁用粗页](https://docs.unrealengine.com/5.1/zh-CN/virtual-shadow-maps-in-unreal-engine#%E7%B2%97%E9%A1%B5)。
- 使用网格体LOD在效果不再明显的距离处切换到不使用WPO/PDO的材质。在某些情况下可以为远处的这些对象**关闭动态阴影投射**,并完全依赖屏幕空间**接触阴影**。
对于定向光源,还有其他可用选项:
- 距离场阴影替代超出 **Dynamic Shadow Distance Movable Light** 距离范围的非Nanite几何体该距离通过光源的级联阴影贴图Cascaded Shadow Maps分段设置。为远处的非Nanite切换到**距离场阴影**可以大大提高性能因为此几何体没有Nanite提供的细粒度LOD缩放。
- 在某些情况下创建移除WPO/PDO的材质LOD可能不切实际但这些转换的最终效果在远处不明显。使用 `r.Shadow.Virtual.Cache.MaxMaterialPositionInvalidationRange` 设置距离(以厘米为单位),超过该距离时,将忽略这些材质的缓存失效。
# Shadow Map Ray Tracing(阴影贴图光线追踪)
一种渲染**软阴影**的方式。可通过以下命令来设置采样数值:
- `r.Shadow.Virtual.SMRT.RayCountLocal` :每个像素采样光线数量。
- `r.Shadow.Virtual.SMRT.RayCountDirectional`:每个像素采样光线数量。
- `r.Shadow.Virtual.SMRT.SamplesPerRayLocal`每个像素受到VSM的光线追踪影响的数量。
- `r.Shadow.Virtual.SMRT.SamplesPerRayDirectional`每个像素受到VSM的光线追踪影响的数量。
- `r.Shadow.Virtual.SMRT.MaxRayAngleFromLight`:通过降低半影的精度来优化性能。
- `r.Shadow.Virtual.SMRT.RayLengthScaleDirectional`:通过降低半影的精度来优化性能。
# ## GPU分析和优化
- **RenderVirtualShadowMaps(Nanite)** 包含所有与Nanite几何体渲染到VSM中相关的内容。所有定向光源都在单个Nanite通道中渲染所有局部光源都在第二个通道中渲染。
- **RenderVirtualShadowMaps非Nanite** 负责处理非Nanite几何体的渲染。每个可见光源都有一个单独的通道各种对象和实例拥有单独的绘制调用这点与传统阴影贴图渲染相同。
- **图集Atlas** 和 **立方体贴图Cubemap** 与其他类似通道包括VSM通道都只是渲染传统阴影贴图。在虚拟阴影贴图的路径中仍有少部分类型的几何体不受支持它们遵循传统路径。如果没有不受支持的几何体投射阴影这些通道将不会运行或分配阴影贴图存储。这些通道和相关的开销可以使用cvar `r.Shadow.Virtual.ForceOnlyVirtualShadowMaps 1` 完全禁用,在这种情况下,所有不受支持的几何体类型都完全不会投射阴影。
## 提升非Nanite性能
除了改进缓存之外还有许多方法可以提高非Nanite阴影渲染的性能。
- 在你的项目的几何体中**尽可能多**的部分上**启用Nanite**。
- Nanite几何体在虚拟阴影贴图中的渲染效率要高得多无论多边形数量如何都应该在每个适用的情况下作为首选。
- Nanite几何体可以遮挡非Nanite几何体并避免虚假缓存失效。因此唯一的非Nanite对象应该是Nanite本身不支持的对象例如变形对象蒙皮网格体或使用世界位置偏移WPO和像素深度偏移PDO的材质。
- **非Nanite对象**应具有**完整的网格体LOD层级设置**
- 非Nanite网格体具有LOD设置很重要否则渲染到小页的开销会非常高。
- 如果可以,建议在**距离太远**而使效果不明显时切换到**非变形网格体无WPO/PDO材质**。
- CPU剔除控制台变量对于渲染到虚拟阴影贴图的非Nanite网格体仍然有用
- 使用控制台变量 `r.Shadow.RadiusThreshold`调整渲染到虚拟阴影贴图中的非Nanite对象的CPU剔除值。这有助于控制远处小型对象的开销。
- 将[距离场阴影](https://docs.unrealengine.com/5.1/zh-CN/distance-field-soft-shadows-in-unreal-engine)用于非Nanite对象的远距离阴影投射。
- 对于定向光源在超出某个范围时通常需要切换到距离场阴影与级联阴影贴图相同。使用虚拟阴影贴图仅非Nanite几何体将切换到使用距离场阴影而Nanite几何体仍采用全细节阴影。
- 在粗页中禁用非Nanite几何体可以提高性能
- 在粗页中禁用非Nanite几何体通常可以实现大幅的性能提升因为非Nanite几何体在渲染到大页中时通常效率低下。
## 阴影投射
**阴影投射Shadow Projection** 类别是使用阴影贴图光线追踪对阴影贴图取样产生的开销。这些通道位于 **光源Lights | DirectLighting | UnbatchedLights** 之下通常每个相关光源都有一个VSM投射通道。产生最高开销的通道一般都是 **VirtualShadowMapProjection** 中的主SMRT循环。其余的开销应该相对较低。
# 其他
## 虚拟现实
虚拟阴影贴图尚未完全支持虚拟现实。右眼视角可能存在定向光源瑕疵。
## 分屏
分屏受到的测试极少,性能可能很差。
## 物理页池溢出
使用虚拟阴影贴图,场景中所有光源的所有阴影数据都存储在一个大型纹理池中。默认池大小受 **阴影Shadow** 可扩展性设置的影响,但在具有许多使用高分辨率阴影的光源的场景中,可能需要进行调整。
或者,可能需要在低端硬件上进行调整,以节省显存。
页池大小可以使用 `r.Shadow.Virtual.MaxPhysicalPages` 进行调整。连续使用 `r.ShaderPrintEnable 1` 和 `r.Shadow.Virtual.ShowStats 2` 启用虚拟阴影贴图统计数据,将显示有关当前页池使用情况的统计数据。
## 场景捕获
在一些情况下,场景捕获组件会导致整个虚拟阴影贴图缓存无效化。具体症状体现为 _Invalidations_ 在虚拟阴影贴图数据中变低但是缓存的页面也变低甚至会变为0缓存的页面会全部变成红色。
发生该情况试着隐藏或移除场景中的场景捕获Actor来验证它们是否在导致这个问题。
## 材质
**仅支持简单的次表面材质**。尚未实现次表面轮廓和传输。如果某个材质正在使用它们,则该材质将被遮蔽,就好像它不透明一样。
### 阴影分辨率
与传统阴影贴图相比,虚拟阴影贴图的分辨率显著提升,但浅光源角(或投影锯齿)和非常大的局部光源可能耗尽可用的虚拟分辨率。根据几何体的表面,这可能会呈现为盒状阴影和偏差问题。
定向光源裁剪图不太容易耗尽分辨率,但非常窄的摄像机视野最终也会耗尽这些分辨率。
阴影贴图的投影锯齿并没有简单的解决方案。即使使用虚拟阴影贴图,也必须注意避免最坏的情况,并平衡分辨率和性能。
# 优化案例
## 场景存在问题
1. 场景中的很躲静态物体没有启用Nanite使得VirualShadowMap性能变低。
2. 远景的天空球SM_Skybox_Mesh、雾气面片、近景3个人 投射阴影。
3. 植被问题。
![800](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/%E5%9B%BE%E7%89%871.png)
## 解决方法
1.让场景模型启用Nanite。
![800](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/%E5%9B%BE%E7%89%872.png)
可以通过ViewMode - VirualShadowMap - Cache模式来显示缓存失效情况,以此来找到非Nanaite物体。
![800](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/%E5%9B%BE%E7%89%873.png)
之后使用Show > Visualize > 仅绘制导致VSM失效的几何体Draw only Geometry Causing VSM Invalidation来精准查找未开启Nanite的物体。
![800](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/%E5%9B%BE%E7%89%874.png)
2. 关闭远景天空球SM_Skybox_Mesh、雾气面片与近景3个人模型的 Cast Shadow选项。尝试启用远景天空球的Nanite选项。
3. 植被分两种情况:有/无WorldPositionOffset。无的话直接转成Nanite即可。有的话建议去除 Cast Shadow选项并且勾选Contact Shadow。