zoukankan      html  css  js  c++  java
  • Shadow Acne问题

    ShadowMap是实时渲染中实现阴影效果一种常用的方法,它的基本思路是创建一个光源视角下的深度图;然后在渲染时,将渲染frag的深度和深度图对应的深度进行比较,若frag的深度比深度图的深度值大,则说明它是在阴影下的(有一个物体在它前面遮挡了光线),否则不需要渲染阴影。
    但是在实际的实现中,会有一个问题,如下图所示:

    仔细看上图的地板和方体,可以看到条纹装的阴影,拉近镜头的话如下所示:

    该现象被称作Shadow Acne。其实原因也是不难理解。因为我们创建的深度图终究是离散的数值,对深度图采样只能得到该像素下某一个点的深度值,但实际上同一个像素不同位置的深度值也是有很大差别的,如下图所示:

    图中黄色的一个像素,在渲染时只能将中间的深度值作为该像素的深度值。但在实际渲染场景的时候,像素其他位置的深度值可能会高于或低于深度图存储的值,就会出现这种一部分在阴影中,一部分没有阴影的效果。
    那么该如何解决这类问题呢?最简单的做法是为深度图中读取出的深度图加上一个bias,保证该像素内所包含的frag的深度均位于其下,这样就将该问题解决了。
    我们还可以设置bias的值根据光线和物体本身的normal动态变化:

    float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
    

    但是利用该方法也有一个缺点,那就是利用bias有可能会导致阴影的偏移,如下图所示:

    尤其是在bias的值选的过大时,该现象更加明显。
    其实,想彻底解决该问题只需要一个小小的改动就可以:在渲染深度图时只渲染背面。这样一来,假设该物体实际上被某物体遮挡,那么它的深度值必然高于遮挡物体背面的深度值。反之,假设该物体没有被遮挡,那么它的深度值必然小于它背面的深度值:

    这种方法被称作Peter panning。
    当然,该方法也是有自己的问题的:就是它只能处理闭合的模型(比如长方体),对于只有一个面的模型(比如长方形)就无法渲染它的背面了。这就要求在制作模型的时候就要制作闭合的模型。
    当然,实际上大部分还是用的bias值来处理该问题。只要比较小心得设置它的值,就可以得到皆大欢喜的结果。

  • 相关阅读:
    Linux基础---开关机与帮助
    Linux磁盘管理命令
    批处理之命令补充II
    LeetCode 328. 奇偶链表(Odd Even Linked List)
    LeetCode 岛屿的最大面积(探索字节跳动)
    LeetCode 复原IP地址(探索字节跳动)
    LeetCode 简化路径(探索字节跳动)
    LeetCode 最长公共前缀(探索字节跳动)
    LeetCode 无重复字符的最长子串(探索字节跳动)
    自动机器学习超参数调整(贝叶斯优化)
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/12926299.html
Copyright © 2011-2022 走看看