辐射度量学和渲染方程
一、前言
笔者研究生阶段主要从事的是视频、多媒体相关技术的研究和工程实践。
在做播放器的过程,接触了OpenGL的图形API,实现了流媒体播放器的渲染,之后选择了图形相关的工作。
然而,一直没有对图形学相关的基础概念进行一些系统的认识和梳理。
因而总觉得在图形门外,无法深入,找不到进阶的方法。
故而,想把自己觉得需要理解的东西整理成本篇笔记。
会引用到网络上的一些文章,向各位大佬致敬!
二、辐射度量学简述
图形渲染,模拟的是光线与各类材质进行交互的过程。
计算在某个给定时间内,光源发出的所有光线跟场景所有物体表面交互后,进入到眼球视网膜上的光能给人的感受。
如何度量这种人眼的感受呢?
这种感受本质与光的能量有关。那么,我们就需要了解:
- 光线的能量要如何进行度量?
- 光如何转换成为眼睛感受到的颜色?
2.1 光的辐射
这个部分摘自 渲染方程Rendering equation
光是能量的一种传播方式。光能量也被称为光子能量(按粒子性)。
每个光子都具有一定量的能量,频率越高,能量也越高。
辐射中的重要概念有:
- 辐射能(Radiant energy )
- 辐射通量(Radiant flux )
- 辐照度(Irradiance)
- 辐射强度(Radiant Intensity)
- 辐射度(Radiance)
2.1.1 辐射能(Radiant energy ):总击中
如图,Radiant energy:40 hit,表示的是两秒内光子的击中总数。这个数字表达的是捕获到的所有光子的总能量。
其中,每个光子的能量如公式所示:
Q = h c λ Q=\frac{hc}{\lambda} Q=λhc
h为普朗克常数,单位为 j ∗ s j*s j∗s。c为光速,单位为 m / s m/s m/s。
那么hit,其实是单位焦耳(J)。
2.1.2 辐射通量(Radiant flux ):每秒击中
这个概念表示的是:每秒的击中次数,即能量的时间密度。
假设上图为2秒的光子击中数,那么每秒的击中数则为:radiant flux:40 hits/2s = 20 hits/s 。
根据单位有:j/s,即瓦特w。
所以,辐射通量的单位为瓦特。通常用 Φ \Phi Φ 标记。
2.1.3 辐照度(Irradiance):每秒每单位面积的击中
除了知道击中的总数,还需要知道击中发生在哪里。
因此,计算某些“非常小”的区域的每秒的击中量。
除以区域面积,可以理解为辐射通量的面积密度。
则辐照度(Irradiance)的单位为: w / m 2 w/{m^2} w/m2
通常,辐照度(Irradiance)用字母 E 标记。
因此,从这个角度出发,我们在图像生成方面的目标是估计图像中每个点的辐照度(或者每像素的总辐射通量)。
那么,为何图像上会有明暗变化?为什么地球会有四季之分?
可以由以下两图解释:
- 当被照亮的平面,与光线方向垂直:
- 当被照亮的平面,与光线方向存在一定夹角:
由公式可知,当 $\theta $ 越大,则 E E E 越小。
对理想的点光源,假想以点光源为中心不同半径的球包围着点光源,穿过这些球的辐射通量是相同的,均为 Φ \Phi Φ 。
而球的表面积为: 4 π r 2 4 \pi r^2 4πr2,那么球面上的辐照度为:$E=\frac{\Phi }{4\pi r^2} $。
因此可知,辐照度(通量密度)与距离的平方成反比。
离光源越远,通量密度越低,这也是为什么光的衰减与距离的平方成正比。
2.1.4 辐射强度(Radiant Intensity):单位立体角内的辐射功率
在介绍辐射强度(Radiant Intensity)之前,我们首先要了解立体角的概念。
立体角可以看成弧度的三维扩展。
在二维平面上,圆内的角度等于角度对应的弧长除以圆半径。如公式 $\theta = \frac{l}{r} $。
单位圆的周长为 2 π 2\pi 2π。因而,整个圆对应的弧度也是 2 π 2\pi 2π。
单位角,则是度量三维角度的量。
用符号 ω \omega ω 标记。单位为:立体弧度(Steradian,简写为 s r sr sr)。
其值等于立体角在单位球上对应的区域的面积。(实际上也就是在任意半径的球上的面积除以半径的平方,即$\omega=\frac{s}{r^2} $)
单位球的表面积为 4 π 4\pi 4π,则整个球面的立体角也为 4 π 4\pi 4π。
立体角的微分
如图,在球形坐标系下,立体角的微分可以这样按照下面公式求得。
首先,计算得到立体角对应的面积:
KaTeX parse error: No such environment: align* at position 7: \begin{̲a̲l̲i̲g̲n̲*̲}̲ dA =& \left ( …
再根据立体角的定义有:
d
ω
=
d
A
r
2
=
s
i
n
θ
d
θ
ϕ
d\omega = \frac{dA}{r^2} = sin\theta d\theta\phi
dω=r2dA=sinθdθϕ
注: d ω 单 位 立 体 角 , 其 本 质 就 是 一 个 方 向 向 量 。 d\omega单位立体角,其本质就是一个方向向量。 dω单位立体角,其本质就是一个方向向量。
再获得了立体角的微分,我们可以验证单位球对应的立体角:
KaTeX parse error: No such environment: align* at position 7: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \Omega = & \i…
辐射强度(Radiant Intensity),指通过单位立体角的辐射通量。用符号 I I I标记。
I = d Φ d ω I=\frac{d\Phi }{d\omega } I=dωdΦ
单位为: w / s r w/sr w/sr。
其中,对于各向同性的点光源,总的辐射通量 Φ \Phi Φ 。有 Φ = ∫ s 2 I d w = 4 π I \Phi = \int _{s^2} {I}dw = 4 \pi I Φ=∫s2Idw=4πI。
2.1.5 辐射度( radiance ):每单位投影面积、每单位立体角上的辐射通量
我们需要度量一个微小面积表面出发,射向某个微小方向的通量(或来自某个微小方向,照射到某个微小面积表面的通量)。
这个度量的量即为 辐射度是( radiance )。一般用 L L L 标记。
其用公式表示如下:
L ( p , ω ) = d 2 Φ ( p ) d A ⊥ d w = d 2 Φ ( p ) d A d w c o s θ L(p,\omega ) = \frac{d^2\Phi(p)}{dA^\perp dw} = \frac{d^2\Phi(p)}{dA dwcos\theta } L(p,ω)=dA⊥dwd2Φ(p)=dAdwcosθd2Φ(p)
其中, d A ⊥ dA^\perp dA⊥表示微分面积 d A dA dA在光线方向上的投影。
辐射度( radiance )指的是由原点P和方向 ω \omega ω定义的射线的能量(单位时间、单位立体角、单位面积的辐射能)。
- Radiance是渲染里面最重要的一个度量。因为它用微分的方式度量一个被细化的光线携带的能量。是用来描述传感器、摄影机、人眼等受辐射最常见的量,也是最重要的量。 实际上可以看成是我们眼睛看到(或相机拍到)的物体上一点的颜色。
- L ( p , ω ) L(p,\omega ) L(p,ω) 是一个5个自由度的函数, p p p表示光线的起点(终点), ω \omega ω 表示方向。
- 同时,Radiance还有一个重要特性,即它不随位置变化,真空下,L的强度在传播的路径点是不变的。
2.2 光与颜色
经过 2.1 中的介绍,我们了解了关于光的辐射的相关基础概念。
那么,光的辐射如何与我们常说的颜色联系到一起呢?
这个部分摘自 从真实世界到渲染
在辐射度量学中的量都以物理的方式进行描述,但其实人眼只能看到波长在400nm-700nm波长的电磁波。
因而,需要单独用来描述人眼感知的光学量。
光度学中的量其实是跟辐照学中的量是一一对应的,如下图表示。
2.2.1 辐射量和光学量的转换
人眼作为一个探测器,输入的是辐射量表示的可见光辐射,输出感受值的光学量。
辐射能到发光能的转换可以表示为:
Φ v = 683.002 l m / w ⋅ ∫ 0 ∞ y ‾ ( λ ) Φ e , λ d λ \Phi _v = 683.002lm/w \cdot \int_{0}^{\infty}\overline{y}(\lambda ) \Phi _{e,\lambda }d\lambda Φv=683.002lm/w⋅∫0∞y(λ)Φe,λdλ
其中:
- Φ e , λ \Phi _{e,\lambda } Φe,λ 是光功率谱的分布,单位为: W / n m W/nm W/nm
- y ‾ ( λ ) \overline{y}(\lambda ) y(λ)是光度函数,没有单位;
- λ \lambda λ是波长,单位为nm;
光在不同波长上的分布,叫做光谱功率分布(spectral power distributions/SPD)。
如下图所示:三个不同的SPD。
- 第一个是单色光,第二个是混合光,第三个是户外自然光。
光度函数,如下图所示:
2.2.2 CIE标准色度学系统
自然界的光照有复杂的SPD,但人眼的颜色感受细胞其实只有三种,分别为红绿蓝三种颜色。
所以,可以将复杂的光谱功率分布转为RGB表示即可。
根据CIE-RGB标准,指定三原色 r ( 654 n m ) , g ( 526 n m ) , b ( 444 n m ) r(654nm),g(526nm),b(444nm) r(654nm),g(526nm),b(444nm),用下面的光谱映射函数和SPD求内积,来将一个任意的SPD表示为三个刺激值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cuvl5YaD-1623923864604)(images/wavelengthRGB.jpg)]
注意:为什么r值会有负数?
根据加法混色原理,亮度是累加的,如果需要亮度比较低,就可能需要减少一些光,也就是负值了。
但是这种方式得到的值有负数,不便于计算,也很难理解。
因此,又有了CIE-XYZ系统。将SPD通过内积转换为三个数字XYZ三刺激值。
- XYZ三原色,是为了避免CIE-RGB系统中的三刺激值和色度坐标值出现负值而虚构出来的三原色。
- XYZ其实是对RGB的简单线性变换。
KaTeX parse error: No such environment: align* at position 7: \begin{̲a̲l̲i̲g̲n̲*̲}̲ X= & \int_{3…
人们为了单纯讨论颜色的色度,会把颜色中的光度变量解耦出去,单纯的讨论没有亮度概念的色度。
再定义了:
KaTeX parse error: No such environment: align* at position 7: \begin{̲a̲l̲i̲g̲n̲*̲}̲ x= & \frac{X…
将z值忽略,用x和y值做出一张图,即CIE色度图(hromaticity diagram)。
RGB色域有很多种,sRGB(这里指的是线性sRGB),是显示器中最常见的色域,也是目前绝大部分实时渲染中用到的色域。
尽管从严格意义上来说RGB颜色并不能完全反映真实世界中物体对光SPD的反馈。
但是在绝大多数情况下效果都是非常不错的,目前只有少部分工业级电影的离线渲染使用频谱渲染。
三、渲染方程
3.1 渲染方程
渲染方程(这里其实指的是反射方程),通过公式的形式定义了图形渲染如何进行求解:
L 0 ( p , ω o ) = L e ( p , ω o ) + ∫ Ω f r ( p , ω i → w o ) L i ( p , ω i ) c o s θ d ω i L_0(p,\omega _o) = L_e(p,\omega _o)+\int_{\Omega }^{} f_r(p,\omega _i \to w_o)L_i(p,\omega _i)cos\theta d\omega _i L0(p,ωo)=Le(p,ωo)+∫Ωfr(p,ωi→wo)Li(p,ωi)cosθdωi
其中:
- L o ( p , ω 0 ) L_o(p,\omega_0) Lo(p,ω0):表示的是P点沿 ω o \omega_o ωo方向出射的总Radiance(辐射度),通常 ω o \omega_o ωo就是摄像机的观察方向;
- L e ( p , ω o ) L_e(p,\omega_o) Le(p,ωo):表示的P点位置,物体材质自身发射的沿 ω o \omega_o ωo方向的Radiance(辐射度);
- Ω \Omega Ω:表示沿P点法线的上半球;
- f r f_r fr:反射函数,后续会进行介绍。
- L i ( p , ω i ) L_i(p,\omega_i) Li(p,ωi):表示的是沿 ω i \omega_i ωi方向朝P点入射的Radiance(辐射度);
- c o s θ cos\theta cosθ:表示的入射 ω i \omega_i ωi和p点法线方向的余弦值;
为何求解的是L(Radiance)?
因为:
- 符合光的传播特征,光是发散式传播的,Radiance是一个不会随距离变化的量。
- 符合人眼的观察特征,固定Radiance的物体,在任何距离观察亮度总是相同的。
这是符合生活常识的,可以理解为距离距离变远之后,虽然到达人眼的辐射通量比变少了,但相应的形成的像也变小了,所以看到的亮度是不变的。
可由以下数学方法验证:
设距离 r 1 r_1 r1处有一个微面元,面积为 d A dA dA,辐射度为L,人眼瞳孔面积为 S S S,视网膜到瞳孔的距离为 r 2 r_2 r2。
微元表面在瞳孔上形成的立体角为 d ω = d A π r 1 2 d\omega = \frac{dA}{\pi r_1^2} dω=πr12dA,通过瞳孔的辐射通量为 d Φ = d ω L S = d A L S π r 1 2 d\Phi = d\omega L S = \frac{dALS}{\pi r_1^2} dΦ=dωLS=πr12dALS。
设微元表面在视网膜上成像大小为 d A ’ dA’ dA’,有 r 1 2 d A = r 2 2 d A ′ \frac{r_1^2}{dA} = \frac{r_2^2}{dA'} dAr12=dA′r22 ,则 d A ′ = d A r 2 2 r 1 2 dA' = \frac{dAr_2^2}{r_1^2} dA′=r12dAr22。
微元表面在视网膜上成像产生的辐照度 E = d Φ d A ′ = L S π r 2 2 E=\frac{d\Phi}{dA'}=\frac{LS}{\pi r_2^2} E=dA′dΦ=πr22LS。
则 E E E不会随着 r 1 r_1 r1的变化而变化,在不同距离观察的亮度是相同的。
3.2 BRDF(Bidirectional Reflectance Distribution Function)
上述中反射方程中定义了微表面P点沿 ω o \omega_o ωo方向出射的总Radiance的求解方法。
其中,涉及到一个反射函数 f r ( p , ω i → w o ) f_r(p,\omega _i \to w_o) fr(p,ωi→wo) 。
那么这个函数是如何定义的呢?
在实时渲染中,定义其为 f r ( p , ω i → w o ) = d L o ( ω o ) d E ( ω i ) f_r(p,\omega _i \to w_o)=\frac{dL_o(\omega_o)}{dE(\omega_i)} fr(p,ωi→wo)=dE(ωi)dLo(ωo),称作BRDF(双向反射分布函数)。
其中,
- ω i \omega_i ωi 为入射光的方向, ω o \omega_o ωo为出射光的方向。
-
d
L
o
(
ω
o
)
dL_o(\omega_o)
dLo(ωo),表面反射到
ω
o
\omega_o
ωo方向的反射光的微分辐射度(Radiance)。
- L o ( ω o ) L_o(\omega_o) Lo(ωo)表示来自于表面上半球所有方向的入射光线的贡献。
- d L o ( ω o ) dL_o(\omega_o) dLo(ωo)特指来自方向 ω i \omega_i ωi的入射光贡献的反射Radiance。
-
d
E
(
ω
i
)
dE(\omega_i)
dE(ωi) 是表面上来自入射光方向
ω
i
\omega_i
ωi的微分Irradiance。
- E E E表示的是表面接收到的Irradiance,来自上半球所有方向的入射光线的贡献。
- d E ( ω i ) dE(\omega_i) dE(ωi) 特指来自方向 ω i \omega_i ωi的入射光贡献的Irradiance。
表面对不同频率的光反射率可能不一样,因此BRDF和光的频率有关。
在图形学中,将BRDF表示为RGB向量,三个分量各有自己的 f f f函数。
问题:为什么BRDF要定义成Radiance和Irradiance的比值,而不是直接定义为Radiance和Radiance比值?
其中一种解释如下:
从数学的角度出发,对于现实世界中的非光学平面,一束光线射到表面上后,被表面反射到各个方向,其中一个出射方向的光通量只是整个反射光通量极小的一部分,当出射方向立体角趋于0时, lim ω o → 0 d L o L i = 0 \lim_{ \omega_o \to 0} \frac{dL_o}{L_i} = 0 limωo→0LidLo=0,所以在实际计算中使用辐射度(Radiance)和辐射度(Radiance)比值是没有意义的。
而如果分母改成表面上接收到的来自光源方向的微分辐照度(Irradiance),有: d E = L i ( l ) d ω i c o s θ i dE=L_i(l)d\omega _icos\theta _i dE=Li(l)dωicosθi,由于给入射辐射度乘了一个趋于零的微分立体角, d E dE dE的值会小很多,可以理解成二者才是等价无穷小,比值 d L o ( ω o ) d E ( ω i ) \frac{dL_o(\omega_o)}{dE(\omega_i)} dE(ωi)dLo(ωo)才又意义!