PCSS 简介

来源:互联网 发布:植美村旗舰店淘宝电话 编辑:程序博客网 时间:2024/05/17 01:29
本文简单介绍一下Percentage Closer Soft Shadow的原理,由于本人对于这个东西理解很浅,所以有些想法可能是不成熟的。 
谈到PCSS,首先我们要介绍一下PCF(Percentage Closer Filtering),最早在1987年就被人提出的一种过虑算法,当时作者的初衷是用这种算法来改变Shadow Map的走样问题。 
image image 
我把SDK中的Shadow Map简单改了一下,生成了上面两幅图片。左边的渲染图是经过PCF处理的,而右边是最普通的shadow map算法(注意:sdk中的shadow map也是有PCF的,不过只有4个采样点,效果不是很好,而右图中是去除了PCF的效果图)。我们把红框中的像素放大来看,得到下面结果: 
image image 
可以看到,经过PCF处理的Shadow边缘会被模糊,不会有很严重的锯齿。所以PCF可以用来为shadow map做抗锯齿,而且效果还可以接受。 
其实PCF的原理并不复杂,无非就是一种采样方式而已,大致原理如下: 
image  
点采样会根据uv值,找到最近的整数坐标,用该位置的texel作为采样结果。而线性采样则对附近的四个texel进行一定的插值运算。而在Shadow map采样,如果利用点采样或者线性采样得到一个深度值,然后在于即将渲染的pixel的深度进行比较的话,最终结果是二值化的。就是说即将渲染的pixel只有两种情况,在阴影内部或者外部。这种二值化的特性直接导致shadow map是没有半影现象了,加上shadow map的分辨率有限,当其被放大的时候,经常会有精度不足的情况出现,所以会导致出现严重的锯齿。这也是shadow map算法最致命的一个问题了。 
PCF的工作方式大致如下,把即将渲染的pixel的深度值与shadow map中的周围像素一一对比,然后shadow map的一个局部会出现一个二值化的空间。根据1与0数量比例,就可以判断出当前像素与阴影的关系。这种采样方式的一个很重要的优点就是结果不是二值化的,而是从0到1的浮点型数值。换个角度理解,就是说这种采样的结果可以描述当前像素被阴影覆盖的程度,而不是简单的是否被阴影覆盖。从理论上讲,就赋予了shadow map渲染半影的能力了,至少可以简单解决shadow map算法中的边缘走样问题。 
在把目标点变换到Light Space之后,我们需要确定都读取shadow map中的哪些像素。最简单的办法就是按照规律均匀读取一定的采样点,不过这种办法可能会产生一些规律性的东西,所以用泊松分布来读取周围的采样点更靠谱一些。而周围的采样点的范围,我们可以用一个参数kernel_size来线性变换。这个值可以控制半影的大小,当然,半影越大,需要的采样点也越多一些,否则会有明显的走样问题。 
上面简单描述了下PCF的算法原理。那么PCSS相对于PCF多做了些什么工作呢?实际上,如果PCF能够动态适应半影的大小,那么就可以直接做成soft shadow了,PCSS也正是这样工作的。 
PCSS的算法分成三个步骤: 
首先,把目标点变换到Light space,然后找到周围点中的遮挡该目标点的点,记录其与光源的距离。在搜索了一定的遮挡点之后,我们会根据这些遮挡点计算出一个平均遮挡距离。如果目标点不在阴影中,平均遮挡距离为0,PCSS算法直接返回1.0。 
然后,我们假设光源、遮挡物和目标接受点所在平面都是平行的,通过相似三角形的原理,计算出半影的大小。 
image
最后,根据半影的大小,我们可以动态的调节PCF中的搜索范围,从而改变半影的大小。 
上面的步骤没有详细说明,想深入了解的朋友建议还是看看paper里面的描述吧。 
image  
上图是我根据sample里面的代码,加入了PCSS算法所生成的结果。我们看到,飞机距离墙面比较远,所以阴影的很模糊。而距离墙面最近物体投射的阴影都是很清晰的,不过也没有明显的锯齿。 
PCSS可以动态生成软阴影,而且不需要额外处理。只要引擎里面有shadow map算法,更改成PCSS算法并不复杂。 
当然,这个算法也是有一定问题的,在光源距离遮挡物很近的时候,我们看到的shadow会有严重的重影现象(这个问题我没有深入调查,不过可能是用一些插值手段去除其走样吧)。好在许多游戏中,光源被很近的物体遮挡住的现象非常少,该算法应该还有很多用武之地的。
0 0
原创粉丝点击