在这章中,把阴影贴图的思路扩展到正确处理全方位的(点)光源中,其中包括了实现细节,也涉及到基本硬件能力不足时的低效运行策略。
首先,这篇文章也谈到了在实时计算机图形学中产生可见阴影的两个流行方法是:
- 模板阴影(stencil shadows)/ 阴影体(Shadow Volume) 相关知识可以参考之前的章 https://mp.csdn.net/postedit/89161545
- 阴影贴图(shadow mapping)相关知识可以参考之前的文章 https://mp.csdn.net/postedit/89207385
模板阴影(Stencil Shadows,也被称Shadow Volume,阴影体)作在《Doom 3》中有所应用,优点是得到大量的GPU支持、独立于光源的种类、产生的阴影质量很高。但缺点是严重依赖于CPU,只能产生清晰的影子,需要很高的填充率,而且不能与硬件(hardware-tessellated)的表面一起使用。
阴影贴图(Shadow Mapping,也译作阴影映射)由Lance Williams于1978年引入计算机图形学,文章发布当时多数好莱坞电影都在使用这个方法,包括计算机渲染和特效。为了计算阴影,阴影映射在场景几何体上投射特殊的动态创建的纹理。它可以渲染清晰和模糊的影子,以及由不同类型的光源产生的阴影,它还可以与硬件镶嵌的表面以及GPU动画的网格(例如蒙皮网格)一起使用。
该文章主要介绍了全方位阴影贴图(Omnidirectional Shadow Mapping)方法,处理的对象是点光源,因为点光源是向四周所有面发散光,所以点光源的阴影贴图由立方体贴图实现。该方法有两个主要步骤:
- 创建阴影贴图
- 进行阴影投射
在创建阶段,对所有把阴影投射到阴影贴图纹理上的物体,渲染它们到光源的距离的平方。而在投射结算,渲染所有接受阴影的物体,并比较所渲染的像素到光源的距离的平方。以下为全方位阴影映射算法的伪代码:
for (iLight = 0; iLight < NumberOfLights; iLight++)
{// Fill the shadow map.for (iObject = 0; iObject < NumberOfObjects; iObject++){RenderObjectToShadowMap(iLight, iObject);}// Lighting and shadow mapping.for (iObject = 0; iObject < NumberOfObjects; iObject++) {LightAndShadeObject (iLight, iObject);}
}
具体实现可以参考 源代码http://http.download.nvidia.com/developer/GPU_Gems/CD_Image/Index.html
其中几个重要的点:
- 从光源点出发,视域必须90度,将物体渲染进立方体贴图六个面
- 浮点纹理和整数纹理的取样
- PCF算法产生软阴影(上篇文章讲到的)如下代码:
vFilter是个数组,记录了周围四个采样点偏移位置,代码中的0.25其实就是除以4的平均值,循环四次后最后相加得到最终结果