zoukankan      html  css  js  c++  java
  • 《CSM and PCF》

    在进行阴影绘制的时候,除了blur整张shadow map之外,实现软阴影的方法还有CSMPCF

    CSM:

    CSMCascaded Shadow Map)即级联shadow map,又称作PSSM,它的做法是把相机从近裁剪面到远裁剪面分割成N个子视锥,每个视锥渲染一张shadow map

    一般而言,级联shadow map的几级大小是一样的,比如四级,可以在整张shadow map中分成四份,只是一级的shadow map里面的可视区域最小,阴影边缘锯齿也最不明显;第四级的shadow map可视区域最大,用它做出来的阴影的边缘锯齿也就最明显,但是由于使用到这一级的shadow map的物体都是比较远的物体所以可以这种效果。

    在分级的时候,比如分4级,原来相机只有一个远裁剪面,现在会分成4个,可以进行线性等分,也可以不等分:

    下图中,C0是近裁,Cm是远裁,Ci代表分割线,假如我们想要分割出N个子视锥,那我们就需要求出N-1Ci 
     

    通用算法是: 

    使用混合因子λ将平均切分和指数切分融合起来。 

     

    其中,指数切分公式是: 

    平均切分的公式是: 

    其中,n为近裁,f为远裁,i为切分线,m为子视锥总数。 

    代入最上面的公式,就能得到最终的切分公式。

    利用级联CSM的算法实现shadow map,生成级联的shadow map之后,后面的步骤即和传统的shadow map原理相差不大,不同的是,在传统的shadow map算法中,将当前pixel的坐标转换到light space后,等到的深度值仅仅和唯一的一张shadow map进行比较,现在,在级联shadow map的算发现,是有多张shadow map的,应该根据之前在light space中得到的深度来判断应该使用哪张级联shadow map中的那个,再进行深度比较,其中要注意UV的偏移不要采样到错误的shadow map中的像素,得到错误的比较结果,导致阴影效果出问题。

    关于一些CSM的优化;如果camera不动,角色在场景中走动,穿过两级shadow map的时候会发现阴影效果有明显改变,为了解决这种问题,可以让两级shadow map之间有重叠部分,比如重叠20%,然后对两张shadow map产生的阴影进行混合,这样的好处是完成了两级阴影效果之间的平滑过渡,但是坏处是发现当前pixel的深度位于light space的两级视锥之间的时候需要采样两张shadow map,具有额外的矩阵计算和采样消耗。

    SDSM:

    仅仅按照以上的CSM算法,会在视觉上有一些问题,主要有两个缺点。第一个是,CSM阴影效果影响很大的地方是光锥的集中程度。如果光锥需要包裹整个视锥,那么即便视锥的近平面上有面墙挡住了整个视野,光锥仍然不能集中到可见的pixel上。有一个优化方法是根据视锥内物体的AABB来提高光锥的集中效率,但如果遇上上面说的那面墙,情况并不会得到改善。另一个缺点是,决定区域划分的时候有一个参数,通过对它的调整可以改善近距离屈于或者远距离屈于的阴影质量,但不能两全其美。

    以上两个缺点,I3D2011上的Sample Distribution Shadow Maps可以用很很低的代价同时解决掉这些缺点,在最大程度上优化shadow map上sample的分布。

    另外针对于以上缺陷,可以使用SDSM方法实现,它能够根据可见pixel来动态分配区域划分,完全解决掉这两个问题。

    CSM的两个缺点实际都来自同一个根源:光锥区域是根据视锥的大小,而不是可见pixel的范围来调整。这里所说的pixel范围涉及到两个方面。第一是pixel在view space的深度范围,这会影响到区域的划分。另一个是pixel投影到light space的坐标范围,这影响到scale和bias的计算。很明显最佳情况是,shadow map的sample分布在所有可见pixel上,其他地方不浪费。而这两个方面都可以很简单地通过场景的depth texture得到。

    具体的SDSM算法可以归纳为:

    1.渲染一遍场景,得到depth texture。

    2.统计depth texture,得到最大和最小的depth。

    3.把depth的范围根据log的距离分布平均切成几个区域。

    4.从pixel的depth求出view space position,投影到light space,得到该区域的scale和bias,组成crop matrix乘到projection matrix之后。

    5.对每一区域都生成一张shadow map。

    6.在使用的时候,根据像素在view空间的位置确定自己是在哪个区域,以选择shadow map。

    SDSM仍然是一种CSM。总体来看,SDSM只是不通过光锥,而是通过可见pixel来划分区域和计算crop,这就解决了PSSM的第一个缺点。另外,由于深度是自动划分的,也就不会存在远近不能两全的缺点,也不需要一个额外参数来手工调整。所以PSSM的两个大缺点在SDSM里都不存在了。

    从这里看出,整体程序升级到SDSM不需要改变太多。由于depth texture在deferred rendering里面是必须的,所以1步骤是基本已经有了。对于forward rendering而言,pre-depth也是常用的。 

    PCF:

    PCFPercentage Closer Filtering的缩写;传统算法里,在shadow map里面采样出来的值和depth value进行比较的时候二者是一一对应的,在PCF算法中,可以对shadow map的周边进行采样,然后都和depth value进行比较,比如采样shadow map4次,每确定这次采样处于阴影中就为最终计算的值累计0.25,这样最终得到的值的可能性是0.00.250.500.751.0,该值用于与阴影颜色相乘,以此来决定该pixel处于阴影的程度,实现软阴影效果。

    参考:http://www.klayge.org/2013/05/07/%E5%A4%A7%E8%8C%83%E5%9B%B4shadow-map%EF%BC%88%E4%BA%8C%EF%BC%89%EF%BC%9Asdsm/

  • 相关阅读:
    java设计模式----工厂模式
    使用.Net Core Mvc +SqlSugar +Autofac+AutoMapper+....
    使用 Date 和 SimpleDateFormat 类表示时间
    .Net Core 3.0 IdentityServer4 快速入门02
    .Net Core 3.0 IdentityServer4 快速入门
    微信小程序支付
    微信小程序集成腾讯云 IM SDK
    架构杂谈《十》
    架构杂谈《九》
    架构杂谈《八》
  • 原文地址:https://www.cnblogs.com/DeanWang/p/7143741.html
Copyright © 2011-2022 走看看