TSR 时域超分
自动关联目录:TSR 时域超分
官方依据:Temporal Super Resolution(UE 5.8 Documentation)。本页覆盖该页全部 36 个条目,并按本库标准重排为"原理 → 参数 → 代价 → 排查"。
1. 定位
TSR 是 UE 自研的平台无关时域超分器:以低于输出的分辨率渲染,把昂贵的计算分摊到多帧,用时间换画质。
一句话定位:TSR 是让 Nanite 的细节和 Lumen 的开销同时成立的关键——没有它,UE5 的画质与性能组合就撑不住。
官方给的实际收益:1080p 内部分辨率输出接近原生 4K 画质,GPU 帧时间减半。
2. 它是什么、在哪一环
| 特性 | 说明 |
|---|---|
| 平台无关 | D3D11 / D3D12 / Vulkan / Metal / PS5 / Xbox Series S|X,SM5 及以上 |
| 跨一致性 | 所有支持平台上的超分质量与行为严格一致;但对 PS5/XSX 的 AMD RDNA 做了专门优化(16-bit 类型与打包指令) |
| 相比 UE4 的 TAA | 更少的"鬼影"(对高频背景)、对 Nanite 高复杂度几何减少闪烁 |
| 动态分辨率 | 支持主机平台的 Dynamic Resolution |
在渲染链中的位置(很重要):
... → 景深(Depth of Field)→ 【TSR】→ 运动模糊 → Bloom → 色调映射 → ...TSR 发生在景深之后,之后的所有东西都是被放大过的。这直接导致"隐藏成本",见第 6 节。
3. 五个组成部分
| 组件 | 作用 | 默认启用的档位 |
|---|---|---|
| History | 在帧间累积、存储并复用细节 | 全部档位(必选) |
| Parallax Heuristics | 用运动向量重投影历史,并在遮挡解除处保持画质 | 全部档位(必选) |
| Shading Rejection | 判断当前帧与历史是否匹配、该复用还是拒绝;检测颜色变化与半透明 | 全部档位(必选) |
| Flickering Temporal Analysis | 稳定画面,减少摩尔纹等伪影 | High / Epic / Cinematic |
| History Resurrection | 当历史中更早的某帧更匹配时,"复活"它而不是只用上一帧 | Medium 及以上 |
外加两个可选增强:
| 增强 | 说明 | 档位 |
|---|---|---|
| Spatial Anti-Aliaser | 历史被拒绝时的空间抗锯齿(FXAA 风格) | Medium 及以上 |
| Reprojection Field | 每像素嵌入 2x2 Jacobian 矩阵,移动时保持锐利边缘 | High 及以上 |
4. 参数与控制台变量
抗锯齿可扩展性组
sg.AntiAliasingQuality:0=Low, 1=Medium, 2=High, 3=Epic, 4=Cinematic。
BaseScalability.ini 的 [AntiAliasingQuality@3](High)示例:
[AntiAliasingQuality@3]
r.FXAA.Quality=4
r.TemporalAA.Quality=2
r.TSR.History.R11G11B10=1
r.TSR.History.ScreenPercentage=200
r.TSR.History.UpdateQuality=3
r.TSR.ShadingRejection.Flickering=1
r.TSR.RejectionAntiAliasingQuality=2
r.TSR.Resurrection=1项目自己的 DefaultScalability.ini 可以覆写。低于 50% 的极端超分只在目标分辨率 >4K,或主机动态分辨率的极少数情况下才应考虑。
核心 CVar
| CVar | 默认 | 说明 |
|---|---|---|
r.TSR.History.ScreenPercentage | 200(Epic/Cinematic;其余 100) | 历史缓冲相对输出分辨率的倍数。只支持 100–200。200 = Nyquist-Shannon 历史,见下 |
r.TSR.History.SampleCount | 16 | 历史每个输出像素的最大采样数;8–32(受 metadata 编码限制)。高 → 静态高光更稳,但某些 VFX(如萤火虫)会更容易鬼影 |
r.TSR.History.UpdateQuality | 由 AA 组驱动 | 0=low…3=epic;细节见 TSRUpdateHistory.usf 的 DIM_UPDATE_QUALITY |
r.TSR.History.R11G11B10 | 1 | 历史用 11/11/10 位深度,省带宽。r.PostProcessing.PropagateAlpha=1 时不支持 |
r.TSR.Velocity.WeightClampingSampleCount | 4.0 | 移动时的稳定性 vs 清晰度。叙事类可保持 4.0;竞技类(如 Fortnite)降到 2.0 换锐利度 |
r.TSR.Velocity.WeightClampingPixelSpeed | — | 达到该像素速度时才开始 clamp |
r.TSR.RejectionAntiAliasingQuality | 除 Low 外都开 | 空间抗锯齿质量 |
r.TSR.Resurrection | Medium+ 开 | 历史复活 |
r.TSR.Resurrection.PersistentFrameCount | 2 | 必须是 ≥2 的偶数;增大会增大历史内存占用 |
r.TSR.Resurrection.PersistentFrameInterval | 31 | 必须是 ≥1 的奇数;不影响内存。用 r.TSR.Visualize 5 调 |
r.TSR.ReprojectionField | High+ 开 | 重投影场 |
r.TSR.ShadingRejection.Flickering | High+ 开 | 闪烁时域分析 |
r.TSR.ShadingRejection.Flickering.Period | 3 | 多少帧内亮度振荡算"闪烁" |
r.TSR.ShadingRejection.Flickering.FrameRateCap | 60 | 低于该帧率时自动放宽闪烁判定 |
r.TSR.ShadingRejection.Flickering.AdjustToFrameRate | 开 | 官方强烈不建议关 |
r.TSR.ShadingRejection.Flickering.MaxParallaxVelocity | — | 视差遮蔽映射(POM)假内部几何无法给出正确运动向量时的保护阈值 |
r.TSR.ShadingRejection.SampleCount | 2.0 | 完全拒绝后历史的最大采样数。低 → 更清晰但后续帧更不稳 |
r.TSR.ShadingRejection.ExposureOffset | — | 只调 TSR 拒绝启发式里的曝光 |
r.TSR.ShadingRejection.TileOverscan | — | 卷积 tile 重叠;高 → 少 tiling 伪影但更贵 |
r.TSR.AsyncCompute | 2 | 0 关 / 1 仅独立 pass / 2 依赖深度与速度缓冲的也可异步(默认) / 3 全部 |
r.TSR.16BitVALU 及 .AMD/.Intel/.Nvidia | — | 16-bit VALU 开关与按厂商覆写 |
r.TSR.WaveOps | — | 用 wave ops 加速卷积;SPIR-V 平台(Vulkan/Metal)目前禁用(DXC 编译时间问题) |
r.TSR.WaveSize | 0 自动 | 16/32/64 |
r.TSR.ForceSeparateTranslucency | 开 | 开 TSR 时覆写 r.SeparateTranslucency |
r.TSR.AlphaChannel | -1 | 是否处理 alpha(跟随 r.PostProcessing.PropagateAlpha) |
r.TSR.Visualize | — | 见第 8 节 |
运动模糊相关(都默认开启)
| CVar | 作用 |
|---|---|
r.MotionBlur.AllowExternalVelocityFlatten | TSR 接管原本在输入分辨率跑的 Velocity Flatten pass |
r.MotionBlur.HalfResInput | TSR 输出半分辨率场景色,缓解大方向性运动模糊核的带宽瓶颈 |
r.MotionBlur.HalfResGather | 设 1 让方向性模糊在很大运动时跑半分辨率 |
r.SecondaryScreenPercentage.GameViewport | 二级屏幕百分比 + 空间上采样器 |
r.Translucency.AutoBeforeDOF | 自动把焦点距离之后的半透明画到 Before DOF;0=1x 焦距,0.5=2x,1=100x |
5. 两个关键指标
TSR feed(MP/s)
TSR feed = 显示宽 × 显示高 × ScreenPercentage² × 帧率衡量"TSR 每秒要收敛多少数据",与显示分辨率无关地反映运动中的宏观画质。
| 显示分辨率 | Screen % | 帧率 | TSR feed |
|---|---|---|---|
| 4K | 50% | 60 | 124.4 MP/s |
| 4K | 58% | 60 | 167.4 MP/s |
| 4K | 66% | 60 | 216.7 MP/s |
| 4K | 50% | 30 | 62.2 MP/s |
| 4K | 72% | 30 | 124.4 MP/s |
| 1080p | 100% | 60 | 124.4 MP/s |
| 1080p | 72% | 60 | 62.2 MP/s |
| 1080p | 50% | 60 | 31.1 MP/s |
TSR 1spp(收敛时间)
TSR1spp = 1000 / (ScreenPercentage² × FrameRate) (毫秒)达到"每像素一个样本"所需的时间——运动中遮挡解除区域能不能快速补上细节,就看它。
| Screen % | 帧率 | 收敛 |
|---|---|---|
| 50% | 60 | 66.6 ms |
| 58% | 60 | 49.5 ms |
| 66% | 60 | 38.2 ms |
| 100% | 60 | 16.6 ms |
| 50% | 30 | 133.3 ms |
举例:Screen % = 50 时需要 (50/100)^-2 = 4 帧才有每像素一个样本;每帧 16.6ms → 遮挡解除区域要 66.4ms 才够。
重要推论:TSR 不只受 GPU 限制帧率影响,CPU 受限、以及非可变刷新率显示器上的 VSync,都会影响它。
查看方式:stat tsr(或 Viewport Options → Stat > Engine → 勾选 TSR)。
6. 代价与权衡
Nyquist-Shannon 历史:用 4 倍成本换锐度
历史重投影时,当前帧与上一帧的像素几乎不可能对齐,只能插值 → 引入模糊。1 像素厚的细节只移动半像素,这个细节就永久丢失了。
后果很具体:1080p 显示时,运动中的画面观感可能像 540p。
对策:Epic / Cinematic 档把 r.TSR.History.ScreenPercentage 设为 200——历史按两倍显示分辨率存储,用 Mitchell-Netravali 下采样核做重投影,符合 Nyquist-Shannon 采样定理。
代价很直白:历史更新的 GPU 成本变成 4 倍。官方说这看起来反直觉,但逻辑是"沿分辨率轴提供两倍信息",下采样后保留的细节远多于不这么做。
担心帧预算就用 High 或更低档——Epic 抗锯齿档的 GPU 成本明显更高。
隐藏成本:TSR 之后的 pass
TSR 处在后处理链中段。如果没有二级屏幕百分比,运动模糊和色调映射等之后的所有 pass 跑在显示分辨率而不是渲染分辨率上。
官方明确说:因为 TSR 默认开启,有大量工作投入到降低这些"TSR 之后"的隐藏成本上(半分辨率/四分之一分辨率输出,影响 Gaussian DOF、Convolution Bloom、Lens Flare、自动曝光、Local Exposure)。
上采样本身的成本
TSR 的主要 GPU 工作随它拿到的分辨率缩放(部分工作必须在显示分辨率做)。Valley of the Ancients 实测:r.ScreenPercentage=100 约 0.79ms,=50 约 0.43ms。
异步计算的收益(Fortnite Ch4 / PS5 / XSX 实测):视差启发式只依赖深度与速度缓冲(它们比场景色/半透明更早完成),可以异步计算,抵消约 0.5ms;最终 TSR 有效成本降到 1.5ms,关键路径 1.1ms。
| 权衡 | 收益 | 代价 | 什么时候不该用 |
|---|---|---|---|
| 低屏幕百分比 | 大幅省 GPU | 收敛慢、易糊、鬼影 | 快节奏竞技类宁可提高分辨率或降 WeightClamping |
| History 200% | 运动中锐利 | 历史更新 4 倍成本 | 预算紧用 High 档 |
| 异步计算 | 关键路径省 ~0.5ms | 依赖深度/速度缓冲就绪 | 调试时可关 |
| 闪烁时域分析 | 抑摩尔纹 | 不透明材质的像素动画会被误判成闪烁 → 鬼影 | 见下 |
| 历史复活 | 减少重新累积带来的鬼影 | 额外的缓存带宽(边缘) | 内存极紧可降 PersistentFrameCount |
7. 三类必须知道的内容约束
① WPO 顶点动画
用 WPO 做顶点动画的材质,必须同时求当前帧与上一帧才能得到正确运动向量;否则上一帧结果用的是当前帧的值 → 错误。
Previous Frame Switch 材质节点就是为此存在——它能生成正确的校正运动向量,让运动模糊与 TSR 重投影都正确。
| 相关设置 | 说明 |
|---|---|
项目设置 Output velocities due to vertex deformation | 默认开启:让 WPO 材质做双求值,即使 Actor 没动也输出速度 |
项目设置 Velocity Pass = Write after base pass | 会有额外 draw call 的性能代价;大量 WPO 物体(如整片森林)时代价更高 |
| 纯时间函数的材质 | 无需改动即可工作,但无法处理运行时改变动画的材质参数 |
② 半透明
半透明材质默认不画速度,最多画一层 → TSR 不知道它们怎么动 → 边缘不够锐利。
| 项 | 说明 |
|---|---|
| 半透明 pass | Before DOF / After DOF(默认) / After Motion Blur |
| TSR 的对策 | 对 After DOF 半透明专门加了一层模糊卷积——牺牲一点稳定性换取更少鬼影 |
| 输出速度 | 材质里勾选 Output Depth and Velocity 可让半透明写运动向量 |
| Opacity Mask Clip Value | 默认 0.333,深度与速度只能被整体覆写、不能像颜色那样混合。VFX 常用更高的值,只为最不透明的区域写速度 |
| 官方建议 | 只在明确知道自己在做什么时才改 Translucency Pass,默认 After DOF 就好 |
③ 像素动画的不透明材质
纹理平移这类像素着色器动画没有运动向量,但颜色频繁变化 → 被闪烁时域分析判定为"闪烁" → TSR 试图稳定它 → 产生鬼影。
解决方案:在材质(或材质实例的 Material Property Overrides)里勾选 Has Pixel Animation。这会把使用该材质的 primitive 编码进速度缓冲,让闪烁分析忽略这些像素。
8. 可视化与调试
| CVar / Show Flag | 看什么 |
|---|---|
Show > Visualize > Temporal Upscaler I/O | TSR 的原始输入/输出缓冲 |
Show > Visualize > Temporal Super Resolution | TSR 总览(粉=被禁用,黄/红=对画质有害,绿=有利于画质) |
r.TSR.Visualize 0 | 历史累积样本数(绿=够,红=不够) |
r.TSR.Visualize 1 | 基于深度/速度的视差遮挡解除 |
r.TSR.Visualize 2 | 历史被拒绝的 mask |
r.TSR.Visualize 3 | 历史被 clamp 的 mask |
r.TSR.Visualize 4 / 5 | 历史复活 mask / 复活帧里的 mask |
r.TSR.Visualize 6 | 空间抗锯齿计算区域 |
r.TSR.Visualize 7 | 闪烁时域分析生效区域(移动的像素被禁用时显示为粉) |
Show > Visualize > Motion Blur | 运动向量箭头;看方向对不对、物体是否是黄色(表示在画运动向量) |
Show > Visualize > Reprojection | 当前帧与重投影的上一帧之差;对不齐的地方会显色 |
r.TSR.Visualize -2 / -1 | 强制显示总览网格 |
DumpGPU(诊断跨帧累积问题最好用)
r.DumpGPU.Root="*TemporalSuperResolution*"
r.DumpGPU.FrameCount=30
r.DumpGPU.Stream=1
r.DumpGPU.FixedTickRate=30
r.DumpGPU.Delay=3
r.DumpGPU.CameraCut=1r.DumpGPU.FrameCount=30:TSR 跨帧累积,必须抓多帧才能看出伪影怎么演化r.ResetRenderTargetsExtent:改了渲染分辨率后让内部 RT 对齐- 动态分辨率开启时可用
r.DynamicRes.TestScreenPercentage锁定渲染分辨率(内部 RT 大小仍由r.DynamicRes.MaxScreenPercentage控制)
空间抗锯齿的自测
r.Test.CameraCut 1
r.Test.SecondaryUpscaleOverride 8
r.TSR.RejectionAntiAliasingQuality 0 / 1 ← 开关对比9. 鬼影排查(官方给出的检查单,按序执行)
- 确认是不是 TSR 造成的:用 Temporal Upscaler 视图看输入里有没有鬼影;或换抗锯齿方法/直接关掉 AA 对比。
- 是不是运动向量错了:TSR 靠运动向量重投影不透明几何。如果问题只出现在特定物体而不是整个场景,基本就是运动向量。
- 半透明(如云)覆写了速度?试
r.Translucency.Velocity 0快速验证 - WPO 是否基于动画参数?检查
Previous Frame Switch是否喂了上一帧的值 - 注意:运动向量计算不自动处理逐实例 transform 的运动
- 半透明(如云)覆写了速度?试
- 是不是闪烁时域分析造成的(先确认 2 已经排除):TSR 视图里找红色区域;若是做了着色器动画的不透明材质,勾 Has Pixel Animation。
- 物体是不是半透明:在 Temporal Upscaler 的
Translucency.AfterDOF.Color输入里确认。TSR 对 After DOF 半透明更不宽容(默认不画速度,无法正确重投影)。
10. 踩坑与排查
| 坑 | 现象 | 怎么验证 |
|---|---|---|
| 运动中画面糊 | 分辨率低 + 收敛慢 | 看 stat tsr 的 1spp;提高 Screen% 或降低 WeightClampingSampleCount |
| CPU 受限时画质变差 | TSR 依赖帧率不只是 GPU | 官方明确:CPU-bound 与非 VRR 的 VSync 都会影响 |
| WPO 顶点动画鬼影/模糊 | 上一帧值不对 | 材质里用 Previous Frame Switch |
| 纹理平移动画鬼影 | 被误判为闪烁 | 材质勾 Has Pixel Animation |
| 半透明边缘不锐利 | 默认不画速度 | 勾 Output Depth and Velocity;调 Opacity Mask Clip Value |
| VFX 萤火虫拖尾 | 历史采样数过高 | 降 r.TSR.History.SampleCount(最低 8) |
| Epic 档帧率不够 | History 200% 的 4 倍成本 | 降到 High 档(History 100%) |
| 大量 WPO 物体掉帧 | Velocity Pass 额外 draw call | 检查 Velocity Pass 设置;Output velocities due to vertex deformation 是否必要 |
| 摩尔纹 | Nanite 细节 + 掠射角 | 开 r.TSR.ShadingRejection.Flickering(High+ 默认开);调 Period 与 FrameRateCap |
| 改了分辨率摩尔纹位置变了 | 现有算法的已知局限 | 官方承认:现有硬件上没有足够高性能的解法,TSR 需要几帧才能重新定位 |
| 关了 AdjustToFrameRate | 低帧率下 VFX 闪烁 | 官方强烈不建议关 |
抗闪烁调参流程(官方给的步骤)
1. r.TSR.ShadingRejection.Flickering.FrameRateCap = 目标帧率(30 或 60)
2. t.MaxFPS 锁定编辑器帧率到同一个值
3. r.TSR.ShadingRejection.Flickering.Period 调到想要的效果
4. 确认后写进 DefaultEngine.ini,保证编辑器与目标平台一致