Shadow Mapping

本文探讨了图形学中的阴影生成原理,重点在于通过优化光源视角下的正交投影和有效投射物体来改善阴影模糊问题。通过减小投影范围并仅考虑实际可见的阴影,作者介绍了如何计算阴影图和判断表面阴影的方法,以及如何应用这些技巧来提升渲染质量。
摘要由CSDN通过智能技术生成

先把文字搬过来,图以后有时间补。

感谢@Oo慕白oO大佬的讲解与帮助。

在本文中,会提到两个视角,一个是主视角,一个是光源视角,解释如下。后续说法中的主摄像机和光源摄像机等皆同此理,不做赘述。
主视角:实际渲染场景的视角。光源视角:以光源位置作为摄像机位置、光照方向作为摄像机朝向的视角。提到的光源均指方向光(即天光、平行光)。


【原理】
在真实世界中,阴影是怎么来的?
简单地说,有东西挡住了光源便产生了阴影。
也就是说,处于阴影中的微表面(着色点)与光源之间存在不透明的物体。
如下图左半所示,这等价于在光源视角下,如果表面能被直接观察到(光源直射),那么他不受阴影影响,否则此表面处于阴影之中。


那么我们怎么确定一个微表面是否能被光源直接观察到呢?
在图形学中,很容易就能够想到:能被直接观察到的表面距离光源最近,投影之后的深度值最小。
所以当我们处理一个微表面的阴影时,可以计算其在光源视角下的深度,然后与光源视角下场景的最小深度做比较。
如上图右侧所示,当光源视角下的深度(0.9)大于光源视角下场景的最小深度(0.4)时,表明微表面未被光源直接观察,即处于阴影之中。


【实现思路】
通过上文对阴影原理的分析,我们可以发现为了实现阴影效果,我们需要完成以下两个工作:
首先,记录光源视角下场景的最小深度。

其次,对于某一个着色点,需要知道他在光源视角下的深度并与最小深度进行比较,确定其是否处于阴影之中。
1、如何记录光源视角下场景的最小深度?
这个问题很好解决,我们只需要将摄像机观察方向设置为光源方向渲染一遍场景,即可利用渲染管线得到这一视角下场景的最小深度并将结果保存在一张阴影图纹理中。
PS:由于我们此时讨论的是平行光,所以投影变换可以使用正交投影变换。

2、如何判断某一着色点是否处于阴影之中?
这时我们已知的是当前着色点在世界空间中的位置。那么我们只需要对这一点,进行和在光源视角下观察场景时相同的视变换(v)以及投影变换(p),即可得到着色点投影之后在“屏幕”上的 UV 坐标和深度值 Z。
然后通过此 UV 便可以在阴影图中查询到场景的最小深度 Zmin。
最后通过比较 Z 和 Zmin 就可以判断出当前着色点是否处于阴影之中。


【实现细节】
通过上面的分析可以看出,无论是渲染阴影图,还是判断着色点是否位于阴影中,最核心的工具就是光源视角下的视变换(v)以及投影变换(p)。


1、如何构建视变换 v
为了构建视变换 v,我们需要知道摄像机的位置和观察方向。
这里由于我们使用的是正交投影,所以只要我们把投影矩阵的 near、far 参数设置好,相机的位置是不会影响结果的。
所以我们可以把相机设置到(0, 0, 0)点,而相机的观察方向自然是平行光的光照方向。


2、如何构建正交投影变换 p
为了构建正交投影变换 p,我们需要知道 up、down、left、right、near、far 六个值,也就是一个立方体盒子。
这个立方体盒子需要囊括所有能够投射阴影的物体,所以我们只需要将所有能够投射阴影的物体的包围盒累加就可以得到这个立方体盒子。
有了立方体盒子的数据之后我们就可以得到 up、down、left、right、near、far 来构建正交投影变换 p。


在计算出 v 和 p 之后,我们便可以按照阴影算法的实现思路来添加阴影效果。
但是如下图所示,虽然此时阴影成功渲染出来了,不过可以发现阴影非常模糊(硬阴影算法,阴影边缘应该非常锐利)。
通过分析阴影图,很明显可以看到阴影图的利用率非常低,这也就意味着最终屏幕上的大量像素需要共用阴影图中的同一个像素,此时采样率严重不足,最终导致阴影非常模糊。


【效果优化】
经过上一节末尾的分析,我们知道阴影模糊的原因是阴影图利用率不够。
那么阴影图的利用为什么会如此低下呢?原来场景中距离当前视角非常远的位置同样存在投射阴影的物体。
回顾上文正交投影变换的计算,我们在计算时把所有能够投射阴影的物体都包含进去了,但是实际上并不是所有投影都会出现在屏幕上,也就是部分物体产生的阴影是无法在主视角下看到的。
这些投射阴影物体将用来计算投影变换的立方体盒子撑的非常大,最后导致的结果就是我们真正需要使用的部分在阴影图中的占比非常小。

1、如何提高阴影图的利用率?
通过上面的分析,为了提高阴影图的利用率,就需要减小用来计算投影变换的立方体盒子的大小,借此剔除掉无效的投射阴影物体。
这里我们提出有效接收阴影物体和有效投射阴影物体两个概念:
有效接收阴影物体:在主视角下可以观察到的接收阴影物体。

有效投射阴影物体:有可能将阴影投射到有效接收阴影物体上的投射阴影物体。

那么为了提高阴影图的利用率,就需要获取所有有效投射阴影物体,用他们的包围盒来构建正交投影矩阵,最后达到提高阴影图利用率的目的。

2、怎么找到所有的有效投射阴影物体?
根据有效投射阴影物体的定义可以知道,为了获取有效投射阴影物体,我们需要先得到有效接收阴影物体。


在主视角下裁剪场景,通过裁剪的接收阴影物体就是有效接收阴影物体。
如下图所示,累加有效接收阴影物体的包围盒记为 ReceiverBB。


在光源视角下,通过 ReceiverBB 框定的范围裁剪场景,此时得到的物体便是有效投射阴影物体。
如下图所示,有些物体可能不在主视角内,但是其投影可能落在有效接收阴影物体上,所以他们也是有效投射阴影物体。


得到所有有效投射阴影物体之后,累加他们的包围盒记为 CasterBB,CasterBB 便是可以用来正确计算正交投影矩阵的最小立方体盒子。


3、阴影优化效果对比
经过上面对正交投影变换的优化,可以看到阴影图的利用率大幅上升,阴影边缘也符合我们的预期,变得足够锐利。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值