次表面散射(Subsurface Scattering,SSS)是指光线穿过透明或半透明的物体时,在物体内部发生的多次散射现象。这种现象使得光线在物体内部产生弥散的效果,从而让物体看起来更加真实,类似于自然光线照射下的效果。次表面散射既不是半透明,也不是透射。
次表面散射通常在渲染计算机图形中用于模拟皮肤、牙齿、眼睛、水、果冻等半透明材料的外观。它可以让这些物体看起来更加真实,增加场景的真实感和视觉吸引力。
在计算机图形学中,次表面散射可以通过各种技术实现,包括基于物理模型的方法、预计算的方法、基于纹理的方法等。这些方法可以在渲染中模拟出不同类型的材质和光照条件下的次表面散射效果,从而让场景看起来更加逼真和生动。
本篇文章难度很大,内容也很多很多,写这篇文章花费了大于一周的时间,期间参考了很多文章、论文、PDF、PPT等,遇到不明白的地方可以参考引用的原文。
实现次表面散射的核心思路
首先次表面散射是光线在物体内部多次弹射的效果,所以可以通过光线追踪来实现。如下图所示,橙黄色的入射光大部分从表面反射(镜面反射),另一些在进入到物体内部后,部分被吸收,部分发生多次弹射(散射),这些吸收散射的特性就是材料特有的反射率,这些现象从而使光呈现出材料特有的反照率颜色。在实时渲染中,我们谈及的次表面散射都是一种模拟或者说近似。

模拟思路与扩散近似
最常见的思路就是简化光线在物质内的散射现象,假定光线进入后会随机的向任何方向射出,我们可以给定这种散射一种“模糊”函数(这很像Lambert的假设),这种模拟的方法叫做Diffusion Profile。


关于此公式的简化思路我准备放在上一篇BxDF中写,先说结果:其中 R(||Xi-X0||)代表着光线在物体内部散射的系数,也就是Diffusion Profile(Kernel),这代表着我们假定模拟的次表面散射只和入射点和出射点的距离有关系。下图是一张假定的模糊函数表格,代表着R(r)扩散剖面和距离的关系(A是Surface Albedo,可以简单理解为代表着不同光线(光线的各种波长 = 各种颜色的光)的散射能力):

下图是Siggraph2012 PPT中(见导言附录5)的举例(R,G,B三种波长的光线)。(看这个图也就能明白为啥透射出来的光照往往是红色)。

我们可以选用各种各样的模糊函数,比如smoothstep,高斯等,其中最著名的也是在现代引擎里最常用的就是迪士尼提出的Burley Normalized Diffusion Profile。关于Normalized Diffusion本身推荐看文刀秋二的文章 (Burley Normalized Diffusion Profile是Normalized Diffusion一个简化版本)。

这里谈谈引用文章中没说到的部分:

上图画红线的部分:在Unity或者UE里都有一个扩散配置文件:


可以参考专栏的引用链接和附录了解他们各个参数的用途。
基于屏幕空间的次表面散射(SSSSS,Screen Space Subsurface Scattering)
在上文我们得到了Diffusion Profile配置,所以接下来我们只需要通过某种方式获取对当前像素的坐标X0到所有有贡献的像素Xi之间的距离再应用Diffusion Profile即可。
在SSSSS之前,有基于纹理空间的方法,但是由于表现效果不佳(相对的)和 难以优化性能等缺点被淘汰了(只有很少很少的游戏用过),这里就不展开讲了,对这种方法感兴趣的小伙伴可以看看引用的文章。
和SSAO,SSR等基于屏幕空间的技术采样方式类似,SSSSS是基于当前像素(样本点)通过某种采样方式(在Unity和UE中采用了逆采样变换的方式,具体过程可以看导言附录6 Unity的分享或者雷火的文章)来计算的,但和任何基于屏幕空间的技术有着一样的缺点,就是会丢失屏幕外的信息或者被遮挡的物体的信息:


预积分次表面散射(Pre-Integrated Skin)
源自SSSSS的方法相对来说依旧昂贵,预积分次表面散射是一种更简化的方法,这也是大多数移动平台游戏采用的方式。
关于预积分次表面散射最好的理解方式还是读SIGGRAPH2011那篇原作者的PPT(见专栏导言附录7)。
我自己单独推导了一遍,并单独写了一篇文章和工具,有兴趣可以看看。

得到这张LUT图后,x方向分量为NoL,y方向分量就是曲率的倒数:

fwidth(x) 等价于 abs(ddx(x))+abs(ddy(x))

可分离次表面散射(Separable Subsurface Scattering,SSSS)
暴雪的Jorge等人,在GDC 2013,的talk“Next-Generation Character Rendering”(见导言附录4)中首次展示了SSSS的渲染图,并在2015年通过论文正式提出了SSSS(可分离的次表面散射,Separable Subsurface Scattering)(http://iryoku.com/separable-sss)其通过水平和垂直卷积2个Pass来近似,效率更进一步提升,这是目前游戏里采用的主流技术(PC、主机)之一。

Burley Normalized SSS(Disney SSS)
这个不知道翻译过来叫啥,也可以叫迪士尼SSS?(笑)。Disney SSS 和 Separable Subsurface Scattering 是同一年提出的,也同样是目前主流引擎(UE/Unity)内集成的SSS方案,不过对于艺术家来说本方案更友好,上文已经介绍过Burley Normalized了。
除了上述的SSS方式,还有基于路径追踪次表面散射等方案,但是在实时领域并不常用,本文就不详细展开讲了。