zoukankan      html  css  js  c++  java
  • 实时阴影渲染(一):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下将编译错误输出到一个文本文件
    在重命名SqlServer数据库时,报5030错误的解决办法
    将毫秒数转换为时分秒
    搜索手机中的所有音频文件
    安卓-去除ActionBar的方法
    Android, JSONLIB , java.lang.NoClassDefFoundError: Failed resolution of: Lnet/sf/json/JSONArray; 原因
    安卓开发错误:The type android.support.v4.app.TaskStackBuilder$SupportParentable cannot be resolved.
    Jar mismatch! Fix your dependencies的问题
    activity和fragment的生命周期
  • 原文地址:https://www.cnblogs.com/wiki3d/p/shadow1.html
Copyright © 2011-2022 走看看