最近看了关于shadow map的论文,就最近总结一下:
Shadow Map :用于生成阴影
如果要了解shadow map,最好的办法就是去看dx的demo 。其算法大意如下:
运用渲染到纹理方法(render to target),以场景中的光源为坐标原点,建立光源坐标系,从而可以得到相对于光源的场景深度信息,将其保存在render target上(一般是R32F的surface),之所以选择R32F是考虑到场景的精度问题。这里的R32F就是我们所说的Shadow Map 了,其保存着相对于光源的场景深度信息。
接下来,运用系统默认的render target ,启用depth buffer,将场景中的物体(用世界坐标表示)转化到以光源为基准的投影坐标中,这个变化是这样的:世界坐标--〉物体坐标--〉光源坐标--〉光源视坐标--〉光源投影坐标 。然后比较深度,此时在pixel shader里,深度小于shadow map里相对点深度的,就是光源照到的地方(值为1),否则就是在阴影区(值为0)。注意这里比较深度值时,要将坐标转换到窗口坐标,毕竟shadow map是作为render target产生的。这样值为1的地方就输出颜色,而为0的地方就直接输出黑色了,就是阴影。
优点:不用想volume shadow那样去计算场景几何物体的形状,对于复杂场景只需要产生一张map。
缺点:阴影有锯齿,究其原因在于比较深度时,只有0和1 的输出,这样在阴影边缘就会有1和0的交替出现,从而产生锯齿。这也成为图形领域研究的热点。
PCF(Percentage Closer Filter ) :处理运用Shadow Map产生的阴影锯齿。
大致意思: 就是将深度比较产生的0和1的值放到一个render target里,然后对其进行过滤,这样阴影边缘区域就会出现0.2,0.5....等的灰度值,从而产生了soft shadow。 但是这种过滤方法消耗时间,特别是采样数目比较大的时候。后来简化成横向过滤和纵向过滤,从而减少采样数目。
CSM(convolution shadow map): 卷积shadow map。此方法是运用基于阴影重建,因为深度测试要么为0,要么为1 ,从而可以构造出一个x坐标为[-1,1],y坐标为[0,1]的函数,对此函数进行fft变换,运用基准函数(sin和cos)来重新构建Shadow Map 。 此方法占用内存比较多,需要多个render target。
VSM(variance shadow map):方差shadow map。此方法运用了切尔雪夫不等式,通过shadow map中每个象素的深度值期望和方差来计算灰度值。这是一种估计方法。注意这里的深度值期望是对shadow map进行过滤(横向和纵向)后,得到的深度值。还有这里的shadow map里是两个通道,一个保存深度值,另一个保存深度值的平方。所以过滤后,深度值的期望和深度值平方的期望都能得到了。这样就便于求方差,从而利用切尔雪夫不等式来求每个象素的值。深度值小于期望的,就是光源照到的地方,深度值大于期望的,就是阴影区。
优点:无需多个render target,一个就行。同时效果还不错。
缺点:当多个阴影重合时就出现"light bleeding"。这种artifact也是由于切尔雪夫不等式所引起的。所以以后就有了layers variance shadow map 来解决"light bleeding"