【GAMES202】Real-Time Shadows2—实时阴影2

一、PCSS回顾

上一篇我们说了如何用PCSS是实现软阴影,这个过程是没有任何问题的,但是有一个速度的问题,因为PCSS涉及到非常多次对纹理特定某一块区域遍历的操作(工业界一般都是用在该区域采样的方式,会因此产生噪声,但是后续会再做图像空间降噪,包括时间累积和滤波),这节我们将讲解如何把比较慢的第一步的Blocker search和第三步的Percentage Closer Filtering变快。

二、VSSM/VSM—Variance Soft Shadow Mapping

1.VSSM的基本思想

VSSM就是为了针对性解决第一步和第三步速度慢的问题而提出的,先回忆一下我们在第三步干了什么,我们在Shadow map上一块区域内找有多少个texel上记录的深度是小于/大于该着色点的,然后得出一堆非0即1,再做(加权)平均。这里GAMES202里闫老师做了个类比,这个问题非常像你在一场考试中拿了多少分,而此时你想知道你排百分之几,而如果把所有的同学成绩都看一遍这就相当于我们前面PCSS所做的事情,这太慢了,所以我们想提出另外一种方法。

相对来说比较好的方法是如果我们有一个直方图,直方图又比较详细,那我们很轻易的就知道我们排百分之多少,那如果再不准一点呢?我们可以直接把它当成正态分布,这样我们直接就可以根据我们的成绩来估计我们排在前百分之多少了。

那么正态分布我们定义它的时候需要什么呢?只需要均值(期望)方差即可。

也就是说VSSM的思想就是快速的计拿到范围内的均值和方差求出当前区域内深度的正态分布,以此来得出我们当前的着色点的深度在当前范围内的texel的深度中排名百分之多少。

而框出一片区域想快速得到均值这种方法我们在GAMES101中讲过,也就是Mipmap,但是我们需要注意Mipmap其实是不准的,而且只针对正方形。能够更精准的在2D上矩形中求均值的数据结构叫做Summed Area Tables,简称SAT

至于方差,我们可以用概率论与统计中一个非常经典的公式来求得,如上图。但于此同时,我们需要在原本的Shadow Map基础上多记录一个通道,它用来储存深度的平方。(我们不需要多生成一张Texture记录深度的平方,只需要在RGB三个通道中多一个通道顺手记录深度平方即可)

而事实上在概率论中,我们想求得东西也就是上图中阴影区域的面积,也就是CDF。CDF(x)代表了有多少值小于x,也就是上图中右边的曲线。至于如何求出这个面积,可以通过高斯分布的查表或者error function的解析解,但我们这里不采用这种形式因为很麻烦,VSSM采用了切比雪夫不等式来近似。

2.切比雪夫不等式—Chebychev’s inequality

切比雪夫不等式可以在我们不知道随机变量满足的分布是什么样子的情况下,告诉我们一个随机变量超过某一个值的概率,它只需要知道这个分布的期望和方差即可。如上图,我们不知道上图的分布具体信息,但是我们知道它的方差和期望,如果真的给了我们一个值t(t值必须大于均值),我们通过不等式可以知道随机变量大于t的概率,也就是上图中红色的面积不会超过不等式右边那一大堆东西。同时上一篇我们提到,在实时渲染中,我们通常会把不等式当成约等式使用,也就是说切比雪夫不等式在这里给了我们对这片红色面积的一个不错的估计。

因此我们就可以用更简便的方法计算上面提到的CDF实际上VSSM在实际操作过程中由于切比雪夫不等式的缘故,故根本不涉及到正态分布以及任何其它分布的定义和计算

3.回到Blocker search

解决完了第三步我们再回头看第一步的操作,在第一步也就是Blocker search中我们对比区域内的所有texel的深度z和着色点的深度t,如果z<t,则该texel为遮挡物,否则则不是,然后计算遮挡物的平均深度Zocc和非遮挡物的平均深度Zunocc。但显然这太慢了。

我们观察一下上面的等式,很容易理解,因为非遮挡物的比例+遮挡物的比例=1。我们最终的目的是知道Zocc,N我们知道,Zavg我们由SAT或Mipmap也可以很快拿到,N1可以由前面提到的切比雪夫不等式得到,N2则为1-N1,那么只剩下了Zunocc,那么Zunocc怎么得到呢?

这里VSSM做了个更大胆的假设,Zunocc就等于t,也就是上面红色数字的平均深度值就假设为着色点的深度。当然这个假设过后,如果接受阴影的不是平面或者阴影接收面和光源不平行的时候就会出现一些问题。

4.SAT—Summed Area Tables

给定矩形范围内的查询,我们最先想到的是GAMES101里面提到的Mipmap,但是它的特性是近似,快速,正方形 ,也就有局限性,近似代表不准确,并且层与层之间要进行插值,而正方形则是自身限制。

因为Mipmap范围查询的诸多问题,我们提出一种新的数据结构来进行精确的范围查询,也就是SATSAT前缀和算法是紧密结合的。并且由于范围求平均和范围内求平均是一样的,我们只需要快速求和即可。

看上图中的一维数组,蓝色数组是我们查询的对象,如图如果我们正常求上面的sum,那么时间复杂度是O(n),我们想避免它。于是我们使用了SAT,SAT实际上就是一次预计算的处理,我们在数组之外生成的SAT每个SAT的第n个元素记录数组前n个元素的和。而此时,当我们想求sum的时候,只需要用SAT[5]减去SAT[2]就可以了。

理解了一维我们再来看二维,如图如果我们要查询上图中蓝色区域的和,那么如图所示步骤,我们可以通过最左上角坐标和蓝色方形右下角的点组成绿色大方形,然后减去两个橙色方形,而因为多减了一个小方形,我们最后再加一个小的方形就可以得到蓝色区域内的和了。

橙色方形和小绿色方形的坐标都可以由左上角坐标和蓝色方形的右下,右上,左上角坐标得到。

这样我们看到我们只需查询4次SAT就可以得到任意一块矩形区域内数值的和了。同时因为GPU的并行度行列计算并行,构建SAT的时间复杂度O(m*n)可以一定程度减小。

5.VSSM的问题

1.分布假设问题

我们之前说过使用切比雪夫不等式的时候也好还是最开始假设的时候也好,我们都假设遮挡关系符合一个类似正态分布,但实际上如果是上图中右图的情况,反而不能这样假设,而它的分布是尖锐的峰值。

同时,在某些情况,因为分布估计不仅可能完全准确符合实际分布,实际计算出的阴影可能在某些地方突然变黑,但这种情况人们可以一定程度上接受,但人们无法接受有时因为分布估计的误差导致阴影突然变白,也就是漏光,如下图的车子阴影。

2.阴影接收物非平面 

其次是阴影接收物不是平面的问题,因为我们在Blocker search的时候把Zunocc直接当成了着色点的深度t,因此非平面会导致阴影断裂如上图的蓝黄色的平面渲染图。

3.切比雪夫不等式自身局限

其次,切比雪夫不等式自己的问题,我们的着色点深度t必须大于分布的期望值。

 

三、MSM—Moment Shadow Mapping

Moment Shadow Mapping只解决了我们VSSM中的第一个问题,也就是深度值分布描述不准的问题,它采用的方法是使用更高阶的Moments,也就是更高阶的

这里的矩简单理解,我们记录一个数的1次方,2次方,3次方,最后记录到几次方就是保留了前几阶的矩。

我们回忆VSSM干了什么事,我们只采用了前两阶的矩,然后来计算它的方差。由此我们想到,那自然阶数越多,得到的越准确。

如果保留前m阶的矩,我们就可以表示一个由一系列阶跃函数组成的函数,并且可以表示的台阶为m/2个台阶,如上图中深绿色的函数,保留了4阶矩,于是有两个台阶,于是就可以更好的还原蓝色的线,也就是CDF,类似于某种展开。正常情况下,用四阶的矩已经足够了。

至于如何根据前四阶的矩,我们怎么得到这条绿色的线,这是非常非常复杂的,这里就不说了,有兴趣的朋友自行搜索。

在工业界中有一些存储的小细节,比如4阶的矩,我们如果想用float32存储,可以把float32拆成四个8位的来存储,也就是packing打包,使用的时候再解包也就是unpacking,只不过这样做了之后我们就无法插值了。

最后可以看到,MSM的效果比VSSM效果好很多,没有漏光现象,如上图。

参考

Lecture4 Real-time Shadows 2_哔哩哔哩_bilibili

GAMES202_Lecture_04 (ucsb.edu)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper集群单节点启动成功但未同步其他节点数据

首先排查节点启动是否正常&#xff1a; 在zookeeper的bin目录下执行&#xff1a;sh zkServer.sh status 判断当前节点数据leader 还是follower 节点都启动正常&#xff0c;但某一个zookeeper集群节点&#xff08;下面简称“异常节点”&#xff09;不同步其他节点数据&#xf…

SQL-每日一题【1321. 餐馆营业额变化增长】

题目 表: Customer 你是餐馆的老板&#xff0c;现在你想分析一下可能的营业额变化增长&#xff08;每天至少有一位顾客&#xff09;。 计算以 7 天&#xff08;某日期 该日期前的 6 天&#xff09;为一个时间段的顾客消费平均值。average_amount 要 保留两位小数。 结果按 …

最新两年工作经验总结

最新两年工作经验总结 前言URP的使用1&#xff1a;如何开启URP1、老项目升级为URP2、创建新项目时选择URP创建 2&#xff1a;URP阴影的设置 PolyBrush的使用&#xff08;地图编辑插件&#xff09;制作山峰or低谷边缘柔化雨刷上色制造场景中的物体贴图地形创建容易踩坑的点ProBu…

java 工程管理系统源码+项目说明+功能描述+前后端分离 + 二次开发 em

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显…

【C++习题集】-- 堆

&#xff08;用于复习&#xff09; 目录 树概念及结构 名词概念 二叉树概念及结构 特殊的二叉树 满二叉树 完全二叉树 运算性质 二叉树存储结构 顺序存储 链式存储 堆 - 顺序存储 堆的性质 堆的实现 堆的应用 堆排序 直接建堆法 树概念及结构 概念&#xff1a…

编写Dockerfile制作自己的镜像并推送到私有仓库

说明&#xff1a;我将用到的私有仓库是Harbor&#xff0c;安装教程参考我的这一篇文章&#xff1a; 安装搭建私有仓库Harbor_Word_Smith_的博客-CSDN博客 一、案例1 1、要求 编写Dockerfile制作Web应用系统nginx镜像&#xff0c;生成镜像nginx:v1.1&#xff0c;并推送其到私…

【高级IO】- 五种 IO 模型 | 多路转接 - select

目录 IO的基本概念 什么是高效的IO&#xff1f; 五种IO模型 阻塞IO 非阻塞IO 信号驱动IO IO多路转接 异步IO 同步通信VS异步通信&#xff08;synchronous communication / asynchronous communication&#xff09; 同步通信VS同步与互斥 阻塞VS非阻塞 其他高级IO …

JavaScript高级

1、JavaScript面向对象 1.1、面向对象介绍 ​ 在 Java 中我们学习过面向对象&#xff0c;核心思想是万物皆对象。在 JavaScript 中同样也有面向对象。思想类似。 1.2、类的定义和使用 结构说明 代码实现 <!DOCTYPE html> <html lang"en"> <head>…

十问华为云 Toolkit:开发插件如何提升云上开发效能

众所周知&#xff0c;桌面集成开发环境&#xff08;IDE&#xff09;已经融入到开发的各个环节&#xff0c;对开发者的重要性和广泛度是不言而喻的&#xff0c;而开发插件更是建立在IDE基础上的功能Buff。 Huawei Cloud ToolKit作为华为云围绕其产品能力向开发者桌面上的延伸&a…

快速实现SAP的移动化和流程优化

热门议题&#xff1a; 1、企业如何快速解决人员移动办公的需求&#xff0c;比如在苹果安卓手机&#xff0c;平板电脑&#xff0c;MAC登录SAP。2、企业如何解决用户经常抱怨的流程复杂&#xff0c;操作繁琐&#xff0c;难以使用等问题 公司介绍&#xff1a; Synactive,Inc. 是…

8. 实现业务功能--用户注册

目录 1. 顺序图 2. 参数要求 3. 接口规范 4. 创建扩展 Mapper.xml 5. 修改 DAO 6. 创建 Service 接口 7. 实现接口 8. 测试接口 9. 实现 Controller 9.1 密码加密处理 10. 实现前端界面 业务实现过程中主要的包和目录及主要功能&#xff1a; model 包&#xff1a;实体对象 d…

vue 弹出框 引入另一个vue页面

为什么要这么做,适用于在一个页面逻辑比较多的时候,可以搞多个页面,防止出错 index页面点击解约按钮,弹出框 进入jieyue.vue 核心代码 <el-buttonsize"mini"type"text"icon"el-icon-edit"v-if"scope.row.delFlag 0"click"j…

探索人工智能 | 模型训练 使用算法和数据对机器学习模型进行参数调整和优化

前言 模型训练是指使用算法和数据对机器学习模型进行参数调整和优化的过程。模型训练一般包含以下步骤&#xff1a;数据收集、数据预处理、模型选择、模型训练、模型评估、超参数调优、模型部署、持续优化。 文章目录 前言数据收集数据预处理模型选择模型训练模型评估超参数调…

websocker无法注入依赖

在公司中准备用websocker统计在线人数&#xff0c;在WebSocketServer使用StringRedisTemplate保存数据到redis中去&#xff0c;但是在保存的时候显示 StringRedisTemplate变量为null 详细问题 2023-08-20 10:37:14.109 ERROR 28240 --- [nio-7125-exec-1] o.a.t.websocket.po…

NAS个人云存储 - 手把手教你搭建Nextcloud个人云盘并实现公网远程访问

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

LeetCode ——二叉树篇(三)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 二叉树的定义及创建见&#xff1a; LeetCode ACM模式——二叉树篇&#xff08;一&#xff09;_要向着光的博客-CSDN博客 目录 116. 填充每个节点的下一个右侧节点指针 117. 填…

Maven介绍_下载_安装_使用_原理

文章目录 1 Maven介绍1.1 Maven的介绍1.2 Maven的作用 2 Maven下载与安装2.1 官网下载2.2 文件目录2.3 环境配置 3 Maven基础概念3.1 仓库分类3.2 依赖坐标3.3 坐标组成 4 Maven配置4.1 本地仓库配置4.2 远程仓库的设置4.3 镜像仓库配置4.4 IDEA配置Maven 5 Maven项目创建5.1 M…

LaWGPT零基础部署win10+anaconda

准备代码&#xff0c;创建环境 # 下载代码 git clone https://github.com/pengxiao-song/LaWGPT cd LaWGPT # 创建环境 conda create -n lawgpt python3.10 -y conda activate lawgpt pip install -r requirements.txt # 启动可视化脚本&#xff08;自动下载预训练模型约15GB…

回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测

回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测 目录 回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测&#x…

第二讲:BeanFactory的实现

BeanFactory的实现 1. 环境准备2. 初始化DefaultListableBeanFactory3. 手动注册BeanDefinition4. 手动添加后置处理器5. 获取被依赖注入的Bean对象6. 让所有的单例bean初始化时加载7. 总结 Spring 的发展历史较为悠久&#xff0c;因此很多资料还在讲解它较旧的实现&#xff0c…