读书笔记17《Unity Shader入门精要》

铁名_IronName Lv4

第 18 章 基于物理的渲染

基于物理的渲染技术(Physically Based Shading,PBS) 是对光和材质之间的行为进行更加真实的建模。

PBS 的理论和数学基础

Naty Hoffman 在 SIGGRAPH 2013 做的名为 Background:Physic and Math of Shading

  • 菲涅耳等式(Fresnel equations):光在介质边界反射和折射的比例
  • 微表面模型
  • 次表面散射光(subsurface-scattered light)
  • 次表面散射渲染技术:如果次表面散射产生的位置偏移较大,那么需要特殊的渲染模型来实现更真实的次表面散射效果。

双向反射分布函数(BRDF)

  • 辐射率(radiance):单位面积、单位方向上光源的辐射通量,通常用 L 来表示。
  • 着色(shading):用入射辐射度 LiL_i 计算出射辐射度 LoL_o
  • 双向反射分布函数(Bidiretional Reflectance Distribution Function, BRDF):用于定量分析物体表面一点是如何和光进行交互的。大多数情况下,BRDF 可以用 f(I,v)f(\textbf{I},\textbf{v}) 来表示,其中 I\textbf{I} 是入射方向,v\textbf{v} 是观察方向(这是“双向”的由来)。
  • 各向同性(isotropic)的 BRDF:绕着表面法线选择入射方向或观察方向不会影响 BRDF 的结果。
  • 各向异性(anisotropic)的 BRDF:和前者相反。
  • 反射等式(reflection equation):该方向上的出射辐射率等于所有入射方向的辐射率积分乘以它的 BRDF 值,再乘以一个余弦值。渲染方程的一个特殊情况;基于物理基础的
Lo(v)=Ωf(I,v)×Li(I)(nI)dωiL_o(\textbf{v})=\int_\Omega f(\textbf{I},\textbf{v})\times L_i(\textbf{I})(\textbf{n}\cdot\textbf{I})d\omega_i
  • 精确光源(punctual light sources):方向确定、体积无限小。用 Ic\textbf{I}_c 表示它的方向,clightc_{light} 表示它的颜色。用精确光源可以大大简化反射等式:
Lo(v)=πf(Ic,v)×clight(nIc)L_o(\textbf{v})=\pi f(\textbf{I}_c, \textbf{v})\times c_{light}(\textbf{n}\cdot \textbf{I}_c)
  • 着色过程是否是基于物理的,要看:BRDF 是否满足交换律(reciprocity)和能量守恒(energy conservation)。即:
f(Ic,v)=f(v,Ic)f(\textbf{I}_c,\textbf{v})=f(\textbf{v},\textbf{I}_c) I,Ωf(I,v)(nI)dωo1\forall I,\int_\Omega f(\textbf{I},\textbf{v})(\textbf{n}\cdot\textbf{I})d\omega_o \le 1

表面反射的能量不能超过入射的光能。

漫反射项(diffuse term)

前面学习的 Lambert 模型是最简单、应用最广泛的漫反射 BRDF。准确的 Lambertian BRDF 的表示为:

fLambert(I,v)=cdiffπf_{Lambert}(\textbf{I},\textbf{v})=\frac{\textbf{c}_{diff}}{\pi}

其中,cdiff\textbf{c}_{diff} 表示漫反射光线所占的比例,也通常被称为漫反射颜色(diffuse color)。

Lambert 漫反射公式是 Lambertian BRDF 在理想漫反射和特定光照模型(如点光源)假设下,为计算最终“观测亮度”而推导出的一个简化、实用的特例。

给定入射方向 I\textbf{I} 的光源在表面某点的出射漫反射辐射率为:

Ldiff=cdiffπ×Li(I)(nI)L_{diff}=\frac{\textbf{c}_{diff}}{\pi}\times L_i(\textbf{I})(\textbf{n}\cdot\textbf{I})

Disney 使用的 BRDF 中的漫反射项:

fdiff(Iv)=baseColorπ(1+(FD901)(1nI)5)(1+(FD901)(1nv)5)f_{diff}(\textbf{I}\cdot\textbf{v})=\frac{baseColor}{\pi}(1+(F_{D90}-1)(1-\textbf{n}\cdot\textbf{I})^5)(1+(F_{D90}-1)(1-\textbf{n}\cdot\textbf{v})^5)

其中,FD90=0.5+2roughness(hI)2F_{D90}=0.5+2roughness(\textbf{h}\cdot\textbf{I})^2baseColorbaseColor 是表面颜色,通常通过纹理采样得到; roughnessroughness 是表面的粗糙度。这个漫反射项考虑了在掠射角(glancing angles)
的能量变化,和表面的粗糙度。这也是 Unity 5 内部使用的漫反射项。

视线方向 V 与表面法线 N 的夹角接近90度时,就处于掠射角观察条件

高光反射项(specular term)

  • 微面元理论(microfacet theory):微面元理论认为,物体表面实际是由许多人哏看不到的微面元组成的,虽然物体表面并不是光学平滑的,但这些微面元可以被认为是光学平滑的,也就是说它们具有完美的高光反射。
fspec(I,v)=F(I,h)G(I,v,h)D(h)4(nI)(nv)f_{spec}(\textbf{I},\textbf{v})=\frac{F(\textbf{I},\textbf{h})G(\textbf{I},\textbf{v},\textbf{h})D(\textbf{h})}{4(\textbf{n}\cdot\textbf{I})(\textbf{n}\cdot\textbf{v})}

这是著名的 Torrance-Sparrow 微面元模型。D(h)D(\textbf{h}) 是微面元的法线分布函数(normal distribution function,NDF),用于计算有多少比例的微面元的法线 m 满足 m=h=I+v2m=h=\frac{\textbf{I}+\textbf{v}}{2} ,只有这部分微面元会把光线从 I 方向反射到 v 上。 G(I,v,h)G(\textbf{I},\textbf{v},\textbf{h}) 是阴影—遮掩函数(shadowing-masking function),用于计算那些满足 m=hm=h 的微面元中有多少会由于遮挡而不会被人眼看到,它给出了活跃的微面元(active microfacets)所占比例。F(I,h)F(\textbf{I},\textbf{h}) 是这些活跃微表面的菲涅耳反射(Fresnel function)函数,给出了反射光线的占比。 最后,4(nI)(nv)4(\textbf{n}\cdot\textbf{I})(\textbf{n}\cdot\textbf{v}) 是用于矫正从微面元的局部空间到整体宏观表面数量差异的矫正因子。

这些函数的不同可以衍生出很多不同的 BRDF 实现。之前学习的 Blin-Phong 模型的法线分布函数 D(h)=(n,h)glossD(\textbf{h})=(\textbf{n},\textbf{h})^{gloss} 。除此之外还有很多更加复杂的法线分布函数 GGX、Beckmann 等。阴影遮蔽函数 G(I,v,h)G(\textbf{I},\textbf{v},\textbf{h}) 也有 Smith 模型等。

  • 在让美工人员直观地调整参数,和具有物理可信度之间找到平衡点。

Unity 中的 PBS 实现

漫反射项

fdiff(Iv)=baseColorπ(1+(FD901)(1nI)5)(1+(FD901)(1nv)5)f_{diff}(\textbf{I}\cdot\textbf{v})=\frac{baseColor}{\pi}(1+(F_{D90}-1)(1-\textbf{n}\cdot\textbf{I})^5)(1+(F_{D90}-1)(1-\textbf{n}\cdot\textbf{v})^5)

其中,FD90=0.5+2roughness(hI)2F_{D90}=0.5+2roughness(\textbf{h}\cdot\textbf{I})^2

高光反射项

  • GGX 模型的法线分布函数,其中 a=roughness2a=roughness^2
DGGX=a2π((a21)(nh)2+1)2D_{GGX}=\frac{a^2}{\pi((a^2-1)(\textbf{n}\cdot\textbf{h})^2+1)^2}
  • 阴影-遮蔽函数是由 GGX 衍生出的 Smith-Schlick 模型,其中 k=roughness22k=\frac{{roughness}^2}{2}
G(I,v,h)=(nI)(nv)((nI)(1k)+k)((nv)(1k)+k)G(\textbf{I},\textbf{v},\textbf{h})=\frac{(\textbf{n}\cdot\textbf{I})(\textbf{n}\cdot\textbf{v})}{((\textbf{n}\cdot\textbf{I})(1-k)+k)((\textbf{n}\cdot\textbf{v})(1-k)+k)}

书上给的好像不准确。

  • 菲涅耳反射则使用图形学经典 Schlick 菲涅耳近似等式,其中 F0F_0 是高光反射系数,或者说是高光反射颜色
F(I,h)=F0+(1F0)(1Ih)5F(\textbf{I},\textbf{h})=F_0+(1-F_0)(1-\textbf{I}\cdot\textbf{h})^5

Unity 5 的 Standard Shader

  • 金属工作流(Metallic workflow)——对应Shader:Standard
  • 高光反射工作流(Specular workflow)——对应Shader:Standard(Specular setup)

它们是如何实现的

源代码可以在 Unity 内置的 builtin_shaders 之类的文件夹中寻找。

如何使用

  • Unity 官方提供的示例项目 Shader Calibration Scene 中有两张非常有参考价值的校准表格
  • 基于物理的渲染需要使用线性色彩空间
  • Unity 对 Standard Shader 进行了高度优化,会自动检查哪些属性没有用到,也会针对目标平台进行相应的优化。

一个更加复杂的例子

  • 全局光照(Global Illumination,GI)流水线
  • 反射探针(Reflection Probes):在特定的位置上对整个场景的环境反射进行采样
  • 使用 Unity 内置的反射探针可以模拟互相反射

答疑解惑

什么是全局光照

全局光照不仅考虑直接光照,还计算间接光照。光线追踪能得到非常出色的画面效果,但性能低,故多用于电影制作中。Unity 采用 Enlighten 解决方案(实时+预计算)来提高全局光照的性能,这个解决方案也被集成在虚幻引擎(Unreal Engine)中。
预计算实时全局光照(Precomputed Realtime GI):预计算物体之间的关系,然后实时计算光照。

什么是伽马矫正

Unity 默认是伽马空间,在伽马空间下进行渲染会导致很多非线性空间下的计算,从而引
入了一些误差。而要把伽马空间转换到线性空间,就需要进行伽马校正(Gamma Correction)
通常,伽马曲线的表达式为 Lout=LinγL_{out}=L_{in}^{\gamma}γ\gamma 就是(编码)伽马。

最开始的时候,人们使用伽马曲线来对拍摄的图像进行伽马编码(gamma encoding) 。事情的起因可以从在真实环境中拍摄一张图片说起。摄像机的原理可以简化为,把进入到镜头内的光线亮度编码成图像(例如一张JEPG ) 中的像素。如果采集到的亮度是 0, 像素就是 0;亮度是1 , 像素就是1;亮度是 0.5, 像素就是 0.5。如果我们只用 8 位空间来存储像素的每个通道的话,这意味着 0~1 区间可以对应 256 种不同的亮度值。但是,后来人们发现,人眼有一个有趣的特性,就是对光的灵敏度在不同亮度上是不一样的。在正常的光照条件下,人眼对较暗区域的变化更加敏感。
如果使用 8 位空间来存储每个通道的话,我们仍然把 0.5 亮度编码成值为 0.5 的像素,那么暗部和亮部区域我们都使用了128 种颜色来表示,但实际上,对亮部区域使用这么多颜色是种存储浪费。一种更好的方法是,我们应该把把更多的空间来存储更多的暗部区域,这样存储空间就可以被充分利用起来了 。

  • 显示伽马(display gamma)来自于早期CRT(Cathode Ray Tube,阴极射线管)输入电压和屏幕亮度的非线性关系。
  • sRGB 颜色空间标准,推荐显示器的显示伽马值为 2.2,配合 0.45 的编码伽马可以保证最后伽马曲线之间相互抵消。
  • 如果不对渲染结果进行处理,那么经过显示伽马处理后,图像整体会偏暗。
  • 伽马的存在还会影响混合。
  • 使用多级渐远纹理(mipmaps)的采样是线性的(对某个方形区域内的像素取平均值),所以需要把非线性的纹理转换到线性空间。
  • 伽马校正应该发生在渲染的最后一步中。

什么是HDR

HDR 是 Hight Dynamic Range 的缩写,即高动态范围。与之相对的是低动态范围(Low Dynamic Range,LDR)。HDR 使用远高于 8 位的精度记录亮度信息,可以表示超过 0-1 的亮度值,更加精确地反映真实的光照环境。即使最后还是需要把信息转换到显示设备使用的 LDR 中,但是中间的计算会更真实可信。
使用 HDR 存储的图像叫做高动态范围图像(HDRI)。HDRI 图像可以用于 场景的 Skybox。

如果我们的场景中有很多光源或是光源强度很大,那么一个物体在经过多次光照渲染叠加后最终得到的光照亮度很可能会超过 1。如果没有使用 HDR,这些超过 1 的部分全部会截取到 1,使得场景丢失了很多亮部区域的细节。但如果开启了 HDR,我们就可以保留这些超过范围的光照结果,尽管最后我们仍然需要把它们转换到 LDR 进行显示,但我们可以使用色调映射(tonemapping)技术来控制这个转换的过程,从而允许我们最大限度地保留需要的亮度细节。

  • 使用 HDR 可以让 Bloom 特效更合理。

扩展阅读

  • 标题: 读书笔记17《Unity Shader入门精要》
  • 作者: 铁名_IronName
  • 创建于 : 2026-02-01 11:48:19
  • 更新于 : 2026-02-15 15:21:15
  • 链接: https://blog.ironname.top/2026/02/01/读书笔记17《Unity-Shader入门精要》/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论