• 实时阴影渲染(一):PSSM平行分割阴影图


    PSSM(Parallel Split Shadow Map)平行分割阴影图,是一种根据距离远近采用多个深度纹理渲染阴影的方法

    适合用于室外大场景中的平行光比如太阳形成的阴影

    本系列需要读者了解基本的深度阴影渲染方面的知识

    1 视锥划分

    如下图,以采用三个划分为例:

    这里将视锥体平行划分为3个区域,代号分别为1、2、3

    这三个区域在渲染阴影的时候分别采用不同的阴影图sm1、 sm2、sm3

    这样将1、2、3对应的距离数据打包为一个float3变量splits.xyz,传入片段shader,然后通过以下的代码实现阴影图的选择:

    if (z <= splits.x)
    {
        shadow = depthShadow(sm1,...);
    }
    else if (z <= splits.y)
    {
        shadow = depthShadow(sm2,...);
    }
    else if (z <= splits.z)
    {
        shadow = depthShadow(sm3,...);
    }

    这里z 、depthShadow函数和单个深度纹理阴影的实现类似,区别是相关参数都变成了三份

    图上的三个划分并没有包含全部的渲染区域,因为没有必要渲染特别远的阴影

    各个阴影区域的大小可以根据需要选择合理的算法

    根据实际情况也可以将阴影区域划分为两个或者更多个

    为了平滑 ,最后一级阴影(本例的3)可根据z值做线性淡入淡出

    2 投影矩阵计算

    渲染阴影前需要分别渲染三个深度纹理

    对每一个阴影区域都需要计算对应的正投影矩阵

    计算正投影矩阵可以理解为计算正投影相机的位置、投影大小和相机的up矢量

    下面以单个投影区域为例说明如何计算这三个要素

     如上图,彩色阴影部分为视锥体的单个划分区域

    根据当前相机的位置、FOV、纵横比和远近截面距离可以算出该视锥体的八个顶点(这里为了简化仅画出四个)

    根据光照方向可以用任一垂直矢量作为投影相机up矢量,不过不同的up矢量得到的投影体大小不同,你可以设计专门的算法计算最优的up矢量

    然后再通过光照方向和up矢量的叉积计算出right矢量

    任选一参照点(此例为左下的O点),通过up ight矢量和光照方向可以计算出其它7个点在投影相机空间相对于O点的最大、最小值也就是最小包围盒

    如图所示,相机的位置应在AB的中点D所在的中心线上,其相对于D点的距离为AC的长度加上阴影可能的投影距离(视锥体外的物体投影)

    投影体的长为AB的长度,宽为right方向得到的长度(此图没画出来)

    也可以将视锥体的八个顶点直接转到相机空间计算轴对称包围盒、相机位置,然后再将相机位置变换回世界空间

    不过当场景很大时,正反两次变换造成的误差会非常的大,直接在世界坐标系内计算则不会有这种问题

  • 相关阅读:
    linux学习笔记28--监控命令vmstat,iostat, lsof
    linux学习笔记27--监控命令ps和top,free
    linux学习笔记26--命令wc
    linux学习笔记24---命令grep
    linux学习笔记23--时间命令date和cal
    linux学习笔记22---命令diff和diff3
    linux学习笔记22--命令ln
    Fiddler 抓取 ios 端数据包
    fiddler 清除证书+重新添加证书
    Fiddler 详尽教程与抓取移动端数据包
  • 原文地址:https://www.cnblogs.com/wiki3d/p/shadow1.html
Copyright © 2020-2023  润新知