什么是球谐与光探头?它们在计算机图形学中有多大用处?他们到底在做什么?从Siggraph演示文稿到博客文章,我到处都听到过球谐和光探头这个词。
最近,马特·佩蒂诺(Matt Pettineo)在他们身上发布了由6部分组成的博客系列,但我仍然不明白它们是什么。
这是改善环境照明的另一种方法吗?
什么是球谐与光探头?它们在计算机图形学中有多大用处?他们到底在做什么?从Siggraph演示文稿到博客文章,我到处都听到过球谐和光探头这个词。
最近,马特·佩蒂诺(Matt Pettineo)在他们身上发布了由6部分组成的博客系列,但我仍然不明白它们是什么。
这是改善环境照明的另一种方法吗?
Answers:
球谐函数基础
可以在SH中有效执行的一种此类操作称为“ 卷积 ”,这意味着将两个球形2D函数的乘积积分到一个球上。这是照明计算中的常见操作,例如,其中一项功能可能是您的入射照明,而一项功能是BRDF。当表示为SH时,此操作只是两个SH系数向量的点积。
另一个有趣的操作是执行有效的低通滤波的能力。因为SH是在频域中表示的,所以这仅仅是将某些SH系数缩放或归零的问题。另一方面,与空间域相比,在SH中可能难以执行其他一些操作,例如,如果您要旋转表示为SH的函数,则对于高阶SH来说可能会非常昂贵。因此,是否适合在SH中执行实际上取决于问题。
SH通常仅用于表示低频函数(即平滑变化的函数),因为更高的频率需要增加存储量(SH系数)和处理量。这就是为什么您看不到使用SH替换光泽表面上的镜面反射的原因。还有Zonal Spherical Harmonics,可以通过仅存储SH系数矩阵的对角元素来减少2D函数的存储和计算,这些函数围绕z轴旋转对称。此外半球谐波可以,如果你只需要与半球功能的处理(也常见于照明)具有能够代表类似的频率,SH用更少的系数有益地使用。
您还需要执行的一项操作是“ SH投影”,以将空间域数据转换为SH。您可以通过使用SH基函数对空间域数据进行卷积来执行此操作。SH的一个有趣特性是,与空间域表示法不同,SH不会遭受锯齿,因此即使投影到非常低阶的SH也不会有锯齿。
光探头
现在您已经了解了SH的基本操作和属性,我们可以考虑如何将它们应用于GI。光探针记录从每个方向到探针所处的点的光量。这是球面上的2D函数,可以表示为SH(或红色,绿色和蓝色为3 SH函数)。根据我们要编码到探测器中的照明细节的数量,我们可以选择SH顺序。
对于仅用于朗伯散射照明的光探测器,由于用余弦瓣进行卷积,因此可以用2阶SH(9个系数)表示,因此低阶SH就足够了。光探头的SH系数可以简单地通过在探头的点渲染一个立方体贴图然后将其投影到SH来生成。
渲染几何图形时,几乎不使用最接近的光探测器,并对其结果进行插值以获取空间中某个点的入射照明功能。例如,可以通过直接内插附近探针的SH系数,然后在SH域中与像素法向取向的余弦波进行卷积来实现。
如果您不知道傅里叶变换是什么,那么在理解球形谐波之前,您需要先了解一下。傅立叶变换使您可以将信号表示为一系列正弦波和余弦波,每个信号的频率是前一个的两倍。也就是说,您可以将信号表示为其平均值,再加上波长与信号长度相同的正弦波,再加上两倍于该波长的正弦波,依此类推。由于傅立叶变换可将您固定在这些特定波长上,因此您只需要记录每个波长的幅度即可。
我们通常使用傅立叶变换来表示图像,它们只是2D数字信号。这很有用,因为您可以丢弃一些正弦波(或降低存储其幅度的精度),而无需显着改变人眼的图像外观。OTOH,丢掉像素会极大地改变图像的外观。
在像图像这样的采样信号中,如果您使用与原始图像中相同数量的正弦波,则可以精确地重建图像,因此一旦开始丢掉任何频率,就可以图片占用更少的存储空间。
球谐函数就像傅立叶变换一样,但是它们代替球面正弦波而使用球面函数,因此代替线性函数(例如图像),它们可以表示在球体上定义的函数(例如环境图)。
就像标准图像记录通过图像平面到达某个点的所有光一样,光探测器记录从各个方向到达某个点的所有光。他们首先出现电影效果。如果要将计算机生成的对象添加到现实世界场景中,则需要能够使用现实世界的照明来照明合成对象。为此,您需要知道什么光到达场景中合成对象所在的位置。(注意:虽然我说的是“照明”,但是您正在记录所有光线的图像,因此它也可以用于反射。)
由于无法使用带有球面透镜的相机来记录从所有方向到达单个点的所有光,因此可以通过拍摄球面镜的普通照片,然后将图像重新投影到球体上来进行记录。
除了电影效果外,更常见的是使用从人造场景生成的光探测器。假设您有一种昂贵的算法来计算场景中的全局照明(GI),并且在该场景中还可以移动一些较小的对象(例如,其中有玩家的游戏关卡)。您不能每次都移动任何对象就运行整个GI算法,因此只能在静态场景中运行一次,并保存在关卡中各个点拍摄的光探测器。然后,您可以使用最接近的光探头来照亮播放器,从而获得与GI近似的效果。
通常,无论如何,您都希望滤除全局照明中的锐利边缘,因此,您需要一种紧凑且容易表现出高频的代表它们的方法。这就是球形谐波真正擅长的!这就是为什么您会经常听到这两个术语一起使用的原因。
您可以使用昂贵的GI算法来计算光探头-通常在关卡设计工具中进行计算,或者如果要包含动态对象,则可以每秒一次(而不是每帧一次)。您可以廉价地将其与球谐函数一起存储-16个浮点数足以用于相当高质量的照明,但不能反射。然后,对于要照明的每个动态对象,选择最接近的光照探针(或一起线性内插多个探针),并将其用作着色器的均匀或恒定输入。使用球谐函数表示环境光遮挡数据也是很平常的事,并且与光探头进行卷积运算非常便宜,尽管旋转球谐函数有一些复杂性。
球谐函数
假设您在数组中有一些数据,但是您想用更少的字节数来表示该数据。
一种方法是将数据表示为函数而不是原始值。
问题是,线性方程可能无法很好地近似您的数据。
与线性方程相比,我们增加了内存存储,还增加了存储和检索数据的计算复杂度,但这是对数据数组的更好近似。我们也可以将其提高到三次函数或更高的三次方函数。增加顺序将增加存储量,计算量和准确性。
就像上面的示例一样,您可以使用低阶球面谐波函数来制作具有较低存储量的内容,并使用较低的计算量来计算数据,但同时也会降低准确性。
另一方面,您可以增加阶数并更好地近似原始数据,但代价是需要更多的存储空间,并且需要更多的计算来计算数据点。
在极端情况下,可以使用与阵列中的样本数量一样多的球谐函数,然后可以精确地重建原始阵列,但是这样做需要花费大量的计算,并且使用的存储空间也同样多从一开始。
因此,实际上,如果您需要表示精细的细节(例如在球体上的锐利反射),那么球形谐波函数不会提供太多好处,但是对于没有精细细节的数据(包含没有太多的高频内容)。它们对于进行频谱分析或卷积之类的频域计算也很有用。
他们擅长存储的此类数据之一就是“辐照度”,即从其他方向射向某个点的光量。它看起来有点模糊,这意味着它只有低频成分,并且是存储在球谐函数中的很好的候选者。
我将把光探头的说明留给另一个人:p