从硬件加速到屏幕空间追踪,理解 URP 17+ 中光线追踪的核心机制与 5 个生产级应用
一、什么是 URP 光线追踪
传统光栅化渲染(rasterization)只计算 从光源到表面 的直接光照,无法自然处理反射、折射、间接光等复杂现象。 光线追踪(Ray Tracing) 则反转了光线方向:从相机发射"虚拟光线"进入场景,与几何体求交,从而天然支持这些视觉效果。
Unity 6 / URP 17 提供了完整的光线追踪集成,底层使用 DXR(DirectX Raytracing)或 Vulkan RT 后端。 关键的是 URP 提供了 多种渲染模式,可以根据项目硬件预算灵活选择:
| 渲染模式 | 光追类型 | 硬件要求 | 适用场景 |
|---|---|---|---|
| Raster(光栅化) | 无 | 任意 | 移动端、低端 PC |
| Raster + Screen Space RT | SSR / SSGI / SSAO | 任意 | 中端 PC 主机 |
| Ray Traced | 硬件 DXR / Vulkan RT | RTX / RDNA2+ | 高端 PC、PS5、Xbox |
| Path Traced | 硬件 RT + 多次弹射 | RTX 30+ 建议 | 电影级、CG 短片 |

二、URP 光线追踪的整体架构
URP 的光线追踪并不是取代整个前向/延迟渲染,而是 嵌入 现有管线的特定阶段, 仅对需要的视觉效果启用追踪计算。整体流程如下:

核心数据结构
URP 的光线追踪依赖三个核心数据对象:
- RayTracingAccelerationStructure(加速结构) :BVH(Bounding Volume Hierarchy)形式的场景几何体组织,
BLAS描述单个网格,TLAS描述整个场景实例层级。 - RayTracingShader(追踪 shader) :包含
__raygen、__miss、__closesthit、__anyhit等可调函数。 - RayTracingPass :通过
CommandBuffer.DispatchRays调度一次追踪计算。
三、追踪算法的核心数学
追踪的本质是 光线与几何体求交。在硬件 RT 出现之前,CPU 上有经典算法如 Möller-Trumbore 三角面求交; GPU 的硬件 RT 把这一计算交给 BVH 加速结构和专用电路(如 NVIDIA 的 RT Core)处理。
光线定义
R(t) = O + t · D, t ∈ tmin, tmax
其中 O 是起点,D 是方向,t 是沿光线的距离参数。
追踪递归方程(渲染方程)
Lo(p, ωo) = Le + ∫Ω f(p, ωi, ωo) · Li(p, ωi) · (n · ωi) dωi
渲染方程描述了从表面点 p 朝方向 ωo 出射的辐射亮度。蒙特卡洛路径追踪通过发射随机光线采样这个积分。
BVH 加速结构的工作方式

性能关键: BVH 重建(rebuild)是追踪性能的最大瓶颈之一。 静态场景只需构建一次,动态场景可以使用 RayTracingAccelerationStructure.Update 增量更新。 URP 内部会自动管理这个生命周期,开发者只需在 UniversalRenderPipelineAsset 中开启对应开关。
四、案例一:光线追踪环境光遮蔽(RTAO)
环境光遮蔽(AO)模拟的是 几何体之间的相互遮挡。传统 SSAO 用屏幕空间深度近似,效果受屏幕分辨率限制; RTAO 在半球空间内发射真实光线,能捕捉到更精确的远距离遮蔽关系。
算法原理
- 对每个表面点 p,沿法线半球方向采样 N 条光线
- 追踪每条光线,统计未命中(被遮挡)比例
- 将未命中率作为 AO 系数
AO(p) = 1 − (1/N) · Σ visibility(p, ωi)

URP 配置步骤
- 打开
UniversalRenderPipelineAsset,将 Rendering Path 改为Deferred。 - 在
UniversalRendererData上点击 Add Renderer Feature → Screen Space Ambient Occlusion。 - 将 Ambient Occlusion 的
Source设为Ray Traced(需 GPU 支持 DXR/Vulkan RT)。 - 调节
Max Ray Length、Sample Count、Denoiser三个核心参数。
推荐参数: Sample Count 在 PC 设为 4--8,主机 设为 2--4(依赖时序降噪)。 Max Ray Length 决定 AO 半径------室内 2--5m,室外 5--20m。Max Ray Length 越大,性能开销越高。
五、案例二:光线追踪反射(RTR)
反射是 RT 最直观的应用。SSR(屏幕空间反射)只能反射屏幕上可见的物体,遇到屏幕外或被遮挡的几何体时只能 fallback 到 cubemap; RTR 不受屏幕限制,能反射场景中的任何物体。

URP 中的反射模式对比
| 反射模式 | 支持屏幕外几何体 | 性能开销 | 最佳场景 |
|---|---|---|---|
| Reflection Probe(烘焙) | 否(仅静态) | 极低 | 室内静态场景 |
| SSR | 否 | 中 | 光滑地面、金属 |
| RTR | 是 | 中高 | 镜面、抛光金属、水面 |
| Hybrid(SSR + RTR 切换) | 是 | 可调 | 复杂动态场景 |
// URP 中启用 RTR(伪代码基于 URP 17 Renderer Feature) class RayTracedReflectionsFeature : ScriptableRendererFeature { public enum Mode { Off, SSR, RTR, Hybrid } public Mode mode = Mode.Hybrid; public int sampleCount = 4; public float maxRayLength = 50f; public float smoothnessCutoff = 0.6f; public override void AddRenderPasses(ScriptableRenderer renderer, ...) { if (mode == Mode.Hybrid) { // 平滑度高 → 用 SSR(便宜) // 平滑度低 + 屏幕外 → 用 RTR } } }
六、案例三:光线追踪全局光照(RTGI)
全局光照(GI)模拟光能在场景中 多次弹射 的效果。传统 lightmap 是预计算的,无法处理动态物体; 屏幕空间 GI(SSGI)受屏幕限制。RTGI 通过追踪二次光线,能实时计算单次或多次弹射的间接光。
单次弹射 RTGI 算法
- 从当前着色点 p 沿法线半球采样 N 条光线
- 追踪每条光线,命中点 q 的位置和法线从 G-Buffer 读取
- 在 q 处直接查询光照(如 SH 环境光或主光)
- 累加作为 p 的间接光
LGI(p) ≈ (1/N) · Σ Ldirect(q) · visibility(p, q) · cos(θ)

**性能注意:**单次弹射 RTGI 在 1080p 下每像素采样 4 条光线、追踪到第一次命中时 通常已接近实时上限(高端 PC 约 4-8ms)。如果需要多次弹射,建议改为 Path Tracing 并启用 NRD 去噪。
七、案例四:光线追踪阴影(RTS)
光栅化阴影(shadow map)本质是 从光源视角渲染深度 ,必然存在分辨率、走样、级联开销等问题。 追踪阴影则从 接收表面向光源 发射一条光线,命中即被遮挡------非常直观。
算法对比
| 特性 | Shadow Map | Ray Traced Shadow |
|---|---|---|
| 分辨率 | 受 shadow map 分辨率限制 | 无(按需追踪) |
| 锯齿 | 有,需 PCF 软化 | 天然无锯齿 |
| 面积光源 | 困难(多张 cascade) | 天然支持 |
| 性能 | 较低 | 高(与像素数相关) |
| 动态光源 | 需要重建 | 无需重建 |

面积光的"软阴影"特性
追踪阴影天然支持 面积光源软阴影。对光源表面采样 N 个点,从接收表面向每个点追踪,求遮挡比例:
Visibility = (1/N) · Σ O_hit(p, light_i) == false
其中 N 越大阴影越柔和,但 N=4 配合去噪通常就够用。
八、案例五:路径追踪(Path Tracing)
路径追踪是 蒙特卡洛方法 直接求解渲染方程的极限形式:每条光线在表面多次弹射(反射、折射), 每次根据 BRDF 随机采样方向,最终结果是无偏的(unbiased)。
伪代码
// 路径追踪 Ray Generation Shader 伪代码 [shader("raygeneration")] void RayGen() { float3 rayDir = GenerateCameraRay(DispatchRaysIndex().xy); float3 throughput = 1.0; float3 radiance = 0.0; for (int bounce = 0; bounce < MAX_BOUNCES; bounce++) { TraceRay(payload, origin, rayDir, ...); if (payload.hitDistance < 0) { radiance += throughput * SampleSky(rayDir); break; } // 命中表面,采样 BRDF float3 brdf = SampleBRDF(payload.normal, rayDir, payload.albedo); float3 newDir = CosineWeightedSample(payload.normal); radiance += throughput * payload.emission; throughput *= brdf * dot(payload.normal, newDir); rayDir = newDir; } _Output[DispatchRaysIndex().xy] = float4(radiance, 1); }

关于噪声: 路径追踪的输出在低采样数下充满噪点。生产实践中通常用 累积帧(progressive accumulation) 或 NRD 去噪器 提升质量。 URP 17 内置了对 NVIDIA NRD 库的封装,可直接调用。
九、性能优化:半分辨率追踪 + 时序去噪
追踪的瓶颈在 每像素光线数 × 总像素数。生产管线几乎都采用两个核心优化:

关键配置
// URP 17 半分辨率追踪配置 var settings = new RayTracingSettings { resolutionScale = 0.5, // 半分辨率 sampleCount = 1, // 每像素光线数 maxRayLength = 30, // 最大追踪距离 denoiser = DenoiserType.NRD, // NRD 去噪 temporalAccumulation = true, // 启用时序累积 motionVectorRejection = 0.1f, // 动体区域检测阈值 };
实战数据: 4K 屏幕下,0.5 + NRD 的 RTR 大约 1.2ms,
而全分辨率 + 1spp 无去噪的 RTR 接近 4ms 且充满噪点。半分辨率方案性价比高约 5 倍。
十、完整配置流程
前置条件
- Unity 6(或 Unity 2023.3+ LTS)+ URP 17+。
- GPU 支持硬件 RT:NVIDIA RTX 系列、AMD RDNA2+、Intel Arc 显卡;或 Vulkan 1.2 + RT 扩展。
- Player Settings → Other Settings → 勾选
Ray Tracing。 - URP Asset 中 Rendering 改为 Deferred(光追仅在 Deferred 下可用)。
添加追踪 Renderer Feature
- 选中
UniversalRendererData,在 Inspector 中点击 Add Renderer Feature。 - 选择需要的效果:
Screen Space Ambient Occlusion、Screen Space Reflections、Screen Space Global Illumination。 - 对每个 feature,将
Mode改为Ray Traced。 - 配置 Sample Count、Max Ray Length、Denoiser。
- 在场景中加入测试物体(带反射地板、面积光源)验证效果。
性能 vs 质量预设
| 预设 | 分辨率缩放 | 每像素光线 | 弹射数 | 去噪 | 4K 目标帧时 |
|---|---|---|---|---|---|
| Ultra | 1.0 | 8 | 4 (Path) | NRD + 时序 | ~8ms (RTX 4080) |
| High | 0.5 | 4 | 2 | NRD + 时序 | ~3ms |
| Medium | 0.5 | 1 | 1 | NRD + 时序 | ~1.5ms |
| Low | 0.25 | 1 | 1 | 简单双边滤波 | ~0.8ms |
十一、常见坑与最佳实践
1. 透明物体追踪
默认追踪在 alpha test 物体(带 cutout 的植被、栅栏)上会产生错误结果。需要:
cs
// 透明材质追踪时关闭 alpha test [shader("closesthit")] void ClosestHit(inout Payload payload) { if (alphaTestedMaterial) { // 调用 anyhit shader 检查 alpha IgnoreHit(); // alpha 不通过则忽略 } payload.hitDistance = RayTCurrent(); }
2. 动体更新
URP 默认每帧重建 BLAS 对所有 Skinned Mesh 来说开销巨大。 对骨骼动画物体推荐使用 RayTracingAccelerationStructure.Update 增量更新。
3. 不开去噪不要出图
追踪结果在低采样下噪点非常明显,不接 NRD/降噪器直接展示是业余做法。 始终在追踪 Pass 后跟一个去噪 Pass,否则用户能直接看到噪点。
4. 远距离光线"飞过"全空
Max Ray Length 过大会让大部分光线"飞过整个场景未命中",浪费算力。推荐值:
- 室内:5 - 20m
- 室外:50 - 200m
- 超远景观:500m+,配合天空盒 fallback
5. 与 forward 模式不兼容
URP 的 Forward/Forward+ 模式 不支持 光线追踪 Renderer Feature。 启用 RT 之前必须确认项目使用 Deferred 模式,否则相关 feature 会被自动禁用。
十二、总结
光线追踪让 URP 的渲染能力跃升一个量级。理解下面的对应关系能帮助你快速决策:
| 视觉效果 | 追踪方案 | 核心收益 | 建议最低配置 |
|---|---|---|---|
| 精确 AO | RTAO | 远距离、复杂几何的遮蔽 | RTX 2060 / RX 6600 |
| 完美反射 | RTR + SSR 混合 | 屏幕外物体反射 | RTX 2070 / RX 6700 |
| 动态间接光 | RTGI | 动态物体 GI、彩色反弹 | RTX 3060 / RX 6800 |
| 面积光软阴影 | RTS | 无锯齿、面积光源 | RTX 3050 / RX 6600 |
| 电影级真实感 | Path Tracing | 无偏全局解 | RTX 3080 / RX 6900 |
一句话总结: URP 的追踪不是替代光栅化,而是光栅化之上的视觉补强。 用"半分辨率 + NRD 去噪"作为默认方案,把有限的 RT 算力花在刀刃上。