ShadowMap 中的 Shadow Asne

阴影技术中最简单的一种(其他的可以算作他的变种)是所谓的shadow mapping(适用于平行光)。

它需要事先为场景中的物体,在以光源为视角的视口内,渲染一张深度图。

在那个视口里,只有最靠近光源的片元才能将自己的深度写入这张深度图。

随后,就正式开始渲染场景了。在正式的片元着色器中,需要先求出片元在光源坐标系内的位置,用xy当作uv坐标值去采样深度图里的深度值,同时用z值和这个深度值比较,如果自己的z值大于深度值,就判定自己在阴影里,光照结果会忽略除了环境光以外的所有成分,反之,判定自己不在阴影里,使用正常的光照结果。

看起来滴水不漏,但是这里面隐含着一个严重的问题,就是所谓的shadow asne ,他会造成画面中出现不可言状的光暗相间的条纹。当物体表面越和光源方向倾斜且越远,越容易产生这样的问题。他的成因可以用这张图表达(图中的camera居然代表光源位置...)。


首先思考,所谓的“片元在光源坐标系内的位置”是怎么得到的? 他是通过插值 顶点在顶点着色器乘以矩阵后的结果得到的(把顶点变换到世界坐标系再变换到光源坐标系),所以他是连续的(图中的GeometryPlane)。而深度图的采样点是离散的(图中蓝线),不同的uv坐标值完全可能采样到同一个离散的点上,这样就出了问题。因为随后,我们会用片元的z值去和采样到的深度值做比对,如图所示,每一段蓝色的斜坡就代表同一个采样到的深度值,黄色线段代表:线段上的点的z值会比采样到的值小,而黑色的线段(不包括最左边多出来的)表示:线段上的点的z值比采样到的值大。采样到了同一个深度值的连续坐标点们就会一会儿判定自己有阴影,一会儿判定自己没有阴影。。。 画面就出现了明暗相间的条纹。

(如果想进一步形象化地思考什么是多个坐标点采样到了一个深度值。可以想象如下场景。

此时,请想象你是一个光源(很亮...),然后双手拿着一大块透明玻璃举到眼前,玻璃被整齐地分成了多个小格,此时,你开始远离场景,距离越远,每个小格中出现地物体就越多。格子就是深度图的所有采样点,格子中出现的物体就是所谓的坐标点。越远,越多)

解决的方法异常简单,只要将深度图的深度值整体升高一点点(表现在图中就是斜坡往远离光源的方向,也就是右下角移动一段距离),以使得这些连续的坐标值在和采样点深度比对的时候,统一胜出,使得自己永远不判定在阴影。这段距离就是所谓的shadow bias。

另外,为了不破坏真实地深度信息,需要尽可能地让bias小一点

比如bias的程度可以按照当前片元法线和光源方向的夹角大小来优化,夹角越大意味着图中蓝线需要往下移动更多的距离才能让plane永远胜出深度比对。所以bias可根据夹角的cos值来动态的调整,这样可以使得所有片元都有属于自己的bias,不至于影响到整体场景的信息。

还有如果场景中的物体正面剔除后不影响遮挡关系的,可以在渲染深度图用正面剔除替代背面剔除。以使得深度图内的值更'深'。

来源:CSDN,作者:zwlstc,转载此文目的在于传递更多信息,版权归原作者所有。
原文:https://blog.csdn.net/zwlstc/article/details/86591056

最新文章