GAMES202 PCF PCSS 环境光渲染

软阴影

Percentage closer soft shadows
PCSS

Shadow Mapping

两次渲染场景
第一次从光源看向场景,输出一个深度 shadow_map (每个方向/物体 记录一个最浅的深度)
第二次从相机看向场景,配合第一次的结果

坏处:自遮挡,走样
在这里插入图片描述
在这里插入图片描述

数值精度造成了自阴影:ShadowMap有分辨率,看到的是离散的像素组成的场景
当光线与地面夹角grazing angle时,自阴影影响最大
解决地面自阴影方法:有一个bias区间,可以容忍。但是引发了新的问题,原本应该遮挡的物体产生的阴影消失了。

Second_depth shadow mapping

每个像素不仅存最小深度,还存次小深度。
比较的时候用中间深度
缺点:要求所有的物体都不能是二维平面的,没有人使用。
获得次小深度很难虽然也是O(n),但是实时渲染不相信复杂度

阴影中的数学

微积分Calculus
施瓦茨不等式
米科夫斯基不等式

实时渲染(RTR)中使用不等式作为近似相等的条件

RTR中的重要不等式
在这里插入图片描述
近似等式什么时候是准的:
1.积分范围最小的时候准,对于点光源或者方向光源的时候是准的
2.在g(x)足够低频的时候准
环境光遮蔽会用到

Percentage Closer Filtering (PCF)

抗锯齿
不是对已经有锯齿的阴影进行filter
不是对shadowMap进行filter

一个点是否在阴影里

之前:shading point 连向light 和shadow map上的点做比较,做一次比较
现在:投影到map后,找map周围一圈的像素,一圈上每一个map上的点都和 shading point 的深度做比较,把做完比较的值(非0即1)平均起来,平均的过程中可以加权
得到的visibility 不再是一个非0即1的数了,而是介于[0,1]的数

深度观察

场景中的一个点,知道他在shadow map上是哪个像素,但是不仅仅考虑这一个像素,要考虑它周围一圈的像素,可以把他们各自的贡献加权,靠近的权重大一点,远离的权重小一点。
有多少个texel或者fragment挡住了场景中的这个点,平均一下得到 visibility

Percentage closer soft shadows (PCSS)

ShadowMapping是硬阴影
阴影应该在什么时候硬,什么时候软?
和遮挡物的距离有关

光源两端向Blocker的边缘投射,投射到接收面上,形成相似三角形,也称为半影范围。

第一步 Blocker search 搜索障碍物 (Lec3 79.50)

目标:计算遮挡物平均深度
知道各处filter多大,那么要先知道blocker到shading point的距离
面光源原本是不可能生成一个shadowmap的,为了模拟面光源的软阴影,(把light当作点光源,从中心出发),把camera放在light的中间,看向场景,产生一张shadow map。
从shading point 连向点光源,取周围的一个区域,判断是否都在阴影里。
如果都在阴影里,那么这个点就是一个Blocker障碍物,然后记录下来深度。
把所有Blocker深度平均起来。

在多大的范围做search呢?
shading point连向light,看在shadowmap上覆盖多大的区域。

第二步 Penumbra estimation 用遮挡物平均深度估算出PCF需要覆盖多大的面积

第三步 Percentage Closer Filtering 应用PCF

filter/convolution 公式
加权平均 (需要通过符号函数生成0,1值)
也可以叫 卷积

复杂度

影响PCSS运行效率的主要是 第一步和第三步
这两步都需要遍历

要节省时间

用采样代替遍历,不过结果也变成了近似的,就会产生噪声
需要再处理,进行图像空间的降噪
Real Time RayTracing 再谈

边缘会不会flicker 边缘抖动
会出现

Variance Soft Shadow Mapping (VSSM)

第三步 从PCF开始

对shadow map作直方图
只需要知道均值和方差
就能知道这个深度排百分之几

快速拿到平均

硬件 mipmap (只能做正方形)
Summed Area Tables (SAT)

快速拿到方差

概率论公式
随机变量的方差 = 平方的值的期望 - 值的期望的平方
空间换时间 使用两张shadow map (1.存深度 2.存深度的平方)

用均值和方差近似生成正态分布

就是概率论中的CDF(累积分布函数),正态分布PDF(概率分布函数/概率密度函数)的积分(面积)
代表在这个深度内的像素占多少比例

工业界最好使用高斯的PDF 而不是正态分布的PDF,画出来形状是一样的,但是能够表示更多的东西。
积分出来的CDF值,可以打成一张表,名字叫做error function 误差函数

这个积分没有解析解,只有数值解
这个解在c++有erf函数 (error function)

切比雪夫不等式

可以知道一个随机变量 取的值超过某一个值的概率的上界,但是不需要知道随机变量取的值满足什么分布,只需要知道这个分布的期望和方差。

实时渲染做一个近似估计,把概率的上界作为概率

既然大家都知道了,那我就不演了 (穿山甲乱入)

知道在某个区域内,挡住了这个物体(shading point)的texel或者fragment占多大比例
也就是知道了有多少个texel或者fragment挡住了这个物体,
这个值也就是[0,1]的visibility

比如说 范围是 100 个,知道挡住的占30%
挡住的就是 30 个
visibility 就是 0.7 :(100-30)/100

用了切比雪夫之后就不需要用正态分布了

扩展 OpenGL

texture 是四个通道
深度depth 是一个通道 占红色通道
depth的平方 可以占绿色通道
其实没有额外的存储开销

运行时间开销
给定范围查询深度的平均 O(1)
给定范围查询深度的平方的平均 O(1)
挡住了这个物体(shading point)的texel或者fragment占多大比例 O(1)

缺点

场景中有物体移动就要更新mipmap/SAT
给一张图就能生成mipmap 都是GPU硬件提供的功能,可以认为不花时间。

更多的还是会使用低采样PCSS做阴影,因为人们对噪声容忍度越来越高,降噪手段高了

第一步 Blocker search 搜索障碍物

shadow map 深度z
shading point 深度t
Blocker (z < t) 数量 N2,计算avg 得到 zocc
Non-Blocker (z > t) 数量 N1, 计算avg 得到 zunocc

满足公式 N1/N * zunocc + N2/N * zocc = zAvg

已经通过MipMap和切比雪夫不等式 获得了 比例关系
我们想知道遮挡物的平均深度,
那么就要知道非遮挡物的平均深度
再做一个假设
假设非遮挡物Non-Blocker的深度都和 shading point 一样
zunocc = t

为什么可以这样假设?
因为绝大多数阴影的接收者是平面

MIPMAP

快速、近似、方形的范围查询

如果需要插值,就是不准的估计

如果是一个层与层之间的范围,需要三线性插值,把相邻两层综合起来看

SAT

1D

在这里插入图片描述
查两次 黄色20 - 黄色9

2D

在这里插入图片描述
查四次 绿色1 - 黄色1 - 黄色2 + 绿色2
时间复杂度O(n) n指的是所有的元素个数
行与行之间是可以并行的,而GPU的并行度比行数是高很多的

Moment shadow mapping

前沿的技术,方法比较麻烦。
但是现在对噪声容忍度越来越高了,PCSS重新焕发了生机。
所以没有太多地方在用。

回顾VSSM

VSSM有很多的假设
当假设不成立时,误差就很大。
比如在shadow map 不接近正态分布的时候,
正态分布是单峰值的,有些简单的情况会出现多峰值
在这里插入图片描述
在这里插入图片描述
红色区域为正态估计区域
蓝色区域为实际区域
估值过大导致画面偏黑

偏黑 用户可以接受
但是 阴影中的区域有白色噪声 不可以接受

目标

为了避免VSSM描述分布情况不准确

使用高阶的矩来描述分布
比VSSM 多存储 深度的三次方 深度的四次方
类似泰勒展开 傅里叶级数,通过矩来描述函数分布

工业界,按位存储的弊端:不容易再插值了
在这里插入图片描述

Distance field soft shadows

虚幻引擎使用的就是这个DFSS
SDF ray-traced shadows很快,需要大量存储。
解决了自遮挡、阴影悬浮的问题。

回顾distance function

定义空间中任何一个点,到物体表面最近的一个点的距离。
是一个有向距离场SDF。(后面又说没有方向)
距离为0说明在物体内部。
在这里插入图片描述
blend运动的边界,线性插值(linear interp: lerp)。
对两张图进行线性插值 lerp(A,B)
对两张图的距离场进行线性插值 SDF-1(lerp(SDF(A),SDF(B)))
优点:可以对任意形状做blending

可以表示物体的边界。
最优传输理论Optimal Translate:SDF

距离场的用途:
1.Sphere tracing:在任意一点,SDF告诉了这个点的安全距离,不管往哪个方向走,之只要不超过这个距离,一定不会碰撞。
刚体运动
2.生成软阴影:用SDF得到,大概有多少范围会被挡住的信息,也就是安全角度safe angle。
从shading point发射一条光线到面光源,每个点上有一个安全角度的值,大概多远是没有障碍物的,角度越小看到的东西越少,越黑。
每一步都有一个安全角度,取最小。
arcsin(SDF( p ) / |p - o|)
由于计算arcsin很慢,所以用min{k * SDF( p ) / |p - o|,1.0 }
k控制软硬阴影的程度
也有其他做法 使用sigmoid函数,比较麻烦没有乘k快
值会被拉到两个极端,偏0和偏1

优点:用的时候快(生成的时候慢,用预计算解决)shadowmap慢在每次都要生成shadowmap
缺点:如果是场景、刚体是可以的,如果形变还要重新计算距离场。
存储方法:三维空间中非常密集地采集很多点,等于一个三维纹理。人们不想这么存储,kd-Tree 八叉树,用深度学习压缩毫无意义–解压缩负担更大。

Shading from environment lighting

the split sum approximation

3D场景中显示字符,需要贴图。
如果

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值