一、问题的起点:为什么不能直接渲染 4K
4K 分辨率 = 3840×2160 ≈ 830 万像素。1080p = 207 万像素。渲染 4K 的像素着色器工作量是 1080p 的 4 倍——帧时间直接乘 4。
超分辨率(Super Resolution)技术要回答的问题:
能不能用 1080p 的成本渲染,输出看起来接近 4K 的画面?
这不是简单的”拉伸+锐化”——那种做法只会得到模糊的 4K。真正的高质量超分需要时间维度上的信息。
二、核心思想:每帧渲染不同的半个像素
1 Jitter:让每一帧的采样点错开
关键洞察:如果每一帧渲染的画面在子像素级别上有微小偏移(Jitter),那么多帧累积起来,相当于用 1080p 的成本采集了超采样级别的信息。
第 1 帧:采样点在像素 (0.1, 0.1)第 2 帧:采样点在像素 (0.6, 0.3)第 3 帧:采样点在像素 (0.3, 0.8)第 4 帧:采样点在像素 (0.8, 0.6)... 8 帧后,每个 1080p 像素内部被采样了 8 个不同位置UE 使用 Halton 序列生成 Jitter 模式——保证多帧累积后采样点均匀覆盖整个像素,不会聚集。
2 历史帧累积:时间维度的 MSAA
当前帧(1080p, Jitter 后)→ 和上一帧对齐 → 累积 → 输出(4K)如果每一帧的采样点都错开,那么连续 N 帧累积后,我们得到了 N 倍采样密度的信息。这就是时域超采样(Temporal Supersampling)。
传统 MSAA 是空间上的多采样(每个像素内多个采样点),时域超分是时间上的多采样——用连续帧的信息拼出更高分辨率的画面。
三、三个必须解决的工程问题
1 运动补偿:历史帧的位置对不上
如果摄像机在动,上一帧的画面和这一帧的位置完全不同。直接混合两帧 → 拖影(Ghosting)。
解决方案:运动向量(Motion Vector)
每个像素存储它在上一帧的屏幕位置偏移:
MotionVector(x, y) = 当前帧像素的屏幕位置 - 上一帧同一物体点的屏幕位置累积历史帧时:
float2 HistoryUV = CurrentUV - MotionVector; // 反推该像素在上一帧的位置float3 HistoryColor = HistoryBuffer.Sample(HistoryUV);float3 CurrentColor = CurrentFrame.Sample(CurrentUV);
// 混合(实际算法更复杂,这里只是示意)Output = lerp(HistoryColor, CurrentColor, BlendFactor);Motion Vector 的质量直接决定超分的质量。 摄像机移动、物体动画、骨骼蒙皮、粒子——每种运动都要在 GBuffer 里正确写入 Motion Vector。
2 Disocclusion:被挡住的东西突然出现
转身的时候,视野里出现了一堵墙后面的东西——上一帧这些像素根本没有历史信息。直接采样历史 → 拿到的是墙的颜色 → 鬼影。
解决方案:Disocclusion 检测
// 检查历史像素和当前像素的深度是否连续float HistoryDepth = HistoryDepthBuffer.Sample(HistoryUV);float CurrentDepth = DepthBuffer.Sample(CurrentUV);
if (abs(HistoryDepth - CurrentDepth) > Threshold) { // 深度突变——这是新出现的区域,不能相信历史 Output = CurrentColor; // 只用当前帧} else { Output = lerp(HistoryColor, CurrentColor, BlendFactor);}更精细的检测还会检查相邻像素的 Motion Vector 一致性——如果周围 3×3 的 Motion Vector 都不一样,说明这个区域有复杂运动,降低历史权重。
3 响应性:历史帧占多少权重
历史帧权重太高 → 画面干净但”糊”,快速运动时拖影严重。历史权重太低 → 锯齿回来了。
TSR 的响应性控制:
- 相机运动快 → 降低历史权重(防止拖影)
- 物体快速移动 → 同样降低
- 静止场景 → 提高历史权重(画面更干净)
- 颜色剧烈变化(如爆炸闪光) → 用颜色 Clamp 防止历史帧的颜色污染当前帧
四、TSR vs TAA:有什么区别
TAA(时间抗锯齿)和 TSR(时间超分辨率)是同族技术,核心都是时域累积。区别在于输入输出分辨率:
TAA: 输入 1080p → 输出 1080p(只做抗锯齿,不提高分辨率) Jitter 的目的是采集子像素信息做抗锯齿
TSR: 输入 1080p → 输出 4K(提高分辨率 + 抗锯齿) Jitter 的目的不只是抗锯齿,还要重建高分辨率画面 TSR 在升采样时做更高质量的重建(Lanczos 类滤波 + 时域信息融合)为什么 UE5 默认 TSR 而不是 TAA:
- 4K 屏幕成为主流,但 GPU 跑不动原生 4K
- TSR 在 1080p 渲染 + 4K 输出的配置下,画面质量显著高于”1080p + TAA + 双线性拉伸”
- 而且 TSR 的输出可以自由配置——性能不够就渲染 720p 输出 1080p,性能充足就渲染 1440p 输出 4K
五、DLSS / FSR / TSR 的对比
| TSR (UE5) | DLSS (NVIDIA) | FSR 2 (AMD) | |
|---|---|---|---|
| 开发方 | Epic | NVIDIA | AMD |
| 硬件要求 | 所有 GPU | 仅 NVIDIA RTX(需要 Tensor Core) | 所有 GPU |
| 核心方法 | 时域累积 + 高质量升采样 | 时域累积 + 神经网络重建 | 时域累积 + 升采样(类似 TSR) |
| 优点 | 跨平台、开源可改、质量优秀 | 质量最高、性能好(Tensor Core 跑 AI) | 开源、跨硬件 |
| 缺点 | 需要引擎集成 | 硬件锁定 | 质量略低于 DLSS |
| UE5 支持 | 内置 | 插件 | 插件 |
核心差异:DLSS 用神经网络做重建——输入”当前帧低分辨率 + 历史帧 + Motion Vector”,网络输出高质量高分辨率画面。Tensor Core 专门做矩阵运算,跑推理极快。TSR/FSR 用传统图形学方法(时域累积 + 滤波),不需要特殊硬件。
DLSS 为什么质量更高:神经网络能从海量训练数据里学到”模糊的低分辨率像素 + 运动向量 → 锐利的高分辨率画面”的映射,特别是在处理边缘、细小线条、重复纹理(如铁丝网)时比手工滤波更强。但它偶尔会”脑补”出不存在的细节(Hallucination)。
六、TSR 的工程成本
1 渲染管线必须配合
TSR 不是后处理插件——它需要整个渲染管线配合:
GBuffer Pass: → 必须输出 Motion Vector Buffer(逐像素运动向量) → 必须输出正确的 Jitter 过的投影矩阵
光照 Pass: → 用 Jitter 过的投影矩阵渲染
TSR Pass(最后): → 输入:当前帧低分辨率 + 历史高分辨率 + Motion Vector + Depth → 输出:高分辨率画面任何材质忘了写 Motion Vector → 那个物体的边缘会出现拖影。 这是超分技术最常见的 bug 来源。
2 半透明物体的挑战
半透明物体(粒子、玻璃)通常不写 Motion Vector(因为它们混合了多层颜色)。TSR 对它们的处理方式:
- UE 的做法:半透明在 TSR 之后渲染(以目标分辨率渲染半透明,直接叠加在高分辨率画面上)
- 代价:半透明物体没有时域累积的好处(粒子可能显得有锯齿)
七、什么时候不用 TSR
| 场景 | 替代方案 |
|---|---|
| VR(需要超低延迟,时域累积增加一帧延迟) | MSAA(前向渲染 + 硬件 MSAA) |
| 竞技游戏(Ghosting 影响瞄准判断) | 原生分辨率 + MSAA 或 FXAA |
| 像素风格游戏(不需要超分) | 原生分辨率 + 最近邻采样(保持像素锐利) |
| UI 和文字 | 无论如何都单独渲染在 TSR 之上(UI 永不被超分) |
TSR 增加一帧延迟——因为你看到的是”当前帧+历史帧的混合”。对 30fps 游戏这是 33ms 的额外延迟,对竞技游戏不可接受;对 60fps 的 3A 单机游戏完全没问题。
八、总结
| 概念 | 一句话 |
|---|---|
| 时域超分 | 用连续帧的 Jitter 采样拼出高分辨率画面 |
| Jitter | 每帧采样点错开子像素位置——Halton 序列均匀覆盖像素 |
| Motion Vector | 历史帧对齐的关键——每个像素存它在上一帧的位置 |
| Disocclusion | 新出现的区域没有历史——深度突变检测 + 降低历史权重 |
| TSR vs TAA | 同族技术——TAA 只抗锯齿,TSR 提高分辨率 |
| DLSS | 时域累积 + 神经网络——质量最高但锁 RTX |
| 成本 | 管线配合(Motion Vector)+ 一帧延迟 + 半透明特殊处理 |
TSR 代表现代渲染的一个大趋势:不再追求”每一帧独立完美”,而是让帧与帧之间协作——时间成为新的采样维度。理解时域技术,就理解了从 TAA 到 DLSS 到未来所有超分技术的核心。