# 基于物理的渲染(Physics-Based Rendering, PBR)

基于物理的渲染指的是一种能对光在物体表面的真实物理反应提供精确渲染的方法。

广泛来说,所有的渲染在某种程度上都是 “基于物理的”,但 “基于物理的” 这个术语在实践中意味着我们将严格遵循物理模型,而不是 “现象学”。现象学通过主观经验感知特征,例如使用经验公式将高光放置在 “正确” 的位置。

# 光线

光线是用几何直线表示光的传播方向的几何抽象。光在均匀透明介质中遵循着直线的发射轨迹。光在不透明表面中的反射和光在不同介质中的反射和折射的轨迹是可以计算并绘制的。

  • 反射:光在传播过程中遇到两种不同介质的交界面时,一部分光会返回原介质继续传播。反射定律:光线的入射角等于反射角。
  • 折射:光在穿越介质或经历介质的渐次变化时传播方向会发生改变,不同折射率介质会发生不同的角度偏转,折射路径为直线。
  • 散射:光在通过不均匀的介质时,一部分光会偏离原来的传播方向,向四面八方散开,偏向角取决于材质本身。散射发生在介质内部。
  • 光的吸收:光照射到物体表面或进入物体内部时,光能转化为其他形式的能量(主要是热能)。

当光由 A 介质进入 B 介质时,它会在 B 介质内产生多次散射,然后再次穿透出 B 介质。二次折射回原介质的穿透点与首次折射时的位置大致相同。

另外:物质的厚度是一个重要的因素,它会影响光的散射和吸收。例如耳朵皮肤的透光。当光线较强时,我们会观察到散射的光线穿过耳朵后的样子。

# 漫反射、高光反射、次表面散射

高光反射是指光在完美的平面上被反射时,其路径符合入射角等于反射角的现象。如果观察角度正好位于反射方向附近,你就会看到一块亮亮的高光。越粗糙的表面,其高光范围就越大,高光亮度会越暗。

漫反射是指光照射到粗糙表面后,反射光线向各个方向均匀散开的现象。从任何角度看,这块表面亮度都差不多。漫反射物质一般对光的吸收性很高,所以光线穿入点和穿出点之间的距离通常可以忽略不计。

次表面散射是指当光打到物体表面时,并不是所有光都会在表面反射,而是在内部发生多次散射的现象。光会进入物体内部,在内部发生多次散射,然后再从内部穿透出来。
含有强散射的半透明材质,例如雾、牛奶、皮肤、玉器等。通常会加入次表面散射的光照模型,以保证渲染物理性质的精确性。此时,光线散射的距离(光线的穿入点和穿出点)就需要加入到计算中。当计算一些变化较大且低散射、低吸收的材质时(例如雾或烟),可能需要渲染成本更高的算法来执行,例如蒙地卡罗模拟。

# 颜色

光是电磁波。不同波长对应不同颜色。可见光大约在 400nm 到 700nm 之间。一个表面被光照射后,会对不同波长产生不同的反射率,这个函数叫光谱反射率。比如一个红色苹果,它并不是在发红光,而是它对长波(红光)反射多,对短波(蓝绿光)吸收多。

人眼只有三类锥细胞,分别对长波、中波、短波敏感。它们的响应曲线重叠很严重。也就是说,很多不同的光谱组合,会在视觉系统里产生相同的三种刺激值,这种现象叫同色异谱。两个物体光谱完全不同,但在你眼里是一样的颜色。
人脑也会修正颜色。色恒常性让我们在不同光源下仍然认出白纸是白的。

图形学里,我们通常不处理完整光谱,而是用 RGB 三通道表示颜色。这是一个工程折中。真实世界是连续光谱,但显示器只能发红绿蓝三种基色。于是我们用三维向量近似光谱空间。

# 微平面理论

# 微小的镜面

微平面理论假设任何宏观表面都是由无数个微小的、完全平滑的镜面组成的。

  • 宏观上:我们看到的是一个粗糙或平滑的平面。
  • 微观上:每个微平面都像一面小镜子,根据其自身的法线将光线进行镜面反射。
  • 粗糙度:本质上是微平面法线分布的混乱程度。法线越趋向一致,表面越平滑(高光尖锐)。法线越杂乱,表面越粗糙(高光模糊)。

# 双向反射分布函数(BRDF)

在下文中,我们约定:

  • nn 为宏观表面法线
  • vv 为观察方向
  • ll 为光照方向
  • hh 为半矢量(Half-vector),即 normalize(v+l)normalize(v + l)
  • α\alpha 为粗糙度参数(通常在引擎中定义为 α=roughness2\alpha = roughness^2

# Cook-Torrance BRDF 模型

为了在着色器中模拟微小镜面这种现象,我们通常使用 Cook-Torrance BRDF 模型。
其镜面反射部分由三个关键函数组成:

fs=DGF4(nl)(nv)f_s = \dfrac{D \cdot G \cdot F}{4(n \cdot l)(n \cdot v)}

# 法线分布函数(Normal Distribution Function, NDF)

它描述了有多少比例的微平面法线正好对准了半矢量(Half-vector, h),从而能将光线反射到观察者眼中。这是最关键的部分。主流算法:GGX (Trowbridge-Reitz)。它在处理高光边缘时有非常漂亮的拖尾效果,是目前游戏行业的标配。
计算方法:

D=α2π((nh)2(α21)+1)2D = \dfrac{\alpha^2}{\pi((n \cdot h)^2(\alpha^2 - 1) + 1)^2}

# 几何函数(Geometry Function)

它描述了微平面之间的相互遮挡,表现为更窄小的高光峰值点,以及更长的衰减弥散,这让材质的高光看起来更加的真实。遮蔽描述了微平面挡住了反射给观察者的光。阴影描述了微平面挡住了入射的光。如果没有 G 项,粗糙表面在掠射角会显得异常明亮,不符合能量守恒。主流算法:Smith-GGX 高度相关几何遮蔽、可见性函数 V_Smith

Smith-GGX 高度相关几何遮蔽:传统的 Smith 几何函数假设遮蔽和阴影是独立的。但在现实中,如果一个点从观察方向被遮挡了,它从光照方向被遮挡的概率也会更高。高度相关版本修正了这一点。

G=2(nl)(nv)(nv)(nl)2(1α2)+α2+(nl)(nv)2(1α2)+α2G = \dfrac{2(n \cdot l)(n \cdot v)}{(n \cdot v)\sqrt{(n \cdot l)^2(1 - \alpha^2) + \alpha^2} + (n \cdot l)\sqrt{(n \cdot v)^2(1 - \alpha^2) + \alpha^2}}

可见性函数 V_Smith
在 Cook-Torrance BRDF 公式中,分母通常带有 4(nl)(nv)4(n \cdot l)(n \cdot v)。为了优化计算,我们会将 G 项与之合并,定义为 Visibility Term (V)。使用上述高度相关 G 项后,V 项可以简化。

V=G4(nl)(nv)=0.5(nv)(nl)2(1α2)+α2+(nl)(nv)2(1α2)+α2V = \dfrac{G}{4(n \cdot l)(n \cdot v)} = \dfrac{0.5}{(n \cdot v)\sqrt{(n \cdot l)^2(1 - \alpha^2) + \alpha^2} + (n \cdot l)\sqrt{(n \cdot v)^2(1 - \alpha^2) + \alpha^2}}

注意:使用 V_Smith 时,BRDF 模型中的分母会被约掉,此时计算方法变为:

fs=DVFf_s = D \cdot V \cdot F

UE4 的 GGX-Smith Correlated Joint 近似方案

V=0.5(nl)((nv)(1α)+α)+(nv)((nl)(1α)+α)V = \dfrac{0.5}{(n \cdot l)((n \cdot v)(1 - \alpha) + \alpha) + (n \cdot v)((n \cdot l)(1 - \alpha) + \alpha)}

Unity HDRP 的 GGX-Smith Correlated Joint 近似方案

β=roughness\beta = roughness

V=0.5(nl)((nv)(1β)+β)+(nv)(nl)2(1β2)+β2V = \dfrac{0.5}{(n \cdot l)((n \cdot v)(1 - \beta) + \beta) + (n \cdot v)\sqrt{(n \cdot l)^2(1 - \beta^2) + \beta^2}}

# 菲涅尔方程(Fresnel Equation)

描述了光线在不同角度下反射与折射的比例。几乎所有物体在接近 90° 观察时,反射率都会急剧上升。对于粗糙的表面,反射会更加地明显,但不会完全达到 100% 高光反射。反射的效果受每个微面元的法线与光的角度影响,而非取决于整个宏观面的法线与光的角度。表面粗糙时,光线被微面元进行不同角度的弥散反射,所以整个反射效果看起来会更加柔和。
常用近似:Schlick 近似。

F0=lerp(0.04,albedo,metallic)F_0 = lerp(0.04, albedo, metallic)

F=F0+(1F0)(1(hv))5F = F_0 + (1 - F_0)(1 - (h \cdot v))^5

F0F_0 是材质的基础反射率(垂直入射时的反射率),albedoalbedo 是反照率(通常为纹理采样值),metallicmetallic 是金属度。在游戏引擎中,电介质(绝缘体)的 F0F_0 通常硬编码为 0.040.04,而金属(导体)的 F0F_0 则是其自身颜色,或者像本文这样用金属度影响菲涅尔反射率。

# BRDF 与贴图的叠加计算

计算方式如下:

specular=fs=DVFspecular = f_s = D \cdot V \cdot F

kd=(1F)(1metallic)kd = (1 - F)(1 - metallic)

diffuse=kdalbedoπdiffuse = \dfrac{kd \cdot albedo}{\pi}

brdf=(diffuse+specular)(nl)brdf = (diffuse + specular)(n \cdot l)

关于 kdkd
1F1 - F 是为了排除镜面反射。FF 代表了光线被镜面反射的比例,根据能量守恒,剩下的 1F1 - F 就是进入物体表面的光线比例。
1metallic1 - metallic 是为了考虑金属度。对于纯金属 (metallic=1metallic = 1),kdkd 会变为 00。在 PBR 理论中,金属的所有漫反射颜色都会被吸收,它们只显示镜面反射的颜色(通常是受金属色调影响的 FF)。对于非金属 (metallic=0metallic = 0),kd=(1F)kd = (1 - F)。除了被镜面反射的那部分光,剩下的全部参与漫反射计算。
如果没有这个系数,当菲尼尔效应很强时(例如在掠射角观查物体),镜面反射 fsf_s 会非常大,如果此时漫反射依然保持满额强度,物体反射出的总能量就会超过入射能量,导致渲染出来的边缘看起来过亮且不真实。

关于 π\pi
在纯物理公式中,漫反射需要除以 π\pi 来保证能量守恒。但在 Unity 以及大多数游戏引擎中,光源的强度通常已经隐含了 π\pi 的补偿。如果你手动除以 π\pi,物体的亮度会下降。所以,是否除以 π\pi 要根据引擎的情况决定。

# 色彩空间

# 线性空间

大多数贴图和屏幕默认都在 sRGB 空间。sRGB 是一种带 Gamma 校正的颜色空间。简单说,它对暗部更敏感,对亮部压缩得更厉害。这是为了适应人眼的感知。但问题是光的物理叠加是线性的,而 sRGB 不是。
如果在 sRGB 空间里直接做光照计算,就像拿一把弯尺子去量直线。比如两盏灯叠加,本该 0.2 + 0.2 = 0.4,但在伽马空间里加出来会偏亮或偏暗。阴影会发灰,高光会错误。
线性空间渲染的核心思想:先把贴图从 sRGB 转成线性空间(去除 Gamma),在真实线性里做所有光照、BRDF、能量守恒计算,最后输出到屏幕前再做一次伽马校正。这是把感知空间还原回物理空间。

数学上常见近似是:linear=srgb2.2linear = srgb^{2.2} \kern 0.1pt

现代引擎(比如 Unity 和 Unreal Engine)默认都推荐线性工作流。尤其是在做 PBR(基于物理的渲染)时。

举例:在 Gamma 模式下,把两个 50% 灰叠加,结果比你预期亮很多。在线性空间里,才是物理正确的叠加。

真实世界是线性的,人脑不是,显示器也不是。

# ACES 色彩空间

ACES 的全名是 Academy Color Encoding System。它是 Academy of Motion Picture Arts and Sciences 推出的电影工业色彩管理体系。目的不是更好看,而是跨设备一致。
电影制作里有个问题:摄影机拍出来一个色域,特效软件一个色域,影院投影仪又一个色域。如果没有统一标准,调色师会崩溃。

ACES 的核心思想

  • 第一层:超大色域
    • ACES 使用的 AP0 / AP1 色域远大于 Rec.709 或 sRGB。它甚至包含人眼理论可见范围之外的颜色。这不是为了显示,而是为了中间计算不丢数据。就像用 32 位浮点做中间结果一样。
  • 第二层:线性 + 高动态范围
    • ACES 默认是线性空间,并且支持非常高的动态范围(HDR)。这让高光不会轻易裁切。
  • 第三层:RRT + ODT
    • 它把场景值通过 RRT(Reference Rendering Transform)和 ODT(Output Device Transform)映射到具体设备。
    • 场景色 -> ACES 色彩空间 -> 电影风格映射 -> 显示设备

ACES 看起来电影感更强。因为它的高光处理不是简单压缩,而是带一点色彩偏移。亮部会微微偏暖或偏冷,这更接近真实胶片响应。胶片在高曝光时不是纯白,而是带色温倾向。

游戏引擎里常说的 ACES Tonemapping,其实是对电影版本的简化实现。比如 Unreal Engine 默认就用了 ACES 风格的色调映射曲线。相比传统 Reinhard,它高光滚降更自然,颜色饱和度保持更好。
游戏引擎中的 ACES 流程通常是:sRGB 贴图 -> 转线性 -> 光照计算(线性空间)-> HDR buffer -> ACES tone mapping -> 输出到 sRGB 显示器

线性空间 与 ACES 不是对立关系,线性空间解决的是物理正确的计算,ACES 解决的是跨设备一致和电影级色调映射。

另外:如果未来显示器全面进入 HDR 和 Rec.2020,ACES 体系的优势会更明显,因为它本来就是为高动态范围设计的。

# PBR 的核心属性

  • 能量守恒定律
    • 一个表面反射光的量少于它接收到的光的量。听上去像废话,但早期光照模型常常违背这一点。
    • 在现代 PBR 中,漫反射(diffuse)和镜面反射(specular)会共享一份能量预算。金属度(metallic)和粗糙度(roughness)就是调度参数。金属几乎不产生漫反射,非金属则把部分能量分给漫反射,剩下的给镜面反射。BRDF 被设计成积分不超过 1,保证总反射能量不超标。
  • 菲涅尔效应
    • 对于大多数非导体(电介质)材质来说,它的 F0F_0 反射值不会有太大的变化,普遍分布在 2%5%2\%-5\% 之间。而对于金属材质来说,反射值更高,范围在 70%100%70\%-100\% 之间。
  • 高光反射
    • 高光反射的强度由以下几个属性共同影响:BRDF 算法、不同工作流下的粗糙度或光泽度贴图、F0F_0 的反射值。
  • 线性空间
    • 光的计算都在线性空间中执行。所有含色彩信息的贴图通常都会被着色器转换成 Linear 用于计算。