计算机图形学 – 实时次表面散射简介(Real-Time Subsurface Scattering)
1 SSS Basics(次表面反射基础)
什么是“Subsurface Scattering”?
在现实世界中,次表面散射通常发生在我们看起来很标准的材料上,比如塑料或者皮革制品。我们通常使用“Lambertian”这样的漫反射BRDF模型进行建模。Naty Hoffman在2013年关于阴影物理的演讲中所展现的下面这幅图对我们理解什么是“Subsurface Scattering”非常有帮助。
在上图中,带有红色轮廓的绿色圆圈的范围可以认为是像素的着色区域,右边的橙色大箭头表示来自特定方向的入射光线,其中大部分入射光线由于镜面反射从左侧射出,然而,也有一部分光线会折射到表面,然后遇到介质中的粒子,然后光在粒子之间散射,从而导致某些波长被吸收,使得光线呈现出材料的反照率颜色。而剩下另一小部分未被完全吸收的光会以随机方向折射出表面,而这些折射出表面的光线可能重新反射到我们眼睛中。我们假设所有的散射光都从入射光进入到表面的位置进行射出,这让我们可以只考虑与像素相交的光线,然后通过大致估计从该点反射的光线来简单量化这一复杂的过程。
然而,当我们在游戏或计算机图形学中提到次表面散射时,这通常不是我们要讨论的。通常,该术语仅在材料半透明的情况下提出,使散射光比更标准的材料反射得更远。如下图中所示:
在这种情况下,散射光不再出现在像素内,而是出现在可能被相邻像素覆盖的区域。换言之,我们已经越过了一个阈值,在这个阈值中,我们不再只考虑像素的入射光,相反,我们需要全局考虑来自其他地方的光,以模拟光通过表面扩散的可见效果。可以想象,对于实时渲染器来说,这确实使事情变得复杂,但我们稍后将进一步讨论这一点。
现在,假设我们正在进行离线渲染,并且可以进行光线追踪或者其他绚丽的功能,那么在这种情况下,我们该如何计算次表面反射呢?
如果我们想要计算准确的次表面散射,我们将使用体积路径跟踪技术来计算光线如何在介质中散射和重构。这听起来可能很贵(而且确实如此!),但它正成为高端动画和VFX工作室越来越可行的选择。无论采用哪种方法,此方法都可以模拟光的完整路径以及表面下发生的所有各种散射事件,这可以为您提供相对准确的结果,从而解释复杂的几何体和非均匀散射参数。
2 Diffusion Approximations
与离线渲染相比,游戏或者实时渲染应用通常受到更加严格的性能限制,所以我们通常使用更近似的基于扩散的方法。这方面大部分的工作源于Jensen在2001年发表的论文A Practical Model for Subsurface Light Transport,该论文首次将双向表面散射分布函数(BSSDF)引入到计算机图形学中。这篇论文在过去的一二十年里引发了各种有趣的后续研究,涵盖了离线渲染与实时渲染领域。其所扩张的内容超出了本文的讨论范围,在本文中我们将内容提炼为在游戏应用中所使用的近似方法。
Jensen提出的方法的关键在于简化假设,即高散射介质中的光分布趋于各向同性。这意味着一旦光线进入曲面,它很可能会以任意方向出现,而不是大部分与入射光方向或者类似方向对齐。这实际上使散射成为一种“模糊”函数,从而导致反射光的均匀分布(请注意,这与我们对Lambertian漫反射的假设相同)。Jensen提出的双向表面散射分布函数(BSSDF)实际上基于两个部分,一个是计算单次散射贡献的精确方法(入射光线进入表面,击中物体,然后再次反弹),另一个是“dipole”方法,该方法通过计算两个虚拟的点光源(一个在物体表面上方,一个在物体表面下方)来近似多次散射的贡献(光进入曲面,发生多次散射,然后找到光的出路):
尽管有分析方法计算光从曲面的输入点到输出点的散射,但是计算此种渲染的积分难以计算。通常,计算任意BSSDF的公式如下:
上述公式是一个平均积分,其要求我们必须遍历网格的整个表面,并在表面的每一个点上采样上半球的每一个方向,并在入射光线上使用散射函数S\left(x_{i}, i ; x_{o}, o\right)进行计算。如果我们要简化这一计算过程,我们可以假设散射函数是径向对称的,实际上只取决于入射点与出射点之间的距离,所以上述积分求和公式可以进行简化:
新的积分公式的计算过程可以简单归纳为对于表面上的每一个点,计算其辐照度,然后乘以以距离为参数的散射函数。上述公式并不能解决“如要对单个点进行着色,那么我们需要对曲面上其他的所有点进行着色”的问题。然而,它确实为我们提供了一个有用的框架以及可以使用的简化模型。散射仅仅取决于距离的假设基本上将散射函数转化为模糊/滤波核,但它可以应用到任意网格曲面而不是2D图像。因此你经常会看到被称为扩散配置文件(或有时称为扩散内核)的R(r),这是我在本文其余部分中经常使用的术语。如果你想描述像人类皮肤一样的东西的扩散轮廓,你可以想象你在一个完全黑暗的房间里,向你的皮肤发射极窄的纯白激光束:
从技术上讲,你可以在这里使用任何你想使用的扩散配置文件。例如,你可以使用Gaussian kernel、smoothstep、cubic functions等。然而你可能希望使用“归一化”函数,因为它不会增加或者减少能量(换句话说,对于所有可能的配置,内核都归一化为1)。但是即使这样,也不能保证你所选择的内核与真实世界物质(如皮肤)的散射行为相匹配。因此,你必须仔细选择扩散配置,使其与该材质相匹配。Disney(迪士尼)在人类皮肤上就是这么做的,他们基于两个指数和创建了一个内核,他们称之为“normalized diffusion”。他们模型的有点在于不仅使用起来简单直观,而且它们还可以准确的适用于单个内核的单散射组件和多散射组件:
3 Rendering With a Diffusion Profile
那么我们如何用BSSDF实际渲染一些东西呢? 即使我们通过使用径向对称扩散轮廓进行了简化,我们仍然存在这样的问题,即网格上任何特定表面的着色都可能依赖于同一网格上的所有其他表面。 在实践中,我们可以利用这样一个事实来改善这种情况,即行为良好的扩散曲线应该总是随着距离的增大而减小。 这让我们可以确定“最大散射距离”,其中超出该距离的贡献低于可接受的阈值。 一旦我们有了这个r_{max},我们就可以将我们的采样限制在一个半径等于r_{max}的球体内。通过让我们将事物限制在阴影点周围的本地邻域,这无疑对事情有很大帮助。
离线世界中的sub-scattering的大多数的早期用途都是围绕使用点云对相邻辐照度进行采样而构建的。点云是一种分层结构,允许将照度缓存在场景中的任意点,通常位于网格(也称为面元)的表面上:
它们由Pixar推广,他们将它们集成到RenderMan中计算全局光照。后来随着点云失宠以及路径追踪开始接管,蒙特卡罗方法开始出现。Solid Angle和Sony Imageworks的演示总结了4种这样的方法,每种方法都基于将光线样本分布在样本点周围的想法,使其密度与扩散轮廓成正比。第四种方法(在球体内从正交方向发射光线)已被迪士尼使用,也许还有许多其他方法:
EA SEED的Halcyon渲染引擎实际上已经实时使用了第一种方法(从地表下方的一点均匀地射出光线):
只要您有资源对场景几何体执行光线相交,这些方法都可以非常有效。尽管需要大量的计算性能,但这里仍然会做出一些假设,您的特定场景可能会违反这些假设。特别是,假设被光线击中的每个点都“连接”到原始着色点,这样光线就可以一直散射到那里。这个问题可以通过限制光线查询来缓解,使它们只与被着色的同一个网格相交,这具有减少需要考虑的表面数量的额外好处。但即使有这个限制,也很容易想象一条散射路径会直接穿过一个空的空气间隙。 迪士尼的课程笔记中有一张图表显示了这种情况:
在这个例子中,如果光从入口点一直散射到出口点,那么它必须在裂缝周围散射,这是一条很长的路。仅考虑这些点之间距离的方法将过度估计此处的散射,而不是可以实际解释间隙的适当体积路径跟踪器。
4 Rendering Diffusion in Real-Time
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:计算机图形学 – 实时次表面散射简介(Real-Time Subsurface Scattering)
原文链接:https://www.stubbornhuang.com/2313/
发布于:2023年06月21日 18:05:30
修改于:2023年06月27日 9:37:41
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
52