Games202学习笔记

Real-Time Shadows

Shadow Mapping回顾

在这里插入图片描述
这是一个2-pass算法,需要对场景渲染两次,

  • 1-pass:从光源空间看过去,得到一张深度图,也就是shadow map
    在这里插入图片描述

  • 2-pass:从摄像机处看过去,并将物体转换到计算shadow map深度的空间,得到物体在光源空间的深度,和shadow map中记录的值进行比较,来决定是否为阴影。
    在这里插入图片描述
    在这里插入图片描述
    Shaow Mapping存在的主要问题

  • 自遮挡问题
    在这里插入图片描述
    因为阴影贴图受限于分辨率,在距离光源比较远的情况下,多个片段可能从深度贴图的同一个值中去采样。图片每个斜坡代表深度贴图一个单独的纹理像素。

在这里插入图片描述
解决方法:引入一个bias,只有在当前点的深度大于shadow map上对应的深度+bias时,我们才认为它在阴影内,这也是工业界使用的比较多的方法,当阳光与地面垂直的时候,bias就比较小,
当阳光几乎与地面平行的时候,bias就会比较大
LeanOpenGL有一个公式,根据夹角计算bias

float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);

在这里插入图片描述
但这会引入一个新的问题,当bias过大的时候,有一些地方原本该是阴影,却被错误的认为不是阴影,形成detach shadow
在这里插入图片描述
同样有解决方案,Sceond-depth shadow mapping
该方法不仅记录最小深度,还记录第二小深度,比较的时候取最小与第二小的平均值。
如下:
在这里插入图片描述

在这里插入图片描述
假设一根光线照过来,我们不用最小深度来比较,而是用由最小和第二小深度所得到的红色线来做后续的阴影,此处就没有Bias的事情了.
在这里插入图片描述

  • 走样
    这是第二个问题,因为shadow map是一张有大小的图像,当分辨率不够的时候,自然会看到锯齿。

在这里插入图片描述

shadow Mapping的数学基础

在微积分中有很多有用的不等式,但在实时渲染中,我们只关心近似约等于,因此可以将不等式约等于等式使用:
在这里插入图片描述
如果你有两个函数的乘积,你又想把他们的乘积积分起来,你可以将其拆出来,也就是:

两个函数乘积的积分 ≈ 两个函数积分的乘积

首先我们来解释一下为什么右边第一个函数多了个分母.

分母这一项的作用是为了保证左右能量相同而做的归一化操作。

我们来用一个例子来解释这个归一化操作。我们假设f(x)是一个常值函数,也就是f(x) = 2,我们的积分域恒为0-3.

那么约等式左边,把f(x) = 2代入,则可以提出来变为2倍的g(x)积分

而等式右侧第一个函数代入f(x)的积分是2 * 3 =6,分母的积分是3,结果也正好是2.正好也是2倍的g(x)积分.

接下来我们来讨论在什么情况下约等式结果更加准确:

一般需要以下两个条件:

1. g(x)积分的support较小。这里的support我们可以暂时理解为积分域。
2. g(x)在积分域上足够光滑(变化不大)。

此时我们把rendering equation代入这个约等式中:
在这里插入图片描述
我们把visibility看作是f(x),提取出来并作归一化处理:
在这里插入图片描述
红色区域部分时visibility,那么剩下的g(x)部分,也就是shading的结果.
因此其表示的意义就是,我们计算每个点的shading,然后去乘这个点的visibality得到的就是最后的渲染结果。

这也就是shadow mapping的基本思想。

那么什么时候这个约等式比较正确呢?
a) 我们要控制积分域足够小,也就是说我们只有一个点光源或者方向光源。
b) 我们要保证shading部分足够光滑,也就是说brdf的部分变化足够小,那么这个brdf部分是diffuse的。
c) 我们还要保证光源各处的radience变化也不大,类似于一个面光源。

PCF(Percentage Closer Filtering)

接下来进入到软阴影和硬阴影,
硬阴影
硬阴影
软阴影
软阴影
软阴影的效果更加真实,为了实现软阴影效果,我们引入了PCF-Percentage closer filtering
PCF初衷是为了抗锯齿,后来发现可以用在软阴影中,通过吧shadow结果做一个加权平均(filtering)。

在哪Filter?

  • 不是在最后生成的阴影结果中filter,而是在做阴影判断的时候进行filter。在原本的锯齿的结果中进行filter,跟Games101反走样一样,在一个走样的结果中做模糊,还是会得到走样的结果。
    在这里插入图片描述
  • 也不是Filter Shadow Map
    如果直接Filter Shadow Map,那么边界会变得模糊起来,而且在第二次pass的时候得到的结果仍然是非0即1,最后得到的还是硬阴影。

我们之前在做点是否在阴影中时,把shading point连向light然后跟Shadow map对应的这一点深度比较判断是否在阴影内,之前我们是做一次比较,这里的区别是,对于这个shading point我们仍要判断是否在阴影内,但是我们把其投影到light之后不再只找其对应的单个像素,而是找其周围一圈的像素,把周围像素深度比较的结果加起来平均一下,就得到一个0-1之间的数,就得到了一个模糊的结果。
在这里插入图片描述
如图,蓝点是本来应该找的单个像素,现在我们对其周围3 * 3个像素的范围进行比较,由于是在Shadow map上,因此每个像素都代表一个深度,我们让在shadow map上范围内的每个像素都与shading point的实际深度进行一下比较,如果shadow map上范围内的像素深度小于shading point的实际深度,则输出1,否则输出0.

从而得到9个非0即1的值:
在这里插入图片描述
最终我们用得到的加权平均值0.667作为shading point的可见性。在计算阴影的时候我们就拿这个作系数来绘制阴影。
在这里插入图片描述

PCSS(Percentage Closer Soft Shadows)

我们会发现如果filter size越大,阴影本身越软,所以这个方法也就可以去绘制软阴影,也就是pcss技术。
在这里插入图片描述
在这个途中,可以看到笔尖的阴影十分锐利(硬阴影),因此我们认为阴影接受物与阴影投射物之间的距离越小,阴影就越硬
因此,我们要解决的一个问题是我们如何决定一个软阴影的半影区。换句话说,就是filter size 有多大的问题:
在这里插入图片描述
根据相似三角形即可得到对应的相似关系,filter size取决于d-Blocker,接下来就是如何确定blocker的距离呢?
不能直接使用shadow map中对应单个点的深度来代表blcoker距离,因为如果该点的深度与周围点的深度差距较大(遮挡物的表面陡峭或者对应点正好有一个孔洞),将会产生一个错误的效果,我们选择使用平均遮挡距离来代替,所以平常我们指的blocker depth其实是Average blocker depth.

blocker上的每个点距离光源的距离是不同的,深度也是不一样的。这里我们采用取平均深度的方式来表示blocker的深度。

求blocker距离的方法如下:

首先,我们把目标shading point 转换到light space 找到shading point在shadow map上对应的像素。

如果shading point的深度大于这个shadow map上点对应的深度,则说明shadow map上的点就是一个Blocker,然后我们取shadow map上这个点(像素)周围的一些像素,找出能够挡住shading point的点的像素,并求出他们的深度平均值作为blocker的深度。

如果shading point的深度大于这个shadow map上点对应的深度,则说明shadow map上的点就是一个Blocker,然后我们取shadow map上这个点(像素)周围的一些像素,找出能够挡住shading point的点的像素,并求出他们的深度平均值作为blocker的深度。

第一种,就是自己规定一个,比如 4 * 4, 16 * 16,比较简单但不实用.

第二种,是通过计算得到一个范围大小:
在这里插入图片描述
离光源越近,遮挡物会少,所以需要在Shadow map上的一个大区域内查找blocker.

这样我们就得到了PCSS的三个步骤:

  1. 寻找blocker,并计算平均深度。
  2. 通过blocker 深度计算filter size。
  3. 按照PCF方式绘制软阴影。

PCSS本质上就是求出了阴影中需要做PCF的半影部分后再进行PCF的计算,这样动态调节了半影范围,也就是动态设置了PCF的搜索范围,这样我们的硬阴影部分清晰,软阴影部分模糊,动态的实现了不错的软阴影效果。

可以看到,1、3都需要做一个范围查询,计算平均值,这样会使得计算速度严重下降,如何解决呢?就有工业界大佬提出了VSSM的解决方法

VSSM(Variance soft shadow mapping)

该方法主要解决PCSS第一步和第三步慢的问题:
我们回到第三步PCF之中,我们要在shadow map上对其周围的一圈像素的各个最小深度与Shading point比较,从而判断是否遮挡,也就是要求出范围内有百分之多少的像素比它浅.

这个过程很像在考试成绩出来后,你知道了自己的成绩,你想知道自己在班级中的排名,因此你需要知道班级中所有人的成绩从而进行比较来判断自己是百分之几,这就是PCF的做法.

但现在我们就是为了避免这种时间消耗大的做法.

那么一个不错的办法就是,对班级所有人的成绩做成一个直方图,根据直方图我们可判断出自己的成绩排名.
在这里插入图片描述
如果我们不需要那么准的话就可以当做一个正态分布,正态分布就只需要方差和平均值就能得出,更加的方便快速,这也就是VSSM的核心思想,通过正态分布来知道自己大约占百分之几.

VSSM的key idea是快速计算出某一区域内的均值和方差.

  • 均值
    对于快速的求一个范围内的求均值,我们可以想到在games101中学到的mipmap方法.但是mipmap毕竟是不准的,而且只能在正方形区域内查询.因此引入Summed Area Tables (SAT)【一种数据结构】.
  • 方差
    VSSM用结合了期望与方差之间的关系的一个公式来得到方差:
    在这里插入图片描述
    此为止我们就快速获得了均值和方差。那么回到问题本身:

有多少百分比的像素是比Shading point 大 也就是 不会挡住 Shading point的只需要计算出下图 PDF中白色面积 的值就行了。

有多少百分比的像素是比Shading point 小 也就是 会挡住 Shading point的只需要计算出下图 PDF中灰色面积 的值就行了。

在这里插入图片描述
PDF:概率密度函数(probability density function), 在数学中,连续型随机变量的概率密度函数是一个描述这个随机变量的输出值,在某个确定的取值点附近的可能性的函数。
CDF : 累积分布函数 (cumulative distribution function),又叫分布函数,是概率密度函数的积分,能完整描述一个实随机变量X的概率分布。

其实想知道CDF,也就是求出PDF曲线下对应的面积.

对于一个通用的高斯的PDF,对于这类PDF,可以直接把CDF结果,输出为一个表,叫误差函数Error Fuction,误差函数有数值解,但是没有解析解,在C++ 中的函数ERF(lower_limit,[upper_limit])函数可以计算CDF。
在这里插入图片描述
我们用切比雪夫不等式,来近似地求出在知道 期望 和 方差 时候,不考虑是不是正态分布,图中红色面积不会超过等式右边,这里使用了一个Trick的方法,将这个不等式近似为相等.

那么就可以通过均值和方差获得图中红色面积的值。因此就可以不用计算CDF了,而是通过1 - 求出的x>t的面积值得到CDF.但是切比雪夫不等式有一个苛刻的条件:t 必须在均值右边,也就是t大于均值。

加速第三步总结:

1.我们通过生成shadow map和square-depth map得到期望值的平方和平方值的期望再根据公式 得到方差
2.通过mipmap或者SAT得到期望
3.得到期望和方差之后,根据切比雪夫不等式近似得到一个depth大于shading point点深度的面积.,也就是求出了未遮挡Shading point的概率,从而可以求出一个在1-0之间的visilibity.

也就是省去了在这个范围内进行采样或者循环的操作,大大加速了第三步.

如果场景/光源出现移动 就需要更新MIPMAP,本身还是有一定的开销,但是生成MIPMAP硬件GPU支持的非常到位,生成非常快(几乎不花时间),而是SAT会慢一点,这个后面进行分析。

到目前为止VSSM也只解决了第三步PCF Filter的问题,PCSS在第一步要需要求在范围内将所有像素的深度走一遍从而求平均遮挡深度Average Blocker Depth的问题并未解决。

在这里插入图片描述
要计算的是平均深度实际就是蓝色区域平均值,即遮挡物的平均深度
非遮挡像素占的比例 * 非遮挡物的平均深度 + 遮挡像素占的比例 * 遮挡物的平均深度 = 总区域内的平均深度.
总区域内的平均深度我们用mipmap或者SAT去求,然后用shadow map和square-depth map方差,最后根据切比雪夫不等式近似求出非遮挡像素占的比例遮挡像素占的比例
在这里插入图片描述
我们做一个大胆的假设,我们认为非遮挡物的平均深度 = shading point的深度,至此就可以解出方程求出平均深度.但是接受平面是曲面或者与光源不平行的时候就会出问题。

在这里插入图片描述
VSSM的做法实在是十分聪明,采用了非常多的大胆假设,同时非常的快,没有任何噪声,本质上其实也没有用正态分布,是直接用切比雪夫不等式来进行近似。但是现在最主流的方法仍然是PCSS,因为人们对噪声的容忍度变高加上降噪的技术越来越高明,因此大多数人采用PCSS.

  • MIPMAP与SAT
    在这里插入图片描述
    最简单的方法自然是MIPMAP,我们在GAMES101里学过,他是一个快速的,近似的,正方形的范围查询,由于他要做插值,因此即便是方形有时也会不准确.同时当插值的范围不是2的次方时,也就是在两个MIPMAP之间时,还要再进行一次插值,也就是“三线性插值”,这样会让结果更加不准确,因此局限性太大且准确度也不算高.

但是SAT是百分百准确的一个数据结构.SAT的出现是为了解决范围查询(在区域内快速得到平均值),并且,范围内求平均值是等价于范围内求和的,毕竟总和除以个数=平均值.

在1维情况下其实就是一维数组,SAT这种数据结构就是做了预处理,也就是在得到一维数组时,先花费O(n)的时间从左到右走一遍,并且在走的同时把对应的累加和存入数组SAT中,那么SAT上任意的一个元素就等于原来数组从最左边的元素加到这个元素的和,如图SAT数组第2个元素表示原数字前2个元素之和。

那么查询下图中SUM区域总和时候,就是SAT数组中第六个元素减去第三个元素。相当于使用了O(n)的时间,把预计算做了一遍。
在这里插入图片描述
那么在2维(二维数组)情况下 有一个任意矩形(横平竖直),蓝色矩形内的总和为两个绿色矩形内的总和减去两个橙色矩形内的总和。同样可以采用SAT 的方法,做一个表,做出从左上角到这个元素的和。因此只需要查表4次就可以得出精准的区域求和。

在2维情况下,可以通过建立m行中每行的SAT和在每行的sat基础上再建立n列中每列的SAT,最终可以获得一个2维的SAT因此最终的SAT,但是由于gpu的并行度很高,行与行或列与列之间的sat可并行,因此具有m×n的时间复杂度。
在这里插入图片描述

Monment Shadow Mapping

VSSM是为了解决PCSS的问题,但vssm由于做了很多假设,当假设不对的时候会有问题。
在这里插入图片描述
比如右图,只有三个片的遮挡的情况下,那么深度的分布就在这三个遮挡度深度周围,形成了三个峰值,自然就会出现假设描述的不准。
在这里插入图片描述
不是正态分布强行按正态分布算就会出现漏光和过暗的结果。在阴影的承接面不是平面的情况下也会出现阴影断掉的现象。
在这里插入图片描述
我们看图中小车可以发现,在车的底部阴影部分出现了一部分偏白的阴影,这是因为车是一个镂空的状态,如果从底部向LIGHT处看去会发现底板遮挡一部分,车顶附近会遮挡一部分,这就导致了不是正态分布情况,因此才出现light leaking这种情况.

因此人们为了避免VSSM中不是正态分布情况下的问题,就引入了更高阶的moments来得到更加准确的深度分布情况.想要描述的更准确,就要使用更高阶的moment(矩),矩的定义有很多,最简单的矩就是记录一个数的次方,VSSM 就等于用了前两阶的矩。这样多记录几阶矩就能得到更准确的结果。
在这里插入图片描述
如果保留前M阶的矩,就能描述一个阶跃函数,阶数等2/M,就等于某种展开。越多的阶数就和原本的分布越拟合。一般来说4阶就够用。
在这里插入图片描述

SDF

距离场,SDF大多用在与几何之类的方向上,比如我有两个物体的SDF,我们将两个SDF进行Blend操作,从而得到一个新的SDF,也就得到了一个新的几何物体,因为当距离0为实,即可认为是物体的边界,SDF可以很准确地反应物体的边界。几何转换SDF的时候,可以很好地把几何进行过渡。
在这里插入图片描述

Ray Marching

假设我们已经知道场景的SDF,现在有一根光线,我们试图让光线和SDF所表示的隐含表面进行求交,也就是我们要用sphere tarcing(ray marching)进行求交.

RayMarching可以理解为一个贪心思想:
任意一点的SDF我们是已知的,假如在 P 0 P0 P0点,此时我们以 P 0 P0 P0为中心点,以他的SDF值为半径画圆、球,考虑2D的情况,在圆内部,不可能与物体相交,这是一个安全距离,那么每次都利用上这个安全距离,直到与物体相交。
在这里插入图片描述

如果在超一方向trace非常远的距离但仍然什么都没trace到,此时就可以舍弃这条光线,也就是停止了.

Generate Soft Window

将安全距离延申,可以得到safe angle,安全角的概念
在这里插入图片描述
我们取点P为shading point往一方向打出一根光线,光线上的一点a,有一个SDF值SDF(a),也就是在a点以SDF(a)为半径所做的球或圆内是安全的,不会碰到物体.

把shading point和面光源相连,所得到的安全角度越小,被遮蔽的可能越高,就可以认为

safe angle越小,阴影越黑,越趋近于硬阴影;
safe angle够大就视为不被遮挡没有阴影,也就越趋近于软阴影。

因此我们需要知道的应是如何从ray marching中求出safe angle:

在这里插入图片描述

我们以o为起点,沿一个方向推进,仍然是ray marhcing的步骤,在p1点以SDF(p1)进行推进,其余点也是一样,此处主要是为了求safe angle,我们在起点o沿每个点的sdf为半径所形成的圆做切线,从而求出各个点的safe angle,我们最后再取其中最小的角度作为总的safe angle.

那么我们该怎么去计算这个角度?

从图我们可以知道,以p1点为例,从o点到p1的距离为斜边,sdf(p1)是直角边,因此我们用arcsin就可以求出safe angle了.
但是!!!

arcsin的计算量其实是十分大的,因此在shader中我们不用反三角函数.
在这里插入图片描述
只要sdf长度除以光线走过的距离乘一个k值,再限定到1以内,就能得到遮挡值或者说是visibility,而k的大小是控制阴影的软硬程度.

我们从图中右半部分可以看出来,当k值越大时候,就越接近硬阴影的效果,也就是它限制了可能半影的区域:
在这里插入图片描述

k越小,安全角度比较大,半影区域越大,越接近软阴影效果.

K越大,安全角度比较小,半影区域越小,越接近硬阴影效果.

而是求出safe angle,安全角度越大,阴影越软;安全角度越小,阴影越硬.

总结:SDF是一个快速的高质量的软阴影生成方法(比shadow map快是忽略了SDF生成的时间),但是在存储上的消耗非常大,而且生成SDF的花的时间也要很久,SDF是预计算,在有动态的物体的情况就得重新计算SDF。

Environment lighting

在games101中我们知道,环境贴图就是在场景中任意一点往四周看去可看到的光照,将其记录在一张图上这就是环境光照,或者也可以叫做IBL(image-based lighing).这里我们认为看到的光照来自于无限远处,这也就是为什么用环境光照去渲染物体时会产生一种漂浮在空中的感觉,因为光照来自于无限远处.
通常我们用spherical map和cube map来存储环境光照.

如果已知环境光照,此时放置一个物体在场景中间,在不考虑遮挡时我们该如何去得到任何一物体上任何一shading part的shading值呢?

首先要先来看rendering equation:
在这里插入图片描述
在此先不考虑遮挡问题,通用的解法是使用蒙特卡洛积分去求解,但是采样太多才会导致结果比较接近,如果我们对每一个shading point都做一遍蒙特卡洛,会导致效率很低下。

brdf又分为两种情况:

  • brdf为glossy时,覆盖在球面上的范围很小,也就是small support(积分域).
  • brdf为diffuse时,它会覆盖整个半球的区域,但是是smooth的,也就是值的变化不大,就算加上cos也是相对平滑的.
    在这里插入图片描述
    考虑到之前的积分近似公式,可以拆分成两部分:
    在这里插入图片描述
    由于brdf项满足accuary condition,即small support或smooth,从而我们将rendering equation的lighting项拆出让他变为 :
    在这里插入图片描述
    1st stage
    把light项拆分出来,然后将brdf范围内的lighting积分起来并进行normalize,其实就是将IBL这张图给模糊了.

模糊就是在任何一点上取周围一片范围求出范围内的平均值并将平均值写回这个点上,主语滤波的核取多大取决于BRDF占多大,BRDF的区域越大,最后取得的图也就越模糊.
在这里插入图片描述
而这些模糊过的图是我们在进行rendering之前生成的,也就是pre-filtering,Prefiltering就是提前把滤波环境光生成,提前将不同卷积核的滤波核的环境光生成一系列模糊过的图(和mipmap相似),当我们需要时进行查询即可,其他尺寸的图则可以经过这些已生成的通过三线性插值得到.

之前提过,拆分就是为了做一个Pre-filtering,那么做pre-filtering是为了干什么?

在这里插入图片描述
左图为brdf求shading point值时,我们要以一定立体角的范围内进行采样再加权平均从而求出shading pointd的值.

右图为我们从镜面反射方向望去在pre-filtering的图上进行查询,由于图上任何一点都是周围范围内的加权平均值,因此在镜面反射方向上进行一次查询就等价于左图的操作,并且不需要采样,速度更快.

2nd stage
到此我们解决了拆分后的前半部分积分采样的问题,那么接下来我们处理BRDF项采样的问题:
在这里插入图片描述
接下来讲的方法并不是最优方法,现如今已经有更简单方便的方法了,但是本课我们主要是为了学习方法背后的思想.
在这里插入图片描述
我们仍然可以用预计算来解决后半部分积分采样的问题,但是预计算的话我们需要将参数的所有可能性均考虑进去,但是比较多,包括roughness、color等。考虑所有参数的话我们需要打印出一张五维或者更高的表格,这样会拥有爆炸的存储量,因此我们需要想办法降低维度,也就是减少参数量从而实现预计算.

在这里插入图片描述
在microfacet brdf中中,考虑的是菲涅尔项、阴影项以及法线项,由于此时暂时不考虑阴影,此处需要关注的是Fresnel termdistribution of normals
在这里插入图片描述
Frenel term可以近似成一个基础反射率R0和入射角度的指数函数

法线发布函数(NDF)是一个一维的分布,其中有两个变量,一个变量定义是diffuse还是gloosy,另一个 是half vector和法线中间的夹角,可以近似成入射角度相关的数,这样就变成了3维的预计算。

(PS:在这里我们认为反射角,入射角,half vector可以用一个角 θ \theta θ代替).

至此我们有了三个变量:基础反射率r0,roughness α \alpha α和角度 θ \theta θ,三维的预计算仍然是一个存储量爆炸的结果,因此我们还要想办法减少参数量.

所以我们通过将Schlick近似带入后半部分的积分中:
基础反射R0被拆出积分式,需要预计算的两个量就只有 roughness α \alpha α和角度 θ \theta θ,可以将预计算结果绘制成一张纹理,在使用时进行查询即可。

我们可以看到,最后产生的结果是十分满意的:
在这里插入图片描述
那么在有了环境光照情况下如何去得到物体被环境光照射下生成的阴影呢?

严格意义上来讲,这是不可能完成的事,因为以目前的技术来说是很难实现的,要从两个考虑角度来说:

1.many light问题:我们把环境光理解为很多个小的光源,这种情况下去生成阴影的话,需要在每个小光源下生成shadow map,因此会生成线性于光源数量的shadow map,这是十分高昂的代价.

2.sampling问题:在任何一个Shading point上已知来自正半球方向的光照去接rendering equation,最简单的方法是采样空间中各方向上的不同光照,可以做重要性采样,虽然做了重要性采样但仍需要大量的样本,因为最困难的是visibility term.由于Shading point不同方向上的遮挡是不相同的,我们可以对环境光照进行重要性采样,但一个SP周围的visibility项是未知的,因此我们只能盲目的去采样(我个人对盲目采样的理解是,为了确保准确性需要对sp各个方向的遮挡进行采样,因此仍然会生成大量的样本).我们也无法提取出visibility项,因为如果是glossy brdf,他是一个高频的,且Lighting项的积分域是整个半球,因此并不满足smooth或small support,因此无法提取出visibility项.

在工业界中,我们通常以环境光中最亮的那个作为主要光源,也就是太阳,只生成太阳为光源的shadow.

知识回顾

1.傅里叶级数展开:任何一个函数可以写成常数和一系列基函数(不同频率sin和cos项)的线性组合,基函数数量越多越接近于原函数的形状
在这里插入图片描述
2.频率:在空间上图像信号数值的变化是否剧烈,如头发区域属于高频,因为是一根一根的,衣服,背景等变化不剧烈的属于低频.
在这里插入图片描述
频谱最中心处是低频内容,我们可以做一个filtering(滤波),从而去除一系列频率上的内容,我们对这张图用一个低通滤波器,从而把高频的内容去除掉.
在这里插入图片描述
首先我们来说一下卷积,卷积其实就是一个模糊操作,在图上取任意一点,取点的周围一定区域内的像素值进行加权平均并将结果写回这个点,这就是卷积.
在这里插入图片描述
在spitial域上做卷积也就等于在函数上做一个卷积,就等于在频域上做一个 原图频谱 和 卷积核频谱 的乘积操作,我们可以看到卷积核的高频部分几乎是黑的,也就是0,做了成绩操作后原本的高频部分就消失了,逐点相乘后得到的结果在经过逆傅里叶变化得到模糊后的图.
在这里插入图片描述
在spitial域上做卷积也就等于在函数上做一个卷积,就等于在频域上做一个 原图频谱 和 卷积核频谱 的乘积操作,我们可以看到卷积核的高频部分几乎是黑的,也就是0,做了成绩操作后原本的高频部分就消失了,逐点相乘后得到的结果在经过逆傅里叶变化得到模糊后的图.

3.基函数
在这里插入图片描述
把一个函数可以描绘成其他函数的线性组合,如f(x)可以描绘成一系列的Bi函数乘以各自对应的系数最终再相加在一起,这一系列的函数Bi就是基函数.

回归正题,我们要讨论的是如何在环境光照下生成阴影,先从最简单的开始,如果给了你环境光和一个diffuse的物体,在不考虑Shadow的情况下如何去计算shading值?

为了计算shading值,我们引入数学工具----->Spherical Harmonics(球谐函数)

在游戏渲染中,SH有很多应用.比如SH可以用来表示低频部分的环境光照,也可以用来提供light probe的烘培光照等等…

球谐函数(Spherical Harmonics)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值