13 KiB
title, date, excerpt, tags, rating
title | date | excerpt | tags | rating |
---|---|---|---|---|
VirualShadowMap优化笔记 | 2023-02-08 12:29:43 | VSM Nanite | ⭐ |
前言
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之后:
- 无论距离如何,Nanite几何体始终使用虚拟阴影贴图渲染阴影,因为这是性能最高的选项,可提供最高质量。可以通过控制台变量
r.Shadow.Virtual.UseFarShadowCulling 0
使非Nanite几何体的行为方式与Nanite相同。 - 静态烘焙阴影将会失效。
- 距离场阴影主要作用于非Nanite物体(比如大量植被)超出动态阴影距离可移动光源(Dynamic Shadow Distance Movable Light) 距离的阴影渲染。
- 局部光源(点光源和聚光光源)不受影响,依然会使用距离场阴影进行渲染。
- 光线追踪阴影的优先级仍然高于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.Visualize [mode] :在Virtual Shadow Map可视化模式下,此命令指定要显示的通道。Cache 和 vpage 是用于可视化的两个常用选择,none 可禁用vsm可视化。
- 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 失效。
在某些情况下,例如草,有时是植被,仅使用接触阴影足以替代高分辨率阴影贴图。如果前景中需要细节丰富的阴影,请考虑以下事项以帮助降低性能开销:
- 非Nanite对象仍然遵循常规的阴影CPU剔除设置,例如
r.Shadow.RadiusThreshold
。使用这些来帮助控制将这些对象渲染到虚拟阴影贴图的开销。 - 在有大量植被的场景中,强烈建议使用
r.Shadow.Virtual.NonNanite.IncludeInCoarsePages 0
禁用粗页中的非Nanite对象。或者,如果不需要,请考虑完全禁用粗页。 - 使用网格体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剔除值。这有助于控制远处小型对象的开销。
- 使用控制台变量
- 将距离场阴影用于非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. 植被问题。
解决方法
可以通过ViewMode - VirualShadowMap - Cache模式来显示缓存失效情况,,以此来找到非Nanaite物体。
之后使用Show > Visualize > 仅绘制导致VSM失效的几何体(Draw only Geometry Causing VSM Invalidation)来精准查找未开启Nanite的物体。
2. 关闭远景天空球(SM_Skybox_Mesh)、雾气面片与近景3个人模型的 Cast Shadow选项。尝试启用远景天空球的Nanite选项。 3. 植被分两种情况:有/无WorldPositionOffset。无的话直接转成Nanite即可。有的话建议去除 Cast Shadow选项,并且勾选Contact Shadow。