前一篇文章里,我们已经把体积渲染里最核心的理论部分过了一遍:从吸收、外散射、内散射和发光 这四种基本行为出发,一步步拼出了辐射传输方程 的基本形式。到了这里,我们总算算是手握理解 BSSRDF 的钥匙,也是时候来揭开它的神秘面纱了。
BSSRDF,全称 Bidirectional Surface Scattering Reflectance Distribution Function ,通常可以翻译为双向表面散射反射分布函数 。和 BSDF 相比,它关心的问题要更复杂一些。BSDF 主要描述的是光线在物体表面发生的反射和折射,而 BSSRDF 则进一步考虑了:光线进入物体表面之后,是否会在内部传播一段距离,再从另一个位置重新射出。
当然,并不是所有材质都会出现这种现象。对于金属、塑料这类主要发生表面反射的材质,BSDF 往往就已经够用了。但对于像皮肤、蜡、牛奶、果冻、大理石 这类具有明显次表面散射 特征的半透明材质,单纯依靠 BSDF 往往很难准确表现它们那种柔和、通透、带有“内部发光感”的外观。而这,正是 BSSRDF 要解决的问题。
一般来说,一个完整的 BSSRDF 往往会被拆成两部分来处理:单次散射 和多次散射 。前者描述的是光进入物体后,经过较少次数散射就离开表面的那部分贡献;后者则对应光在内部经历多次散射后形成的更加平滑、柔和的扩散效果。很多经典模型都会采用类似的拆分思路:先用一个项去抓住主要的能量分布,再用另一个更平滑的项去近似更复杂的传播过程。但是这种精确的拆分往往会伴随着巨大的计算量,因此更多情况下,我们会将单次散射和多次散射整合在一起 ,用一个统一的公式表达。
从理论上说,BSSRDF 的推导是建立在辐射传输方程之上的。经典论文 A practical model for subsurface light transport 对这套推导过程做了非常详细的说明。这篇论文我其实很早就看过一次,当时的感受基本只有一个:完全看不懂。现在回头再看至少已经能稍微看懂一点了(骗你的,其实还是看不懂)。
不过,我们并不打算一头扎进那些冗长而复杂的推导细节里。我们的重点会放在 BSSRDF 最终是怎样被表达出来的,它到底在描述什么,以及这些公式在直觉上该怎么理解 。毕竟,很多时候最有意思的地方恰恰在于:在一整套复杂理论的背后,最后得到的结果反而可以写得相当简洁。尤其对于各向同性介质 ,很多模型甚至还能借助预计算,把 BSSRDF 进一步整理成一种更容易使用的形式,并在渲染中高效应用。
和前两篇文章一样,本文依然会以理论 为主,不会涉及具体的代码实现。
BSSDF的基础理论
在 BRDF 里,我们关心的是:光线打到表面上的某一个点之后,会怎样从这个点反射或折射出去。因此,计算时通常只需要对这个点上的入射半球方向 做积分就够了。
但到了 BSSRDF ,事情就不一样了。因为次表面散射描述的,不再只是“光从哪里来、又从同一个点往哪里走”,而是还要考虑这样一种情况:光线从表面的某个位置进入物体,在内部传播和散射之后,最后从另一个位置重新射出。
这意味着,除了要对入射方向做积分之外,我们还必须进一步把所有可能的入射位置 也一起考虑进去。换句话说,在 BSSRDF 中,我们不仅要做方向积分 ,还要再做一次面积分 :
L ( x o , ω o ) = ∫ A ∫ 2 π S ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) (1) L(\mathbf x_o, \boldsymbol \omega_o) = \int_A \int_{2\pi} S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)\, L(\mathbf x_i,\boldsymbol \omega_i)\, (\mathbf n \cdot \boldsymbol \omega_i)\, \mathrm d \boldsymbol \omega_i\, \mathrm d A(\mathbf x_i) \tag{1}
L ( x o , ω o ) = ∫ A ∫ 2 π S ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) ( 1 )
这里的
S ( x i , ω i ; x o , ω o ) S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)
S ( x i , ω i ; x o , ω o )
就是 BSSRDF 本身。它描述的是:光线以方向 ω i \boldsymbol \omega_i ω i 入射到表面位置 x i \mathbf x_i x i 时,有多少能量会在另一个位置 x o \mathbf x_o x o 处,沿着方向 ω o \boldsymbol \omega_o ω o 出射出来。
论文A practical model for subsurface light transport 给出了
S ( x i , ω i ; x o , ω o ) S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) S ( x i , ω i ; x o , ω o ) 的具体表达形式。正如我们在引言里提到的那样,论文将 BSSRDF 拆成了两部分:多次散射项 和 单次散射项 。
具体来说,可以写成:
S ( x i , ω i ; x o , ω o ) = S d ( x i , ω i ; x o , ω o ) + S ( 1 ) ( x i , ω i ; x o , ω o ) (2) S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) = S_d(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) + S^{(1)}(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) \tag{2}
S ( x i , ω i ; x o , ω o ) = S d ( x i , ω i ; x o , ω o ) + S ( 1 ) ( x i , ω i ; x o , ω o ) ( 2 )
其中,
S d ( x i , ω i ; x o , ω o ) S_d(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)
S d ( x i , ω i ; x o , ω o )
表示的是多次散射项 。它描述的是:光进入物体之后,并不是只在内部“弹”一次就出来了,而是会在介质内部经历多次散射,最后才从表面重新离开。换句话说,这一项统计的是除了第一次散射之外,其余所有散射共同形成的累积效果 。也正因为散射次数很多,这一部分通常会表现得更加平滑、柔和,看起来很像一种“在内部扩散开来”的感觉。
另一部分则是单次散射项 :
S ( 1 ) ( x i , ω i ; x o , ω o ) S^{(1)}(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)
S ( 1 ) ( x i , ω i ; x o , ω o )
顾名思义,它描述的是光线进入物体之后,只经历一次散射 就重新离开表面的那部分分布。和多次散射相比,单次散射通常保留了更多“方向性”,因此在一些材质上会带来更清晰、更锐利的视觉特征。
多次散射项
那么,公式(2)中的两部分在数学上到底是怎么写出来的呢?先从较为简单的多次散射项入手:
S d ( x i , ω i ; x o , ω o ) = 1 π F t ( η , ω i ) R d ( r ) F t ( 1 η , ω o ) S_d(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) = \frac{1}{\pi}F_t(\eta,\boldsymbol \omega_i)R_d(r)F_t(\frac{1}{\eta},\boldsymbol \omega_o)
S d ( x i , ω i ; x o , ω o ) = π 1 F t ( η , ω i ) R d ( r ) F t ( η 1 , ω o )
其中,
r = ∥ x o − x i ∥ r = \left\|\mathbf x_o - \mathbf x_i\right\|
r = ∥ x o − x i ∥
表示入射点和出射点在表面上的距离。这里通常默认物体表面可以近似看成一张无限大的平面 。
而在这个式子里,最核心的部分其实是
R d ( r ) R_d(r)
R d ( r )
在论文中被称为Diffusion BSDF ,它描述的是:当一部分光进入介质内部之后,这部分能量会怎样在内部扩散,并最终在距离入射点 r r r 的位置附近重新透射出来。 你可以想象介质内部有一个虚拟光源,它把进入内部的能量重新分配到周围的各个位置上,而且离得越远,分到的能量通常就越少。
这里之所以说它是“虚拟光源”,是因为它当然不是真正存在的光源,而只是一个帮助我们理解和建模的数学等效。那这部分能量到底是从哪里来的呢?答案其实很直接:它本质上还是来自外部的入射光。
这也解释了为什么公式两边会各出现一个菲涅尔项。它们的作用不是去描述反射掉了多少能量,而是描述:有多少光能够真正穿过边界进入介质,以及最后又有多少光能够从介质内部穿出来。
如果用最直观的方式去理解,这里的透射项可以简单写成:
F t = 1 − F F_t = 1 - F
F t = 1 − F
也就是说,菲涅尔反射项 F F F 描述的是被表面反射走的那部分能量,而 F t F_t F t 描述的则是成功透射过去的那一部分。
这样一来,整个公式的物理图像就很清楚了。
首先,一束入射光打到表面上,经过第一个透射菲涅尔项的修正,只有其中一部分能量真正进入了介质内部;接着,这部分能量会按照 R d ( r ) R_d(r) R d ( r ) 所描述的方式,在介质内部不断扩散,并有一部分分配到距离入射点为 r r r 的出射位置附近;最后,这部分到达出射点附近的能量还需要再穿过一次边界,因此还要再乘上第二个透射菲涅尔项,才能变成我们最终在表面外看到的出射辐亮度。
从这个角度看,多次散射项的结构其实非常优雅:进来一次、内部扩散一次、出去一次。
两个菲涅尔项负责处理“进”和“出”,中间的 R d ( r ) R_d(r) R d ( r ) 则负责描述“在里面发生了什么”。
另外,理论上对 R d ( r ) R_d(r) R d ( r ) 做积分,结果并不一定会等于 1 1 1 。这其实并不奇怪:一方面,这一项本来就只描述了多次散射 ,并没有把单次散射 算进去;另一方面,光在介质内部传播时,还会有一部分能量被吸收掉,所以最终能够重新回到表面的能量本来就不可能完整保留。
至于 R d ( r ) R_d(r) R d ( r ) 的具体形式,这里就再展开了。因为在实际使用 BSSRDF 的时候,我们通常不会直接使用它的原始推导式硬算,而是会进一步采用一些更简洁、更实用的近似模型 。这也是这篇文章后半部分的内容。
单次散射项
相比多次散射项,单次散射项 的公式会稍微复杂一些。不过,只要对前面介绍过的辐射传输方程已经有了一点感觉,这个式子其实并没有看起来那么难懂。它本质上描述的,仍然是一个非常直观的过程:光线进入物体内部,在某个位置发生一次散射,然后从表面离开。
先直接把公式写出来:
L o ( 1 ) ( x 0 , ω o ) = ∫ A ∫ 2 π S ( 1 ) ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = σ s ( x o ) ∫ 2 π F ⋅ p ( ω i ′ , ω o ′ ) ∫ o ∞ e − σ t c s d s d ω i \begin{align*}
L_o^{(1)}(\mathbf x_0, \boldsymbol \omega_o)
&= \int_A \int_{2\pi} S^{(1)}(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)\, L(\mathbf x_i,\boldsymbol \omega_i)\, (\mathbf n \cdot \boldsymbol \omega_i)\, \mathrm d \boldsymbol \omega_i\, \mathrm d A(\mathbf x_i) \\
&= \sigma_s(\mathbf x_o)\int_{2\pi}F \cdot p(\boldsymbol \omega_i',\boldsymbol \omega_o')\int_o^{\infty}e^{-\sigma_{tc}s}\mathrm d s \,\mathrm d \boldsymbol \omega_i
\end{align*} L o ( 1 ) ( x 0 , ω o ) = ∫ A ∫ 2 π S ( 1 ) ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = σ s ( x o ) ∫ 2 π F ⋅ p ( ω i ′ , ω o ′ ) ∫ o ∞ e − σ t c s d s d ω i
其中,
F = F t ( η , ω i ) F t ( 1 η , ω o ) F = F_t(\eta,\boldsymbol \omega_i)F_t(\frac{1}{\eta},\boldsymbol \omega_o)
F = F t ( η , ω i ) F t ( η 1 , ω o )
表示入射和出射两次穿过边界时的透射修正;
p ( ω i ′ , ω o ′ ) p(\boldsymbol \omega_i',\boldsymbol \omega_o') p ( ω i ′ , ω o ′ ) 是相位函数,用来描述光线在散射点处从入射方向分配到出射方向的比例;
而
∫ 0 ∞ e − σ t c s d s \int_0^{\infty}e^{-\sigma_{tc}s}\,\mathrm d s
∫ 0 ∞ e − σ t c s d s
则对应我们前面在前篇文章中介绍过的 Beer–Lambert Law ,用来描述光线在介质中传播时,能量如何随着路径长度按指数 形式衰减。
论文里也给出了这条公式的示意图。之所以单次散射项看起来会比多次散射更“绕”一些,是因为它要求我们去考虑所有可能的单次散射路径 :光线先从入射点进入介质,在内部某个位置发生一次散射,然后再从出射点离开表面。
由于这个散射点可以落在路径上的任意位置,我们就需要对所有可能的路径长度进行积分,因此这里的积分范围自然是
[ 0 , ∞ ) [0,\infty)
[ 0 , ∞ )
不过要注意,这里的 s s s 只是散射点到出射点 这一段路径上的参数。为了把整个传播过程——也就是“入射点 → \rightarrow → 散射点 → \rightarrow → 出射点”——统一纳入衰减项中,我们需要引入一个修正后的消光系数 σ t c \sigma_{tc} σ t c 。
借助一点简单的几何关系,可以得到它的表达式:
σ t c = ( 1 + G ) σ t \sigma_{tc} = (1+G)\sigma_t
σ t c = ( 1 + G ) σ t
其中,
G = ∣ n ⋅ ω o ′ n ⋅ ω i ′ ∣ G=\left|\frac{\mathbf n \cdot \boldsymbol \omega_o'}{\mathbf n \cdot \boldsymbol \omega_i'}\right|
G = n ⋅ ω i ′ n ⋅ ω o ′
这个量可以理解成一个路径比例修正项。直观来说,它反映了入射段路径和出射段路径之间的相对长度关系,因此能够把原本只沿单段路径定义的衰减,转换成对整条单次散射路径都成立的形式。当然,这种映射假设了介质内部的消光系数处处相等。
这么看下来,单次散射项虽然公式更长,但物理图像其实很清楚:
光先穿过表面进入介质,在内部传播的过程中不断衰减;接着在某个点发生一次散射;最后再继续衰减,并从表面射出。
整个公式做的事情,无非就是把所有可能发生这件事的路径全部累加起来。
如果你是第一次接触 BSSRDF,那么看到这里对一些概念感到陌生其实很正常。像消光系数 、Beer–Lambert Law 、相位函数 这些东西,本来就是从体积渲染和辐射传输方程一路延伸过来的。要是你对这部分理论暂时没那么感兴趣,直接先跳过这部分也完全没问题,毕竟在很多实际实现里,大家往往也不会直接使用这种最原始的表达形式。
但如果你想真正把这条公式背后的来龙去脉彻底搞明白,那确实最好回过头,先把体积渲染那部分内容理解一下。
BSSDF的完整数学表达
有了单次散射 和多次散射 的表达之后,我们终于可以把 BSSDF 的完整形式写出来了:
L o ( x 0 , ω o ) = ∫ A ∫ 2 π S ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = ∫ A ∫ 2 π ( S d ( x i , ω i ; x o , ω o ) + S ( 1 ) ( x i , ω i ; x o , ω o ) ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = ∫ A ∫ 2 π 1 π F t ( η , ω i ) R d ( r ) F t ( 1 η , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) + σ s ( x o ) ∫ 2 π F ⋅ p ( ω i ′ , ω o ′ ) ∫ o ∞ e − σ t c s d s d ω i \begin{align*}
L_o(\mathbf x_0, \boldsymbol \omega_o)
&= \int_A \int_{2\pi} S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)\, L(\mathbf x_i,\boldsymbol \omega_i)\, (\mathbf n \cdot \boldsymbol \omega_i)\, \mathrm d \boldsymbol \omega_i\, \mathrm d A(\mathbf x_i) \\
&= \int_A \int_{2\pi} (S_d(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o)+S^{(1)}(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o))\, L(\mathbf x_i,\boldsymbol \omega_i)\, (\mathbf n \cdot \boldsymbol \omega_i)\, \mathrm d \boldsymbol \omega_i\, \mathrm d A(\mathbf x_i) \\
&= \int_A \int_{2\pi} \frac{1}{\pi}F_t(\eta,\boldsymbol \omega_i)R_d(r)F_t(\frac{1}{\eta},\boldsymbol \omega_o)\, L(\mathbf x_i,\boldsymbol \omega_i)\, (\mathbf n \cdot \boldsymbol \omega_i)\, \mathrm d \boldsymbol \omega_i\, \mathrm d A(\mathbf x_i) \\
&+\sigma_s(\mathbf x_o)\int_{2\pi}F \cdot p(\boldsymbol \omega_i',\boldsymbol \omega_o')\int_o^{\infty}e^{-\sigma_{tc}s}\mathrm d s \,\mathrm d \boldsymbol \omega_i
\end{align*} L o ( x 0 , ω o ) = ∫ A ∫ 2 π S ( x i , ω i ; x o , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = ∫ A ∫ 2 π ( S d ( x i , ω i ; x o , ω o ) + S ( 1 ) ( x i , ω i ; x o , ω o )) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) = ∫ A ∫ 2 π π 1 F t ( η , ω i ) R d ( r ) F t ( η 1 , ω o ) L ( x i , ω i ) ( n ⋅ ω i ) d ω i d A ( x i ) + σ s ( x o ) ∫ 2 π F ⋅ p ( ω i ′ , ω o ′ ) ∫ o ∞ e − σ t c s d s d ω i
看着实在是太复杂了哈哈,不过别担心,后面的形式会变得更加简单些(心虚)。
BSSDF的BRDF近似
论文 A practical model for subsurface light transport 还给出了一个非常实用的 BSSDF 的 BRDF 近似 。
所谓“BRDF 近似”,本质上就是在一些特定假设下,把原本和入射位置 x i \mathbf x_i x i 、出射位置 x o \mathbf x_o x o 有关的部分先预计算 掉,这样在真正渲染的时候,就不需要再显式处理整块表面的空间积分了。
为了做到这一点,需要先做一个常见假设:入射光在表面上是均匀的 ,也就是
L ( x i , ω i ) = L ( ω i ) L(\mathbf x_i,\boldsymbol \omega_i) = L(\boldsymbol \omega_i)
L ( x i , ω i ) = L ( ω i )
在这个假设下,和空间位置有关的那部分扩散分布就可以提前积掉。对 R d ( r ) R_d(r) R d ( r ) 做积分之后,我们会得到一个很重要的量,论文里通常称它为 Diffuse Reflectance 或类似名称。这里为了方便,我们记作 A A A :
A = 2 π ∫ 0 ∞ R d ( r ) r d r = α ′ 2 ( 1 + e − 4 3 K 3 ( 1 − α ′ ) ) e − 3 ( 1 − α ′ ) . (3) \begin{align*}A
&=2\pi\int_0^\infty R_d(r)\,r\,\mathrm dr \\
&= \frac{\alpha^{\prime}}{2} \left(1+e^{-\frac{4}{3}K\sqrt{3(1-\alpha^{\prime})}}\right) e^{-\sqrt{3(1-\alpha^{\prime})}}.
\end{align*} \tag{3} A = 2 π ∫ 0 ∞ R d ( r ) r d r = 2 α ′ ( 1 + e − 3 4 K 3 ( 1 − α ′ ) ) e − 3 ( 1 − α ′ ) . ( 3 )
这里的 α ′ \alpha' α ′ 被称为 Reduced Albedo ,定义为:
α ′ = σ s ′ σ t ′ \alpha' = \frac{\sigma_s'}{\sigma_t'}
α ′ = σ t ′ σ s ′
其中,σ s ′ \sigma_s' σ s ′ 和 σ t ′ \sigma_t' σ t ′ 是考虑了相位函数影响之后的约化散射系数 和约化消光系数 。它们通常写成:
σ s ′ = σ s ( 1 − g ) , σ t ′ = σ a + σ s ′ \sigma_s' = \sigma_s(1-g), \qquad \sigma_t' = \sigma_a + \sigma_s'
σ s ′ = σ s ( 1 − g ) , σ t ′ = σ a + σ s ′
这里的 g g g 是前一篇文章提到过的不对称因子 (Asymmetry Parameter),用来描述散射更偏向前向还是后向。它的取值一般在 [ − 1 , 1 ] [-1,1] [ − 1 , 1 ] 之间;当 g g g 越大时,散射就越偏向前向。
有了这个预积分结果之后,我们就可以把 BSSDF 写成一个更加紧凑、也更方便在渲染中直接使用的 BRDF 近似形式:
f r ( x , ω i , ω o ) = f r ( 1 ) ( x , ω i , ω o ) + F A π f_r(\mathbf x,\boldsymbol \omega_i,\boldsymbol \omega_o) = f_r^{(1)}(\mathbf x,\boldsymbol \omega_i,\boldsymbol \omega_o) + F\frac{A}{\pi}
f r ( x , ω i , ω o ) = f r ( 1 ) ( x , ω i , ω o ) + F π A
其中,第一项对应的是单次散射项 :
f r ( 1 ) ( x , ω i , ω o ) = α F p ( ω i ′ , ω o ′ ) ∣ n ⋅ ω i ′ ∣ + ∣ n ⋅ ω o ′ ∣ f_r^{(1)}(\mathbf x,\boldsymbol \omega_i,\boldsymbol \omega_o) = \alpha F \frac{p(\boldsymbol \omega_i',\boldsymbol \omega_o')} {\left|\mathbf n\cdot \boldsymbol \omega_i'\right|+\left|\mathbf n\cdot \boldsymbol \omega_o'\right|}
f r ( 1 ) ( x , ω i , ω o ) = α F ∣ n ⋅ ω i ′ ∣ + ∣ n ⋅ ω o ′ ∣ p ( ω i ′ , ω o ′ )
这里
α = σ s σ t , F = F t ( η , ω i ) F t ( 1 η , ω o ) \alpha = \frac{\sigma_s}{\sigma_t}, \qquad F = F_t(\eta,\boldsymbol \omega_i)\,F_t\!\left(\frac{1}{\eta},\boldsymbol \omega_o\right)
α = σ t σ s , F = F t ( η , ω i ) F t ( η 1 , ω o )
这样一来,整个式子的结构就非常清楚了:
一部分由单次散射 贡献,另一部分则用一个更平滑的扩散项 来近似多次散射。原本那个看起来相当庞杂的 BSSDF,经过这些近似和预计算之后,就被压缩成了一个更像 BRDF 的形式,使用起来也方便了很多。
没搞错的话,Disney BRDF 就用到了这里的近似公式模拟次表面散射,不确定,后面再看看。
Normalized Diffusion:更易于实现的经验模型
前面的理论基础已经介绍得差不多了,但如果直接拿上一节那些公式来实现,其实并不算友好。问题的核心在于:其中的 R d ( r ) R_d(r) R d ( r ) 形式比较复杂,不太利于后续的重要性采样。换句话说,它很适合用来理解理论,却不算特别适合直接拿来做工程实现。
所以,我们接下来需要一个更容易使用、也更方便调参 的近似模型,来进一步简化 BSSRDF。这就是 Pixar 在 2015 年提出的一种经验模型:Normalized Diffusion 。
前面我们把散射拆成了单次散射 和多次散射 两部分。这样的拆分在理论上当然很清楚,也很精确,但一旦真正落到计算和实现上,处理起来难免会有些麻烦。于是,一个很自然的想法就是:能不能用一个更统一的形式,把这两部分一起近似掉?
BSSDF 的简化形式如下:
S ( x i , ω i ; x o , ω o ) = C ⋅ F t ( η , ω i ) R ( r ) F t ( 1 η , ω o ) S(\mathbf x_i, \boldsymbol \omega_i;\mathbf x_o, \boldsymbol \omega_o) = C\cdot F_t(\eta,\boldsymbol \omega_i)\,R(r)\,F_t\!\left(\frac{1}{\eta},\boldsymbol \omega_o\right)
S ( x i , ω i ; x o , ω o ) = C ⋅ F t ( η , ω i ) R ( r ) F t ( η 1 , ω o )
其中,
r = ∥ x o − x i ∥ r = \left\|\mathbf x_o - \mathbf x_i\right\|
r = ∥ x o − x i ∥
表示入射点和出射点在表面上的距离。
可以看到,这个形式和前面介绍过的多次散射项 非常相似。区别在于,这里不再显式地区分单次散射和多次散射,而是希望通过一个合适的 R ( r ) R(r) R ( r ) ,统一去近似整个散射分布。于是问题就变成了:怎样选一个既合理、又足够好算的 R ( r ) R(r) R ( r ) 。
至于公式里的常数 C C C ,Pixar 的论文里并没有展开给出特别具体的表达,只提到它是一个常数。本文里我暂时把它看作 1 1 1 来理解,后面如果真的在实现中遇到需要进一步追究它的场景,再去单独研究吧。
在继续往下之前,还需要先引入一个新概念:平均自由程 (mean free path)。这个概念在前面的体积渲染文章里我没有专门提到,它的定义是:
ℓ = 1 σ t \ell = \frac{1}{\sigma_t}
ℓ = σ t 1
直观来看,平均自由程描述的是: 光在介质中平均能传播多远,才会发生一次相互作用。
消光系数越大,说明介质越“浓”,光走不了多远就会被吸收或散射,因此平均自由程也就越短。
Pixar 给出的 R ( r ) R(r) R ( r ) 有两种等价写法。第一种形式是:
R ( r ) = A s e − s r / ℓ + e − s r / ( 3 ℓ ) 8 π ℓ r (4) R(r)=As\frac{e^{-sr/\ell}+e^{-sr/(3\ell)}}{8\pi\ell r} \tag{4}
R ( r ) = A s 8 π ℓ r e − sr / ℓ + e − sr / ( 3 ℓ ) ( 4 )
这个形式有一个很实用的优点:它本身是可积的。
这意味着我们可以进一步得到它的 CDF 解析式,而一旦有了 CDF,后续做重要性采样就会方便很多。不过这篇文章不打算继续展开到采样细节。
回到这个公式本身,里面有几个符号需要先说明一下:
第一种情况叫做 searchlight configuration 。
在这种设定下,入射光近似看作是垂直打到表面上的一束窄光 。这时,s s s 的经验表达式为:
s = 1.85 − A + 7 ∣ A − 0.8 ∣ 3 s = 1.85 - A + 7\left|A-0.8\right|^3
s = 1.85 − A + 7 ∣ A − 0.8 ∣ 3
第二种情况叫做 diffuse surface transmission 。
这里假设光进入介质时更接近一种理想化的漫透射过程,因此更适合用来描述粗糙表面的半透明材质 ,比如皮肤、水果这类介质。在这种情况下,s s s 的计算方式是:
s = 1.9 − A + 3.5 ( A − 0.8 ) 2 s=1.9-A+3.5(A-0.8)^2
s = 1.9 − A + 3.5 ( A − 0.8 ) 2
论文里其实还提到了另一种情况。在那种写法里,会把 ℓ \ell ℓ 替换成 ℓ d \ell_d ℓ d ,也就是介质表面的平均自由程。这部分我自己目前也没有完全理解,似乎就是:当你把表面平均自由程 作为输入参数时,需要用到的一种另外的对应写法。为了避免 Confusion,这部分就略过了。
除了前面那种写法之外,公式(4)还可以改写成另一种完全等价、但更适合给美术调参数的形式:
R ( r ) = A e − r / d + e − r / ( 3 d ) 8 π d r (5) R(r)=A\frac{e^{-r/d}+e^{-r/(3d)}}{8\pi d r} \tag{5}
R ( r ) = A 8 π d r e − r / d + e − r / ( 3 d ) ( 5 )
其中,
d = ℓ s d = \frac{\ell}{s}
d = s ℓ
写成这种形式之后,参数的直觉就清晰多了:
A A A 决定整体的扩散强度,而 d d d 则控制扩散范围。,这两个量都可以比较自然地暴露给美术作为可调参数来使用。
Pixar 的论文还进一步介绍了如何基于这个模型做重要性采样。不过这部分内容我自己目前也还没有形成特别深刻的理解,所以这篇文章就不往下展开了。
那以上就是这篇文章的全部内容了。下一篇大概率会聊到 Disney BRDF 。如果你能一路看到这里,非常感谢阅读。
参考文献
bssrdf
基于物理着色(四)- 次表面散射 - 知乎
PBRT:The BSSRDF
A practical model for subsurface light transport
Pixar:Approximate Reflectance Profiles for Efficient Subsurface Scattering