【AI中字】《生化危机:安魂曲》与《PRAGMATA》中 RE 引擎的实时...
_Aminos_
2026年04月02日 18:39

以下是该文档的详细总结,内容涵盖 Capcom 在 RE Engine 中为《生化危机:安魂曲》(Resident Evil Requiem)和《PRAGMATA》实现实时光线追踪(Path Tracing)的技术演讲,以及 NVIDIA 工程师提供的底层性能优化分析。

---

## 一、演讲概述

- **演讲者**:Capcom 的 Hitoshi Mishima(三岛仁)以及 NVIDIA 的 Calvin Shu

- **主题**:RE Engine 中路径追踪(Path Tracing)的实现,集成 NVIDIA DLSS 3.5(DLSS RR)以及相关优化

- **涉及游戏**:《生化危机:安魂曲》、《PRAGMATA》

- **关键技术**:路径追踪 vs. 光线追踪、NEE(Next Event Estimation)、RIS(Resampled Importance Sampling)、ReSTIR GI、DLSS RR 引导缓冲区(Guide Buffer)、DXR 1.2 与 SER(Shader Execution Reordering)等

---

## 二、路径追踪与光线追踪的对比

- **路径追踪**:更精确的实时渲染,包括更细致的阴影、更稳定的降噪、更锐利的反射、更准确的遮挡。

- **传统光线追踪**(RE Engine 原有实现):仅用于间接光照,直接光照仍使用光栅化。

- **路径追踪统一处理**:直接光照、间接光照、透明物体、后期效果均纳入统一管线。

---

## 三、RE Engine 路径追踪管线

### 3.1 总体流程

1. **Common Pass**:计算着色器执行可复用组件(如蒙皮、集群模拟)。

2. **G-Buffer**:提供初始命中信息。

3. **路径追踪核心循环**(每弹射一次 dispatch):

- 使用 NEE 评估直接光照

- 采样 BSDF 确定方向并发送新光线

- 如果命中几何体,更新表面信息,重复 NEE 与 BSDF 采样

- 如果未命中,则使用 IBL(Image-Based Lighting)贡献结束路径

- 使用俄罗斯轮盘(Russian Roulette)终止长路径

4. **最多 3 次弹射**(3 次 dispatch)

5. **可选的 ReSTIR GI** 用于稳定 DLSS RR 质量

### 3.2 与原有光线追踪的兼容性

- 路径追踪与光线追踪使用相同的 Ray Query 接口和材质着色器

- 实现时间:约 1.5 年,由两名开发人员完成

---

## 四、RIS(Resampled Importance Sampling)策略

### 4.1 简化 BSDF 用于 RIS

- 生成初始候选光源时,使用简化的 BSDF:

- 漫反射:Lambertian

- 镜面:单叶 GGX

- 将 BSDF 转换为单通道值,简化计算(F、G、L 评估)

### 4.2 光源剔除结构

- 类似光栅化光源剔除,定义每个光源的影响范围

- 使用 3D 纹理,每个 texel 存储光源 ID 位掩码

- 每个 cell 尺寸:16×128×128(长宽深)

- 在 shading point 评估重要光源

### 4.3 高强度 IBL 与室内场景问题

- IBL 在室内场景中导致高方差噪声,因为 RIS 未评估可见性

- **解决方案**:从候选集中移除 IBL,单独评估其亮度

### 4.4 高强度聚光灯问题

- RIS 未评估可见性,导致聚光灯照射区域偏暗

- **解决方案**:亮度补偿——使用相机曝光和调整系数作为 reservoir 更新权重,而非传统的 luminance (F·G·L)

### 4.5 弹射与阴影光线数量

- 第一弹射:2~3 条阴影光线

- 第二、三弹射:1 条阴影光线

- 方向光单独处理;点光源与发光多边形通过 RIS 合并

---

## 五、发光多边形(Emissive Polygons)采样

### 5.1 问题

- 仅靠光线命中(ray-hit only)会产生大量噪声

- NEE 必须包含发光多边形

### 5.2 解决方案:Walker's Alias Method

- 构建数据结构:每个 bucket 最多两个元素,支持 O(1) 采样

- 权重:三角形面积 × 基础强度,可包含距离衰减

- 为每个子网格(submesh)与材质对构建一次数据结构(假设面积不变)

- 采样步骤:

1. 用第一个随机数选择 bucket

2. 用第二个随机数选择 bucket 中的元素

3. 选中子网格后,在其三角形上均匀采样

- 预生成样本存于 buffer 中以避免每帧开销

- 发光纹理的影响通过 RIS 进一步降低

---

## 六、ReSTIR GI 的应用

### 6.1 目的

- 稳定 DLSS RR 的质量,减少间接光照的离散(dispersion)

### 6.2 实现细节

- 当前帧像素信息与上一帧像素信息混合,进行重采样(resampling)

- 为避免对 DLSS RR 产生过高的时间相关性,重采样时选择与上一帧像素略有偏移的位置

### 6.3 效果改善示例

- **鬼影/模糊区域**:右侧使用 ReSTIR GI 后明显改善

- **次表面散射(Subsurface Scattering)**:散射前后亮度差异被写入 Guide Buffer,消除了 RR 导致的散射伪影

- **毛玻璃/模糊玻璃**:同样使用次表面散射 Guide 方法消除伪影

---

## 七、DLSS RR 引导缓冲区(Guide Buffer)的扩展

### 7.1 遮挡掩码(Disocclusion Mask)用于雨水/水滴

- 问题:雨水、水滴在 DLSS RR 中变得透明或被过度降噪

- 解决方案:创建遮挡掩码,标记雨水、水滴的像素位置,强制 RR 保留细节

- 注意:过度使用掩码会重新引入噪声,应保守使用

### 7.2 动画投影纹理光源

- 问题:动态纹理光(如地面波纹)导致延迟或拖尾

- 解决方案:利用光源动画信息计算权重,估计每个 shading point 的贡献,创建包含掩码,仅对动画光强烈的区域施加修正

### 7.3 全息图案(Hologram)

- 问题:全息图案使用 emissive 颜色动画,但 DLSS RR 的 Guide Buffer 未包含该信息,导致图案模糊

- 解决方案:将 Guide Buffer 中的漫反射 albedo 和镜面 albedo 替换为 emissive 颜色,使图案清晰可见

---

## 八、头发渲染(Hair Strands)

- 《生化危机:安魂曲》和《PRAGMATA》均使用发丝(strands)模拟头发

- 结合硬件光栅化和软件光栅化

- **PRAGMATA 的挑战**:低重力环境下长发飘动,导致 fallback mesh 与 strands 模拟不一致,产生错误阴影

- **解决方案**:为 strands 构建专用的 BVH(基于 NVIDIA OptiX 或 DXR),使光线追踪与光栅化表现一致

---

## 九、阴影与 Alpha 测试

### 9.1 粗几何体阴影

- 路径追踪产生的阴影可能因几何体粗糙而不完美

- 仅在过场动画中使用特殊方法(参考论文,未详细展开)

### 9.2 Alpha 测试

- 光线追踪中 Alpha 测试通常使用 Any Hit shader

- 路径追踪中为避免复杂 Any Hit shader,采用屏幕空间 Alpha 测试(Screen Space Alpha Test):

- 类似阴影贴图的逆过程,不产生阴影而是允许光线穿过

- 由光栅化器决定命中位置是否可见

---

## 十、BVH 管理与异步计算

- BVH 作为加速结构在后台构建

- **阴影终止点(Shadow Terminator)**:使用 recast ray 避免自相交

- **异步计算**:将 Direct Queue 与 Compute Queue 结合,避免因同时使用 Frame Generation 和 BVH 更新导致的空闲

---

## 十一、性能数据(2022年11-12月)

- 《生化危机:安魂曲》在 4K + DLAA 模式下的初始性能:约 21ms/帧

- 经过优化后:17.7ms → 16.9ms(SER 优化)→ 13.3ms(驱动优化,未来补丁)

---

## 十二、底层性能优化(Calvin Shu 部分)

### 12.1 计算着色器波前(Wavefront)实现

- 每弹射一次 dispatch,写入活跃像素信息,使用原子计数器(atomic append)和间接调度

- 活跃像素的 warp 平均占用 13.7 线程,相干性 43%

- 性能瓶颈:光采样循环(punctual light + emissive light)

### 12.2 光采样循环优化

**原始流程**(每光样本):

- 调用随机函数 2 次

- 评估完整 BRDF

- 向 reservoir 输出漫反射/镜面 radiance

- 再调用随机函数 1 次

- 追踪阴影光线,通过后累加

**优化措施**:

- 简化 RIS 目标函数:仅关注镜面 lobe,漫反射使用固定项

- 使用 world space 的 vanilla GGX 代替高质量 GGX(避免 Firefly 函数)

- 合并随机调用:使用一个 uint 随机数,拆分为高 16 位和低 16 位作为两个 float

- 共享 reservoir 间的随机种子

- 光采样循环只输出 incoming radiance,最后追踪阴影光线时才计算完整 BRDF

**结果**:性能提升 15%(21ms → 17.7ms),指令数减少约 3k,样本数从 400k 降至 300k

### 12.3 DXR 1.2 与 SER(Shader Execution Reordering)

**波前方法 vs. SER**:

- 波前方法:需要手动通过 UAV 传递数据,全局内存开销大,每弹射需同步

- SER:编译器自动决定传递变量,数据可能留在片上,所有弹射并行执行,支持不同材质的不同 hit shader

**初始 SER 移植结果**:23.5ms(SER off)→ 20.8ms(SER on),仍慢于波前方法的 17.7ms

**原因分析**:

- SER 版本指令数高达 24k(波前方法每 pass 约 11k,两个 pass 共 22k 但可独立切换资源)

- 因为合并了两次弹射,且静态 SRV 引用导致编译器重复生成指令

- 35% 时间消耗在“无指令停顿”(等待加载新指令)

**解决方案**:

- 将静态 SRV 引用改为 bindless 数组,使编译器只生成一套代码

- 指令数降至 12k,无指令停顿降至 18%,性能达到 16.9ms(略优于波前方法)

**最终**:结合驱动优化,可降至 13.3ms

### 12.4 性能建议总结

- 减少光采样循环中的 ALU 操作

- 简化目标函数评估

- 复用随机种子,拆分 uint 为两个 float

- 合并光循环类型以减少指令缓存缺失

- 考虑完整 ReSTIR DI 实现以共享相邻像素和时间样本

- 推荐使用 DXR 1.2 + SER,注意避免过度特化的代码路径

---

## 十三、DLSS RR 引导缓冲区的使用建议

- 尽量先不使用掩码,仅在必要时保守添加

- 过度使用掩码会重新引入噪声,关闭累积效果

- NVIDIA 将持续改进 Disocclusion Mask 引导缓冲区

---

## 十四、问答环节摘要

1. **最困难的部分**:满足美术人员的期望(环境间接光照的“煮沸”效果、ReSTIR GI 导致的遮挡变化)

2. **为何使用 Ray Query 而非完整光线追踪管线**:引擎已有 Ray Query 实现,SER 较新,未能在发布前完全优化完成

3. **遮挡掩码过度使用是否导致噪声**:是,毛玻璃等问题使用次表面散射 Guide 而非遮挡掩码

4. **美术协作**:技术美术(TA)收集各项目问题,与引擎团队协作

5. **随机数重用与拆分是否引入偏差**:未严格证明,通过视觉验证

6. **最大性能提升因素**:光源剔除(light grid culling)

7. **切换 IBL 采样策略时是否出现可见噪声**:RR 处理良好,几乎无可见切换噪声

---

## 十五、未来工作

- 继续改进 ReSTIR GI

- 发光多边形评估

- 更多性能优化和 DLSS RR 更新

---

## 十六、致谢

- Capcom 开发团队(Kenta Nakamoto, Kosuke Navata 等)

- NVIDIA DevTech 团队

---

**总结完毕**。文档详细介绍了 Capcom 在 RE Engine 中实现实时路径追踪的全套技术方案,包括核心算法、采样策略、降噪与引导缓冲区、性能优化以及与 NVIDIA 的合作成果。