本文是OpenGL 4.0 Shading Language Cookbook的学习笔记。
百分比渐近过滤(PCF)是一个简单,常见的进行阴影边缘反走的技术。它通过在片段周围进行采样,然后计算样本比片段的更接近光源的比例,使用这个比例对散射光和镜面光成分进行缩放,然后对片段进行着色。使用这一技术后,阴影边缘看上去进行了模糊一样。
这一技术的最基础形式由Reeves et al在1987年发表(SIGGRAPH Proceedings, Volume 21, Number 4, July 1987)。它将片段的坐标坐标变换到阴影空间,然后在一定范围内采取若干样本,计算比片段的深度值更接近Shadowmap的比例,利用这个比例来对着色进行衰减。随着采样的区域扩大,阴影边缘产生模糊效果。
一个常见的PCF算法变体只在Shadowmap的纹理附近进行固定数量的采样。使用采样的纹理中更接近光源比例来进行着色衰减。这一方法会在阴影边缘产生模糊效果。尽管这样做在物理上并不准确,但对于人眼而言,它看上去效果还不错。
下面右图的阴影使用了PCF,左图没有。我们在右图中可以看到模糊的边缘,以及走样现象的减少。
在本文,我们使用上面描述的第二种方法,在片段在Shadowmap中对应位置的周围采样固定数量的纹理。我们使用比较结果的平均数来对散射光和环境光成分进行缩放。
我们会充分利用OpenGL对PCF的内建支持。我们使用线性过滤来访问深度纹理。线性过滤下,OpenGL会自动在纹理周围采样四次(执行四次深度比较),然后使用四次结果的平均值作为结果(这些细节依赖于OpenGL的具体实现)。所以,线性过滤开启后,textureProj函数的返回会在0.0和1.0之间。
我们使用OpenGL的内建函数textureProjOffset来实现对纹理的偏移访问。
实现
使用PCF技术进行阴影的反走样,需要我们对之前的专栏文章《使用Shadowmap渲染阴影》中的代码做下面这些修改:
1. 创建用于渲染Shadowmap的帧缓冲对象时,设置深度纹理使用线性过滤。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2. 使用下面的代码作为片段着色器中shadeWithShadow函数的代码:
subroutine (RenderPassType)
void shadeWithShadow()
{
vec3 ambient = Light.Intensity * Material.Ka;
vec3 diffAndSpec = phongModelDiffAndSpec();
// The sum of the comparisons with nearby
// texels
float sum = 0;
// Sum contributions from texels around
// ShadowCoord
sum += textureProjOffset(ShadowMap, ShadowCoord,ivec2(-1,-1));
sum += textureProjOffset(ShadowMap, ShadowCoord,ivec2(-1,1));
sum += textureProjOffset(ShadowMap, ShadowCoord,ivec2(1,1));
sum += textureProjOffset(ShadowMap, ShadowCoord,ivec2(1,-1));
float shadow = sum * 0.25;
FragColor = vec4(ambient + diffAndSpec * shadow,1.0);
}
原理
第一步,我们开启了Shadowmap纹理的线性过滤。开启后,OpenGL就会自动进行4次采样,然后返回四次采样结果的平均值作为纹理采样结果。
在片段着色器中,我们使用textureProjOffset函数进行4次采样(沿对角线)。该函数的第3个参数时坐标偏移,在采样发生前,这个偏移值会被添加到采样坐标上。
线性过滤开启后,每次纹理访问进行4次采样,也就是说一次textureProjOffset函数调用,采样了16个样本。采样的结果求平均值后被我们保存在了变量shadow。
我们通过变量shadow来进行散射光和镜面光成分的衰减。
优化
皮克斯的Fabio Pellacini发表了一篇非常优秀的关于PCF技术的纵览,可以在GPU Gems, edited by Randima Fernando, Addison-Wesley Professional, 2004的第11章找到。如果想要更详细地了解PCF,强烈推荐阅读这篇短小精悍地文章。
PCF技术因为它地简单高效而成为最常用地进行阴影反走样地技术。除此之外,它生成地阴影边缘地模糊效果也常常被用来模拟软阴影,但随着它地模糊边缘地增大,它需要进行地采样个数也需要增加,这限制了它在这方面的应用。在下一篇文章,我们将介绍使用随机采样的方法生成软阴影。