Lecture 3:Real-Time Shadows 1
-
Recap: shadow mapping
[slides courtesy of Prof. Ravi Ramamoorthi]Issues from shadow mapping and solutions
-
The math behind shadow mapping
-
Percentage closer soft shadows
一、Shadow Mapping
-
A 2-Pass Algorithm
–The light pass generates the SM
–The camera pass uses the SM (recall last lecture)
shadow mapping是一个两趟的算法(渲染场景两遍),第一遍从光源看向场景,输出距离光源最近的最浅深度shadow map,第二遍从相机位置看向场景,配合刚刚的生成的最浅深度图shadow map,渲染出结果。
-
An image-space algorithm
–Pro: no knowledge of scene’s geometry is required
–Con: causing self occlusion and aliasing issues
shadow mapping是一个完全在图像空间中的算法,好处是一旦shadow map已经生成,那么其就可以作为场景中的一个几何表示,为了得到最后的阴影,只需要shadow map即可,而不需要场景中的几何。
但是其会出现自遮挡和走样现象。
1、A 2-Pass Algorithm
Pass 1: Render from Light
Output a “depth texture” from the light source
第一趟从光源看向场景并渲染得到shadow map
Pass 2: Render from Eye
Render a standard image from the eye
第二趟从摄像机看向场景,并将看到的点再次连向光源
Pass 2: Project to light for shadows
Project visible points in eye view back to light source
如果看到的场景中的点到光源的距离与第一步中shadow map记录的深度值相等,则说明该点可见,如果不等,则说明该点被遮挡
2、Visualizing Shadow Mapping
①、The depth buffer from the light’s point-of-view
②、Projecting the depth map onto the eye’s view
Scene with shadows
3、Issues in Shadow Mapping
(1)、Self occlusion
使用shadow map会产生自遮挡的问题,其产生的原因如下:
提前需要说明的是:在一个像素内部其深度是一个常数,所以在第一趟渲染shadow map时,从光源沿某一个像素的方向看向一个场景,看到的一个位置是覆盖该位置的一个像素所代表的深度,也就相当于这个场景在一个像素所覆盖的区域内都是一个常数深度,即shadow map将这样一个场景离散成了一系列小片拼成的场景(如上图红色),由于这个深度是从光源看向场景得到的,所以这些红色的小片与光源方向垂直。
对于上图这样一个平面场景来讲,在第一趟渲染中,从光源沿A点方向看向这个场景中的平面,理应能看到点A,但是由于shadow map将这样一个平面的场景离散成了一系列小片形成的场景,而被橙色的小片所遮挡,则shadow map上记录的是到点B的深度;
那么在第二趟从摄像机看向场景的渲染中,对于同一个点A却可以看到,再将A点连回光源处得到A点深度,但是在第一趟渲染shadow map时,这个方向上却被记录了光源到B点的深度,两趟的深度结果就不一致,导致点A处被认为是被遮挡的状态,导致了自遮挡问题的发生。
根据以上理论,在光源垂直于场景平面照射的时候,问题是最小的,而平行于场景平面照射,问题是最大的。
(2)、Adding a (variable) bias to reduce self occlusion
–But introducing detached shadow issue
我们可以让两次渲染得到的深度值在比较的时候有一个宽容度,差别在某个范围内则认为是相等。由于光源垂直于平面的时候问题最小,那么这时候宽容度可以比较低,而光源平行于场景的时候问题最大,这时候宽容度可以比较高,通过光源与平面的夹角去动态地调整这个宽容度。
但是这样得到的结果依然出现了问题。由于鞋跟处宽容度还是太大,而丢失了原本该有的遮挡。
(3)、Second-depth shadow mapping
–Using the midpoint between first and second depths in SM
–Unfortunately, requires objects to be watertight
–And the overhead may not worth it
在这种方法里,在第一趟生成shadow map时,我们不仅存最小深度,还存次小深度。假设光从上往下照(如上图),那么最小深度就如左图所示,次小深度如中图所示。用最小深度和次小深度的中间深度作为shadow map来和第二趟的深度值比较。
但是其问题是任何模型都要有正反面,就算是一张纸都要做成一个很薄的box。
而且实现保留最小和次小深度本身也不容易,假设有这样一个可以计算的算法,则其输入是一系列无序的数,而始终要保持最小和次小,最小的很好比较,每次跟输入的值比较即可,但是涉及到最小和次小同时比较就要比较很多次。(虽然时间复杂度还是O(n),但是RTR does not trust in COMPLEXITY,实时渲染不相信复杂度,只相信绝对的速度)
(4)、Aliasing
由于shadow map上每个像素都可以理解成一个小片,投影出来的阴影图还会涉及到分辨率等问题,所以会出现锯齿。
二、The math behind shadow mapping
1、Inequalities in Calculus
There are a lot of useful inequalities in calculus
2、Approximation in RTR
- But in RTR, we care more about “approximately equal”
- An important approximation throughout RTR
在实时渲染中我们更关心近似相等,在一系列条件下让不等变成约等。
3、In Shadow Mapping
- Recall: the rendering equation with explicit visibility
- Approximated as
用刚刚的公式可以将渲染方程中的V拿出来做归一化。
这时左边是visibility部分,右边是shading部分,并且两者相乘,这正是shadow map的思路
When is it accurate?
–Small support
(point / directional lighting)
当积分限很小的时候,即小成一个很小很小的点(△),这个式子是准的,也就是当光源是点光源和方向光源时,这个式子没有问题。
–Smooth integrand
(diffuse bsdf / constant radiance area lighting)
当光照L不变,对应一个面光源(积分限是光源所对应的立体角上),面光源内部的radiance都不变,这里我们就可以认为L是完全smooth的,对于shading point,如果BRDF是diffuse的时候是smooth的。
因此当一个光源是面光源且shading point是diffuse时,这时我们也认为得到的结果是准确的。
三、Percentage closer soft shadows
From Hard Shadows to Soft Shadows
软阴影是从本影到没有阴影之间有一个半影区域,在这些区域看向光源,光源会被部分遮挡。
1、Percentage Closer Filtering (PCF)
-
Provides anti-aliasing at shadows’ edges
–Not for soft shadows (PCSS is, introducing later)
–Filtering the results of shadow comparisons
PCF是用来做抗锯齿(反走样),但是后来人们发现这个技术还可以做软阴影,于是有了PCSS
-
Why not filtering the shadow map?
–Texture filtering just averages color components, i.e. you’ll get blurred shadow map first
–Averaging depth values, then comparing, you still get a binary visibility
PCSS不是对渲染出来的阴影图做软阴影处理,也不是对shadow map做处理,而是在阴影判断的时候就做处理(类似于GAMES101中提到的做反走样的流程)
-
Solution [Reeves, SIGGARPH 87]
–Perform multiple (e.g. 7×7) depth comparisons for each fragment
–Then, averages results of comparisons
之前判断任何一个点在不在阴影里的时候,我们将shading point连向light算出深度去跟shadow map对应的这点的深度去比较。
在PCF的算法中,对于一个shading point,依然判断是否落在阴影里,但是投影到light之后不只是找shadow map对应点的像素,同时找shadow map对应该点的像素周围一圈的像素(如7×7),将这一圈的每一个像素深度值都与该shading point深度值去比较,由于每一次比较之后返回的值仅为0和1,做完比较之后把这值取平均,返回到这个点上。
–e.g. for point P on the floor,
(1) compare its depth with all pixels in the red box, e.g. 3×3首先将shading point的点P深度值与shadow map中对应该像素以及周围3×3的每一个像素的深度值分别比较
(2) get the compared results, e.g.
1, 0, 1,
1, 0, 1,
1, 1, 0,然后得到一组返回值
(3) take avg. to get visibility, e.g. 0.667
将这组返回值取平均返回给点P
-
Does filtering size matter?
–Small -> sharper
–Large -> softer
如果卷积盒取小了边缘会很锐利,锯齿问题不会得到改善,卷积盒取大了虽然锯齿没了,但是图片也糊了。
-
Can we use PCF to achieve soft shadow effects?
软阴影的操作就可以通过对硬阴影取一个很大的卷积盒(filter)来实现
-
Key thoughts
–From hard shadows to soft shadows
–What’s the correct size to filter?
–Is it uniform?
2、Percentage Closer Soft Shadows
-
Key observation [Fernando et al.]
–Where is sharper? Where is softer?
物体离投影平面越近,则阴影越硬,离投影平面越远,则阴影越软。
-
Key conclusion
–Filter size <-> blocker distance
–More accurately, relative average projected blocker depth!
如上图,黄色的W是光源,中间的绿色点是投影物体(遮挡物),灰色W是软阴影区域,两个W及其连线组成了一对相似三角形,根据相似三角形原理可以求出软阴影区域W
Penumbr
。这个图可以很好地表明物体离投影平面越近,则阴影越硬,离投影平面越远,则阴影越软。 -
A mathematical “translation”
根据相似三角形将其软阴影用式子表示出来。
-
Now the only question:
–What’s the blocker depth dBlocker
卷积盒filter的大小取决于Light的大小和Blocker的大小。由于Blocker可能是很多不规则物体组成的,因此该处的Blocker要取平均:对于一个shading point来说,在一定的范围内,有多少可以在shadow map上挡住其的像素,这些像素记录的深度的平均值是多少。
-
The complete algorithm of PCSS
–Step 1: Blocker search
(getting the average blocker depth in a certain region)–Step 2: Penumbra estimation
(use the average blocker depth to determine filter size)–Step 3: Percentage Closer Filtering
-
Which region to perform blocker search?
–Can be set constant (e.g. 5×5), but can be better with heuristics
在shading point中,原本就是为了决定在一个shadow map周围多大的范围(filte)做PCF,为了知道这个信息,首先要知道average blocker depth是多少,为了知道这个信息,首先也应该先取一个区域去找average Blocker然后求depth,人们通常一开始固定一个范围大小(如5×5),另外还有更好的方法:
- Which region (on the shadow map) to perform blocker search?
–depends on the light size
–and receiver’s distance from the light
将shading point连向Light,就可以得到其在shadow map上的区域(如上图红色部分),通过这部分区域来确定filter。