GAMES202-复习01

回顾一下GAMES202的知识.

Graphics Pipeline

以下是课上提出的的光栅化的Graphics Pipeline.

Shadow Mapping

目前解决SM问题常用的解决方法是2-Pass Algorithm. 简单的来说就是每个光源自己生成自己可以照射到的Z-Buffer

2-Pass Algorithm

: 是一个Image Space的方法, 并且是硬阴影
Pro: 不需要关于scene的geometry信息
Con: 会造成自遮挡(self occlusion)以及走样(aliasing)的问题

Self Occlusion

由于数值精度所造成的, 实际上, 从光源方向看过去平的地面其实并不是平的(不是连续变化的), 其总会有跳动, 就会导致前面的会对后面的产生遮挡.

解决方案:
1. 添加一个bias, 并且这个bias可以根据夹角大小动态调整, 用来忽略掉由于精度问题所产生的遮挡, 但是如果bias过大,会造成人后面的阴影并不连续.

  1. Second-depth shadow mapping 需要保留模型的第二面信息, 类似于说用模型的第二个最小值? (没有实现过, 不太懂具体的原理). 这个方法用的人不是很多.

Aliasing

数学理论分析:

由下图可知, 通过RTR中的一个近似, 我们可以将渲染方程变换到下面的形式:

其中\(V(p, /omega_i)\)这一项是表征能不能看到的, 也就是visibility项
可以看到, 当是点光源在作用时, 支撑集很小, 满足条件一, 当采用diffuse 或者是 区域照明是, visibility这一项近似是连续的, 满足条件二.

PCF(Percentage cloaser Filtering)

这是用来消除anti-aliasing的方法, 并且它是在results of shadow comparisons上进行filter的, 这一点很重要. 大概算法如下图所示:

如何用PCF来实现软阴影呢? 能不能实现呢? 重点在于你filter correct size的大小

PCSS(Percentage closer soft shadows)

刚刚说了, 2-Pass Algorithm产生的阴影是硬阴影, 然而对于面光源, 我们平常看到的阴影都是有过度的.

参考上文PCF, 一个重要的观察是: 往往离被遮挡的物体越远, 其阴影越软, 所使用的filter correct size就越大.

这里关于blocker Size的大小的选择, 是利用了一个相似三角形的原理. 下面粘一下PCFF作业中的实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
float findBlocker(sampler2D shadowMap, vec2 uv, float zReceiver) {
// This uses similar triangles to compute what
// area of the shadow map we should search
float searchRadius = LIGHT_SIZE_UV * (zReceiver - NEAR_PLANE) / zReceiver;
float blockerDepthSum = 0.0;
int numBlockers = 0;
for (int i = 0; i < BLOCKER_SEARCH_NUM_SAMPLES; i++) {
float shadowMapDepth =
unpack(texture2D(shadowMap, uv + poissonDisk[i] * searchRadius));

if (shadowMapDepth < zReceiver) {
blockerDepthSum += shadowMapDepth;
numBlockers++;
}
}

if (numBlockers == 0)
return -1.0;

return blockerDepthSum / float(numBlockers);
}

float PCSS(sampler2D shadowMap, vec4 coords) {
vec2 uv = coords.xy;
float zReceiver = coords.z; // Assumed to be eye-space z in this code
// STEP 1: blocker search
poissonDiskSamples(uv);
float avgBlockerDepth = findBlocker(shadowMap, uv, zReceiver);

// There are no occluders so early out (this saves filtering)
if (avgBlockerDepth == -1.0)
return 1.0;

// STEP 2: penumbra size
float penumbraRatio = penumbraSize(zReceiver, avgBlockerDepth);
float filterSize = penumbraRatio * LIGHT_SIZE_UV * NEAR_PLANE / zReceiver;

// STEP 3: filtering
// return avgBlockerDepth;
return PCF_Filter(shadowMap, coords.xy, zReceiver, filterSize);
}

VSSM(Variance Soft Shadow Mapping)

PCSS总共有三步: 第一步: 找到block(SM中)的平均深度 第二步: 计算相似关系, 计算需要滤波的filter size 第三步: 对这个filter size进行滤波

第一步和第二步都是非常慢的

将它转换为一个概率的形式(注: VSSM用的不是正态分布(并没有定义这个分布是不是正态分布), 用的是切比雪夫不等式):

用的结构有两种:

可以解决第一步和第三步, 方法不太一样.

PCSS 和 VSSM

PCSS用的更多一点, 因为降噪的方法目前比较好了.

Moment Shadow mapping

相当于对VSSM的改进, 利用更高的矩来更好的模拟实际的分布.

Distance Field Soft Shadows

TOOLS(MIPMAP & Summed-Area Variance Shadow Maps)

MIPMAP

SAT(Summed-Area Tables for Range Query)

是一个非常经典的数据结构: 前缀和 Can we speed up building SAT?

Distance Functions

Distance Fields 的应用: