从条带状阴影谈Unity Shadow

从条带状阴影谈Unity Shadow,第1张

不知道你曾经在Unity中遇到过阴影异常没有,比如近处马赛克状的阴影块?亦或是脱离投影物体的“悬浮”阴影?还是稍远处阴影的突然消失?多块阴影互相叠加处颜色异常的亮度等等。我感觉最让人无法直观理解,也相对常见的一种阴影异常要数“条带状阴影”了。请允许我暂时如此称呼它,因为这很形象。

要重现“条带状阴影”其实很简单,我们甚至可以在不修改任何Unity默认设置的情况下获得这种现象。做个实验,新建一个Unity工程(2019),创建2个Quad对象,然后上下堆叠起来,设置顶层Quad的高度(Y轴世界坐标)为005,设置底层高度为0,调节一下主方向光,使之保持垂直朝向的姿势,既Rotation: (90, 0, 0),一切OK的话大概能得到下图所示的表现,看起来还不错,姑且称之为 现象<0>

我们保持光照和平面位置不变,接下来我们要调节2个重要参数,叫 bias 和 normal bias ,Unity在标准渲染管线模式下,将这2个参数暴露在了Light组件有关shadow的设置参数中;URP模式则可以在 Render Feature的设置栏中找到它们俩。总之找到并设置 bias = 0 , normal bias = 0 ,我们再看看有什么变化:

简单盘点下,在具有一定倾斜角度直接光照下,观察两块相聚非常近的面片中,上方面板向下方面片的投影,我们会发现“条带状阴影”;在此基础上,我们将 bias 和 normal bias 这两个参数归零,面片间投射的阴影恢复正常,但是面片上原本非阴影区域又出现了“条带状阴影”。

无论如何,在解读之前,我们都应该明确这种现象是Unity在处理阴影效果时产生的,因为我们全程只调节了2个控制阴影显示的参数而已。而对于Unity或者一般游戏引擎是如何渲染物体投影效果这一部分,考虑到网上相关内容的资料非常丰富,这里就不再详细阐述了,凝练一下,可以把通用渲染逻辑整理为3个步骤,罗列如下:

步骤1略微展开一下,它涉及到将在光源位置放置摄像机,然后基于光源的视角生成深度图,场景中光源的阴影区也就是光源位置摄影机看不到的地方。ShadowMap本质上是一张深度图,它记录了从该光源的位置出发,能看到的场景中,距离光源最近的表面的深度值。

上图左侧为深度图。右侧在相机位置绘制场景时,能够看到场景中的点Va,其对应的ShadowMap中的位置为a,Va的深度不大于深度图中a位置存储的深度,因此Va不处于阴影

考虑到上述采用shadowmap技术渲染阴影的技术最早可以追述到1978年,人们已经对这项技术能给图形渲染带来的利与弊有了充分的认识。回到 现象<2> 来,在图形学中描述这类现象自然也有其惯用的术语,叫做“Shadow Acne”或者“Self-Shadowing”。这两个英文单词,前者可以翻译为“阴影粉刺”,后者则一般翻译为“自阴影”,一个表形,一个表意,可以说描述得挺好,后续我们还会提到,如果有兴趣了解更多细节,这里有一篇对各种阴影异常表现总结得很好的 技术博文 可以作为参考。

在有了一定的阴影纹理算法基础,以及对所使用数据结构有一定了解的前提下,我们不妨从复盘光照模型开始研究 现象<2> 的成因。

在PL上红色斑点的右侧标记了另一个黑色斑点,毫无疑问它也落在了可见区域中,而且由于光照是垂直向下的,光源到这个黑色斑点的最短距离和一旁的红色斑点应当是一致的,数值上等于图中红色连线的长度,既{Depth}。

当倾斜光照,使之与物体平面(PL)成一定角度相交后,事情就变得有意思起来了。我们都知道,由于透视原理,摄像机近处的物体(PL)相较于远处的物体(光源)会挤占更多的屏幕空间像素,而生成阴影纹理(ShadowMap)的光源空间也有类似的现象,只不过不是因为透视投影导致的(直接光照使用的是正交投影),而是由角度和分辨率共同作用导致的:

现在考察上图中**虚线填充的BCP三角形,在这块区域内的物体(比如顶点P1),到光源处的最短距离必然小于图中红色实线表示的深度值{Depth};同样的在黑色虚线填充的三角形PED中,所有点到光源的距离必然大于深度值{Depth}。根据光照投影算法的定义,在BCP三角形中的点P1,转换到光源空间后的深度值小于该处记录的光源深度,所以P1不在阴影中,这显然是期望的结果;然而另一侧三角形PED中的P2却在相同的算法中被分配到了阴影中,这显然是错误的结论。

通过前面的分析,我们看到,本该处于非阴影状态的三个平面PL上的点 P1、P和P2,在一定光照角度外加一定的纹理分辨率条件下,经过标准光照投影算法处理后会得出错误的结论(三角形PED区域的投影结果),而且导致投影错误的原因也以作图的方法进行的展示。为了能更直观,更量化的反应问题,我们不妨对上述图例作如下简化():

在上图中,黑色粗线表示场景中的平面,**粗线表示为光源所对应的近平面。该近平面会对应产生的ShadowMap。AB表示为这个近平面上对应ShadowMap上一个纹素的区域。假设近平面是一个规范尺寸的正方形,且边长为FSize。对应的ShadowMap分辨率被设置为SSize。那么AB所对应的坐标尺寸通过如下计算可获得: AB = FSize / SSize
我们希望通过某些方式,让纹素AB对应区域在物体平面上的投影CD部分,能够完整的处于图中蓝色虚线的左侧。解决的方法也很朴素直观,按道理只需将ShadowMap中存放的深度值稍微增大点即可,最好是大得刚刚好,恰巧确保CD段处于非阴影区域。

这是第一种修正,针对光线的方向进行偏移:

观察线段(向量)GD,这是我们按照光线方向的最短平移距离,蓝色虚线在平移后恰好位于线段CD的右侧,从而确保了CD段在计算阴影深度时,其在光源空间的深度能够小于ShadowMap采样深度(既图中的BD线段长度)。
求解GD:

除了沿着光线方向直接增加深度之外,还可以沿着法线方向作偏移,间接影响深度值,这就是我们接下来要研究的normal bias法线偏移。

法线偏移其实还分两种实现方式,一种是在将物体顶点转换到光源空间之前,先沿着法线正方向作移动,达到减小片元的深度,具体参考下图:

另一种是在生成ShadowMap时,将物体的顶点沿着法线反方向进行偏移,从而变相得增大阴影的深度值,具体参考下图:

先说第一种方式,它的作用机制不是直接修改阴影纹理的深度值,而是尝试缩小物体在光源空间的深度,因此需要在片元着色器中实现。参考图[normal 1],物体表面沿着自身法线方向移动了距离GM,获得新的位置C'G。将原本CM段的区域整体提升到了蓝色虚线的左侧。我们知道C'G区域的深度取值必然小于等于F点的深度值EF,现在会被光源正常照亮了;至于点G右侧的部分线段可以不用担心,它们将会被相邻的ShadowMap覆盖和处理。

此处的α指的还是光线方向和法线方向形成的夹角。

对于第二种方式,理解起来会直观一些,因为它直接作用于ShadowMap,修改(增加)纹素中的深度值。参考图[normal 2],修正后蓝色虚线向左下方偏移了距离FN, 从而确保CD段区域处于阴影深度线的左侧,被正常照亮。至于偏移量MN的计算,需要分为2步:

其中α指光线方向与法线的夹角;φ指光源方向与法线的夹角。

Unity引入2个bias变量作为控制阴影深度参数的理由,我想至少有2层。其一是增加了灵活性,让用户可以依据场景本身的特质调整光源方向或者法线方向的深度,试想如果Unity只提供了normal bias作为参数,在某些极端情况下,过大的normal bias会导致物体投射的阴影与物体本体脱离的现象(Peter Panning)。

至于另一层理由,可以参考上图,bias对于图中的tanθ曲线,normal bias对于sinθ曲线,θ是光源平面与物体平面的夹角。当光线方向与物体表面越加趋向平行时,光源平面越加垂直于物体平面,θ角越接近90度(π/2),此时使用bias计算得出的修正距离也将随着tan一起趋向无穷大(图中斜向上蓝色箭头)。若此时引入sinθ,则可以平衡bias的影响,这是因为很朴素的道理:sin函数是有上界的(图中蓝色水平箭头),我们可以在θ角小于45度(π/4)时优先使用bias的计算结果,而当θ角超过45度后,将计算偏移距离的权重倒向normal bias一边。

也许有人会问,既然bias计算出的偏移会趋于无穷大,为何不只用normal bias呢?对此之前已经有了回答:我们需要避免Peter Panning现象。

Normal Bias的两种移动方式,在实际效果上并不完全相同。采用在顶点着色器中改变ShadowMap深度值的方式,会在某些情况下导致Normal Bias失效。参考上图,最左侧为产生阴影的普通情况,由于整个单元内采用C点的深度进行比较,所以ED段会错误产生阴影。中间示意图为顶点着色器增加 ShadowMap 深度的做法,在这种方法中,已知从C到D的深度差距记为d,光线和AB段的法线角度为θ,则最小的消除Shadow Acne的沿法线反方向的距离计算为:

在这种情况下,当θ趋向于90°(即光线与AD近乎平行时),最小的距离趋向于无穷大,Normal Bias就很难达到消除Acne的大小。右侧示意图为片元着色器移动片元位置的计算方法,在角度变化的情况下也不会出现最小距离趋近无穷大的情况。但在片元着色器上进行这部分计算,就比前一种方式要更多的计算量。

条带状的“亮暗”渐变,在Unity2019413版本下,使用标注渲染管线,开启软阴影后截屏。

“粉刺”状或者“锉刀”状的暗斑,在Unity2019413版本下,使用标注渲染管线,关闭软阴影后截屏。

吐槽:曾经我也很好奇,为何自阴影的别名叫做 Shadow Acne(阴影粉刺),而不是更加常见的阴影条带。直到我关闭了软阴影并清空了bias修正后看到上图。确实这才是二维格子状纹理出问题后该有的表现,就像下图这样,每个独立的纹素所对应的区域应当被分割成了正方形(正交投影),在二维平面上遇到一定角度的入射光,形成了上图这种规则排列的“粉刺”状暗斑。

进过了上面的分析,我们知道 现象<2> 的出现本质是由于标注阴影算法的缺陷,导致物体自己产生的阴影纹理遮蔽了自己(部分),也就是所谓的“自阴影”。现在我们来看看 现象<1> 的成因,不妨先从2种现象在条件上的差异开始入手。

当场景中存在正常产生阴影的物体时(上图蓝色矩形表示障碍物),全局添加一个Bias,在上图情况中解决了 Self Shadow 的问题,但是正常应该产生的阴影也被消除了。当Bias从小到大逐渐变化时,对一个正常产生阴影的物体来说,它的阴影表现为由靠近物体的一端开始,逐渐消失。这种现象有个专用术语,叫“漏光”(Light Bleeding)。

接下来,我们通过上图复现文章开头引入 现象<1> 的场景布局。还是倾斜入射,这次在物体平面(PL)的正下方多了一层新的平面(UD)。如果不对阴影深度进行修正(bias皆为0),那么来自阴影纹理中像素A投射的等深线CD会与PL平面相交于点P,此时我们在PL上能看到自阴影效果,既图中由点BCP包围的**三角形以及由点PDH围成的黑色三角形区域。当开启bias后,等深线CD分别沿着光线方向和物体法线的反方向做了2次偏移(图中红色箭头),并来带了线段GI所在之处。当UD平面与PL平面距离足够近时,线段GI将于UD平面相交于点P2,同时形成由点EGP2和IJP2围成了2块不同区域。此时我们说在平面UD上出现了“漏光”,既本来不该被照亮的区域(EP2)现在被错误的照亮了。

取消2个bias,有可能消除下层平面UD上投影异常效果。参考上图线段CD所代表的阴影纹理等深平面,并没有出现在平面UD上EJ段的右侧(或者说与线段EJ没有相交),可见这种情况下,UD上能正确显示来自PL的投影。

还是在取消bias前提下,当我们进一步缩小2个平面之间的距离,可以再次复现异常,此时上下层平面可以近似认为是一个平面,下层平面UD会产生源自PL的自阴影。

现象<1> 成因可以说是Unity为了解决 现象<2> ,在引入bias后间接导致的。下面是我总结的一些有助于减缓 现象<1> 的办法,和大家一起分享,当然问题的解决方案是开放的,如果大家有其他好方案,希望不要吝啬得分享出来。

现象<1> 的成因分析,它只会出现在光照方向与物体表面成较小夹角时,我们可以通过合理的布置场景中会导致此类现象的物件位置,优化它们的迎光角度,从而避免出现透光现象。

如果我们对出现 现象<1> 的问题物体投影质量要求不高,完全可以取消该物体的投影选项(不参与阴影纹理的生成,但是可以被动接受阴影),然后使用结构相对简单的投影代理来为该物体实际生成阴影。简言之,我们解决不了问题,那就解决产生问题的物体就好。

如上图中绿色箭头,我们需要通过某种方法,在片原阶段,将平面UD沿着其法线方向的反方向做一次小偏移,使之远离被下压过来的等深线段GI。这里面有个难点,我们如何判断一个像素需要做额外偏移?或者说我们该如何知道物体平面UD需要做额外偏移,而不是物体平面PL呢?一种最简单的方法是把问题丢给CPU,在预处理阶段对不同顶点进行标记,运行时带入到GPU中参与计算。

欢迎分享,转载请注明来源:品搜搜测评网

原文地址:https://pinsoso.cn/meirong/1130286.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-08-31
下一篇2023-08-31

随机推荐

  • 产妇可以做艾灸吗?

    艾灸可以温经通络,调补气血,驱寒祛湿,是很多养生人士非常喜欢的一种养生方式。身边也有很多人平时也在做艾灸保健,懒妈妈去年也花了好多时间去学,目前自己在家也经常做艾灸。对于产妇来说,艾灸也是同样适用的,尤其是一些有产后“月子病”的产妇,月子病

    2024-04-15
    43100
  • 十大公认的美白身体乳

    十大公认的美白身体乳:凡士林美白身体乳、三豆奇异果身体乳、sesderma美白身体乳、Olay美白身体乳、AlphaHydrox果酸身体乳、ASDM强效美白身体乳、森田全净白保湿乳液、日本DAISO大创美白乳液、妮维雅美白身体乳、MENEM

    2024-04-15
    38100
  • 后的套盒有没有防伪码后天气丹套盒真假鉴别

          Whoo后是来自韩国的顶级宫廷护肤名品。而且LG公司每月出的专柜企划版套盒,种类的丰富、包装的华丽以及搭配多变的赠品更是常常让人心动不已。那么,后的套盒有没有防伪码      后的套盒有没有防伪码      后的套盒没有防伪码。

    2024-04-15
    28500
  • 科颜氏男士套盒盒子尺寸

    28寸。颜氏推出了针对男士保湿的品牌产品洗面奶,洗面乳,保湿水等产品组合成了一个礼盒,礼盒大小为28寸。科颜氏是1851年创立于纽约曼哈顿,早期以典型的19世纪药剂师的身份,提供纽约客药水及自然成分提炼的药膏。男生真的不要抵制护肤这件事,白

    2024-04-15
    32600
  • 露安适是哪个国家的-是德国生产的么?

    Lelch®露安适,德国Dehaa Rossun旗下健康护理品牌。品牌定位:具有医学背景的强健薄皮肤专家技术支持:欧盟GMPC认证(德国品质)、SebumCareTM技术、独有年龄分段配方、天然进口原料、通过口腔粘膜无刺激试验、Non-in

    2024-04-15
    26300
  • 小苍兰洗发水是国产的吗

    大家都在问小苍兰魔香洗发水从哪进口的?2个回答3243阅读用户6819128269862022-03-12•Ta已获得425赞同关注小苍兰魔香洗发水不是进口的,是国产品牌,它里面含有八种植物成分萃取,没有任何刺激成分,对头发滋养更加深入,头

    2024-04-15
    29700
  • 精华露和精华液的顺序 正确的护肤流程

    市面上各种各样的精华产品有着不同的护肤效果,精华露和精华液是两种不同种类的精华,无论是质地还是使用感方面都不同,使用顺序也不同。精华露和精华液的顺序精华露和精华液的使用顺序,一般是清爽的用在前,粘稠的用在后头。精华露和精华液其实都属

    2024-04-15
    34700

发表评论

登录后才能评论
保存