Games202笔记——Real-time-Environment-mapping(2)

环境光照的阴影计算

首先,最High level的答案是不知道怎么做

总归这个事情是非常非常困难的,环境光是四面八方过来的光,你难道把每个点都视为点光源或面光源吗(many-light problem)

还有一个思路就是采样,但众所周知采样也不是什么好方法,关键是我们很难获得一个着色点的visibility term,不知道该怎么采样,盲目的采样那就更慢了

如果我们想要用上一节的拆分方法,也就是这个玩意

积分域小,g(x)足够光滑时,我们可以做如上拆分,但是假如你的BRDF是glossy的,那么就会有多次跳变,频率也会很高。同时积分域还是接收光照的整个上半球,可以发现我们并不能继续用这种拆分方法。

工业界对这个问题的近似方法非常的暴力:你总会有一个或几个最主要的光源(例如太阳),我根据这几个光源生成阴影就好了

如果真的要解决的话,下面要讲的PRT是一种很不错的解决方案,它是一种可以得到非常准确的环境光照阴影的方法

以及光追永远滴神

球面谐波函数(Spherical Harmonics,SH)

前置的数学知识

根据我们高数学习的知识,任意一个函数可以用傅里叶级数逼近,即写成一个常数和若干sin和cos项的线性组合,其中每项我们将其称为一个基函数,那么我们也可以说,一个函数可以写成一系列基函数的线性组合

基函数性质可以写成如下公式

其中$B_i(x)$为第i个基函数

对于一个空间上的函数,如果在这个函数覆盖到的空间中,函数值变化非常剧烈,我们可以认为这个函数频率很高,反之则比较低,如下图所示

image-20210514153342149

左图的人像中,头发的位置变化非常频繁且剧烈,频率较高,而背景和衣服部分频率较低,我们可以获得这个图像的频域上所显示的内容,即为频谱,如右图所示。频谱中间四个明显高的spike是由于频谱识别的时候会默认将图像在U和V方向上平铺,在平铺的交界会产生巨大的变化,频率很高。

如果我们在频域上留下低频的部分,去掉高频的部分,就会使图像的变化不太明显,看起来像整个图像被模糊了一样,如下图所示

image-20210514153823413

滤波(filtering)的意思就是在图像频域上去掉特定范围的内容。上图就是低通滤波的一个例子

另外,在图形学上的卷积和平均是同一个意思,而卷积实际上也可以·看作一种滤波,如下图

image-20210514154111345

卷积的数学表示是如下形式

按照上述定义我们可以扩展概念,认为图形学中对两个函数的乘积进行积分的形式就是图形学中的卷积。同样的,我们认为这种形式存在一定的滤波意义

球面谐波函数的定义

球面谐波函数是一系列二维的基函数,这个系列中每一个函数都是定义在球面上的,可以理解为每一个函数都是对方向的函数,对于三维空间中不同的一个二维方向(用$\theta$,$\phi$表示),该函数都对应一个值。每一个SH都是一个独特的函数

和傅里叶级数的基函数非常相似的是,SH也有不同频率的函数,且不同频率所对应的函数个数不同,具体如图所示并看不懂为什么是这样子

image-20210514155651097

上图是对SH的可视化,颜色代表正负,可以看见,对于第L阶,有2L+1个SH,编号从-L到L

每一个SH关联了一个勒让德多项式(Legendre polynomial),数学上是非常复杂的,但我们并不需要理解这个多项式,我们只需要知道一个SH可以用数学方式定义,同时SH的线性组合可以用来描述球面上函数的性质即可

球面谐波函数是正交的,且球面谐波函数基函数发生旋转都可以用同阶函数的线性组合表示

球面谐波函数在环境光照中的使用

对于一个球面函数,我们如果想要得出对应的SH的系数,可以做如下操作

其中$\Omega$为球面,$\omega$为球面上的一个方向。$f(\omega)$是这个函数本身,求这个系数的过程在数学上定义叫做投影, 投影的过程便被我们写成了一个卷积的形式。

因为级数是无限的,我们不可能真的用无穷级数取逼近原函数,通常只会用低阶的SH去还原原函数,相当于对原函数做了低通滤波。

不难发现环境光就是一个定义在球面上,不同的方向有不同的值的函数,因此我们可以用SH还原环境光。

根据上节课对环境光采样的结果,我们可以得出一个结论:

先滤波+一次采样=不滤波+多次采样

全局光照问题在BRDF diffuse的时候可以说是相对做了简化的,回顾渲染方程

其中$L_i(p,\omega_i)$是环境光,不难发现这相当于将环境光与BRDF做了卷积,如果BRDF即$f_r(p,\omega_i,\omega_o)$是diffuse的,那么相当于对环境光项做了低通滤波。

在这种条件下,我们观察到,大概我们只需要三阶SH就可以很好的还原环境光,从三阶开始系数$c_i$几乎是0

那么用这种方法如何解决阴影呢?

PRT(Precomputed Radiance Transfer)

回到渲染方程来

我们如果想要算渲染方程,最简单的方法自然是对于每个对应的像素都乘起来,然后做积分,计算量可想而知的大

不难发现,除了$L_i(p,\omega_i)$以及BRDF本身是球面函数之外,$V(p,\omega_i)$也是在不同的方向上定义有不同的值,也是球面函数

PRT的基本思想是:假设渲染过程中场景内其余物体不变,只有光照会发生变化,因此我们把渲染方程看成两部分,$L_i(p,\omega_i)$是负责光照的那一部分,其余的$f_r(p,\omega_i,\omega_o)\cos{\theta_i}V(p,\omega_i)$和光照并没有什么关系,记为light transport部分。

可以发现light transport是和光照无关的,被渲染物体本身的性质,那么我们也许可以先完成这部分的预计算。不难发现,light transport项对于一个确定的点p仍然是一个球面函数。

如果BRDF是diffuse的,我们可以认为BRDF是一个常值,直接把BRDF项拿出来记作$\rho$,则上式可以被我们写成如下形式

我们把光照写成用SH表示的形式,即

这里我们认为是对于一个确定的点p,即点p是常值。

那么渲染方程可以进一步化简为

在PRT场合之中一定可以交换积分与求和的顺序,因此我们发现积分项是一个球面函数向SH基函数投影的形式,这部分完全可以预计算。因此渲染方程的最终形式为

可以发现求和项就是对两个向量的点乘

SH有一个性质,就是如果我对原函数进行一个旋转,很快的就能算出旋转后SH对应的系数。也就是说环境光是可以旋转的,但是场景中的物件不能移动

至于BRDF不是diffuse该如何解决,下节课讲ylq摸了

欢迎关注我的其它发布渠道