【PBRT】《基于物理的渲染:从理论到实践》之辐射学

LED显示器的光谱

从颜色属性到光谱

在过往所学的渲染中,物体总有一个颜色属性,表示物体发出或者反射的是什么光,比如应用最广泛的冯氏着色模型。但是,现实世界中,物体表面的物理性质不是这样的,这就要涉及到一个概念:光谱。

光谱是物体表面发出或者反射的所有波长的电磁波的图谱。真实的物理情况是,当一束白光找到物体表面时,物体会反射对各个波长的光都反射,只是不同的波长反射力度不一样。比如下面这个是柠檬的表面光谱:


光谱是连续的,意味着它有无限的维度。计算机无法表示无限的光谱,所以要有一个功能把无限的维度降低到有限维度。PBRT使用Spectrum类来实现这功能。它的主要功能是,对输入的光谱数据进行采样,用波长和系数c_i来表示特定波长的反射量,模拟连续的光谱。在PBRT中,Spectrum类可能是SampledSpectrum,或者RGBSpectrum。这两个类有一个共同的基类CoefficientSpectrum,用来提供算术运算。 SampledSpectrum类和RGBSpectrum类的最重要的函数是FromSampled,用来从外部接收数据,计算系数c_i

辐射学

接着进入辐射学的内容。这是比光谱更底层的基础物理知识。光也是一种电磁波,而所有的物体都会一直进行电磁辐射,就是向外不断发出不同波长的电磁波。比如电影中经常看到的用红外望远镜可以在晚上还看到人。电磁辐射,伴随着发出能量,发出的总能量和发射面积以及持续时间有密切的关系。辐射学就是研究这些关系,然后运用一些物理定律,计算表面上某个点能接收到的能量,从而显示颜色。最重要的性质有两个,一个是线性性质,就是两种光叠加上去总亮度就是相加。另一个是能量守恒。接收到的光照能量值要大于等于反射出的能量值,因为可能会有一部分被吸收。

接着,我们进入辐射学基本物理量的学习。

辐射能量Q

辐射能量Q,表示一定时间内,表面的一定区域所接收(或者发出,或者透过)的所有能量总和。

我们的物理量如果不加下标,表示的就是接收、发出、或者透过。要区分的话,会专门用下标表示,比如Q_i表示接收的能量值。下面再介绍物理量的时候就省略括号中的内容了。

辐射通量\Phi

辐射通量(radiant flux,\Phi),表示单位时间内,表面的特定区域接收到的能量和。计算的公式是:\Phi=\frac{dQ}{dt}

辐射照度E

辐射照度(irradiance, E),表示某个点(微面元)接受来自各个方向的辐射通量大小。计算公式是:E=\frac{d\Phi}{dA}。注意,这里的单位面积其实是微面元的概念,就是某一个点附近很小很小的一块区域,其实就跟点差不多,可以理解成比点稍微大一点的一个圆或者正方形。但是在表示这个微面元的时候,就是用点的位置来表示。知道E之后可以反推\Phi的大小,利用下面这个积分公式:\Phi=\int_{S}EdA

辐射强度I

辐射强度(radiant intensity, I),表示某块区域,接受来自某个方向的辐射通量大小。I和E的区别是,E是对面积进行微分,I是对方向进行微分。其计算公式是:I=\frac{d\Phi}{d\omega},其中,\omega就是立体角。

立体角

立体角的概念是这样的,在空间中有一个闭合曲线构成的曲面,然后空间中还有一点P。画闭合曲线和点P的直线,在以点P为中心的单位球上,曲面映射到单位球上的面积就是曲面关于点P的立体角(或者叫球面度),立体角的计算公式是:\omega=\frac{S}{R^2},其中S是投影面积,R是球半径。当我们使用单位球的时候,立体角就是面积。为了方便表述,给立体角一个单位sr,单位名称是球面度。

立体角

辐射亮度L

辐射亮度(radiance, L),表示来自某个方向(立体角)的辐射通量,照射到表面上的一个点(微面元)投影到该方向垂直平面上的辐射通量大小。如下图所示:

辐射亮度L

计算公式是:

注意,书上关于L的公式是错的!

按照辐射亮度的定义,这必然是一个二重微分,对方向和面积的双重微分。这个\cos\theta的值是从哪来的?\theta表示表面法线和方向\omega的夹角,换个角度思考就是微面元dA投射到与\omega垂直方向的表面的面积。L是一个非常重要的概念,有了L之后,我们可以很方便地计算出I和E。公式如下:
\begin{cases} L=\frac{d}{d\omega\cos\theta}(\frac{d\Phi}{dA})=\frac{dE}{d\omega\cos\theta}\\ L=\frac{d}{dA\cos\theta}(\frac{d\Phi}{d\omega})=\frac{dI}{dA\cos\theta} \end{cases}
\begin{cases} E = \int_{\Omega}L\cos\theta d\omega \\ I=\int_{S}L\cos\theta dA \end{cases}
完美。

关于L的计算实例


假设我们要求整个半球的辐射照度E,如上图所示:使用球坐标系来计算,值表示与z轴正方向的夹角,表示与x轴正方向的夹角。我们用的公式是,关键在于如何表示立体角。

还记得吗?立体角是单位球的面积,我们直接对半球的面积积分就好了。方法是这样:


首先,在球坐标系中表示一个点是(r,\theta,\phi),r是球半径,\theta是与z轴正方向的夹角,\phi是与x轴正方向的夹角。\theta的范围是(0,\pi)\phi的范围是(0,2\pi)。所以,当要求半球的辐射照度E时,对\theta的积分区域是(0,\frac{\pi}{2}),而\phi的积分区域是(0,2\pi)

对立体角微元来说,因为立体角本身就是面积,所以我们只要表示一个微面元就可以了,我们采用长方形的表示方式,这样可以铺满整个半球,并且其面积计算公式简单。在微面元的情况下,有一点弯曲的长方形曲面和没有弯曲的长方形的面积是一样的,所以,微面元的面积可以表示成:d\omega=\sin\theta d\theta d\phi,正如上面的图所显示的那样。

d\thetad\phi是角度的微元增量,为什么还有\sin呢?因为当\phi增加了一定值后,它所对应的弧长增加值是角度乘以半径。而(\theta,\phi)点所对应的半径是图中的\sin\theta。于是,半球的辐射照度E是:
E=\int_{0}^{2\pi}\int_{0}^{\frac{\pi}{2}}L\cos\theta\sin\theta d\theta d\phi

上述的公式就是半球辐射照度,弄懂了之后感觉非常简单。

反射模型

BRDF

BRDF全称bidirectional reflectance distribution function,中文翻译成双向反射分布函数。描述的是表面上某一点(微面元),接收到入射光线与该点反射光线之间的相互关系。

为了区分反射和入射,与入射相关的物理量会加小标i,与反射相关的物理量会加小标o。用L_i表示入射亮度,用L_o表示反射亮度。还是从这个公式开始推理:
E_i = \int_{\Omega}L_i\cos\theta_i d\omega_i

两边取微分可以得到dE_i = L_i\cos\theta_i d\omega_i,表示某个方向的照度值。而根据能量守恒定律我们知道,反射的亮度L_o不可能超过入射亮度。根据线性性质还可以知道它和入射亮度之间还有比例关系,入射亮度越大,反射亮度越大,即:dL_o\propto dE_i。于是,我们可以列出这样一个式子:
f_r=\frac{dL_o}{dE_i}
即:反射亮度与入射亮度有一定比例关系。

将这个式子代入到之前的式子中得到
dL_o=f_r L_i\cos\theta_i d\omega_i
于是L_o的值就是:
L_o=\int_{\Omega}f_rL_i\cos\theta_i d\omega_i
这是PBR计算的基本公式之一。

BSSRDF

BSSRDF,全称是bidirectional scattering surface reflectance distribution function,中文翻译成双向散射表面反射分布函数。它是比BRDF模型更贴近现实的计算模型现实中,我们的表面总是会有一定的深度,当光从一面进入的时候,在里面不断反射,然后从另一个地方出来,才是更真实的物理模型。


BSSRDF模型

由于散射的存在,某一个点的反射亮度是和整个表面所接收到的通量挂钩的。整个表面接收的的通量就是\Phi,于是,表面上一点的反射亮度与通量的关系是:S=\frac{dL_o}{d\Phi}
展开可得L_o的完整计算公式:
L_o=\int_{A}\int_{\Omega}SL_i\cos\theta_i d\omega_i dA

要说复杂也复杂,说简单也简单,理解了就好。

总结

欢迎评论!

参考资料:
Physically Based Rendering
pbrt源码,版本3
Introduction to Radiometry and Photometry