[游戏中的图形学实时渲染技术] Part1 实时阴影技术

news2024/10/5 23:31:20

原理篇:

常见的渲染方程如下:

在不考虑自发光项与考虑阴影对于着色结果的影响之后可以将方程变化为如下形式:

如果射线在到达光源前击中了其他物体时,就认为这条来自光源的光线对着色点没有贡献。

利用上述渲染方程进行正确的着色和阴影计算是非常耗时的因为它需要进行积分,因此在光栅化的实时渲染中需要对该方程进行简化:

(微积分的近似公式)

Image

而通过该方程可以将着色和阴影分开,也就是说,可以在先计算着色,在此基础上再乘上阴影计算的结果,即可近似正确的表示阴影。

基础篇:

1. Shadow Mapping

渲染阴影场景涉及两个主要的绘图步骤。第一个生成阴影贴图本身,第二个将其应用于场景。根据实施(和灯的数量),这可能需要两次或更多次绘图过程(多次绘图指的是场景中存在多个光源)。

shadow mapping 的基础原理:

总结:Shadow Mapping的原理是首先将场景从光源的视角进行深度图的渲染,然后再从观察者的视角进行渲染,并使用深度比较来检测可见性并生成阴影。

Shadow Mapping的基本步骤如下:

  1. 从光源视角渲染深度图:先将相机移动到光源位置,以光源为视点向场景中渲染深度图,即从灯光的角度生成一个视锥体,然后对视锥体内的场景使用透视投影矩阵进行投影。
  2. 生成阴影贴图:将深度信息保存,并将结果存入一个纹理,作为阴影贴图

Image

  1. 从相机视角渲染场景:现将相机移回到视点位置,在进行场景渲染前需要将阴影贴图传递给着色器

Image

  1. 计算阴影:在片元着色器中,使用深度测试函数来检查当前像素是否被光源照射到。首先通过使用当前片元的深度值与阴影贴图中对应位置处的深度值进行比较,如果当前像素被遮挡则该像素被认为是在阴影中,否则它处在光照下。

示例:

下图是第一个渲染 pass 中渲染出的光源

Image

下图示从相机视角,第二个 pass 中渲染场景深度图

Image

由此可以进行下一步深度比较,计算阴影操作。

传统shadow mapping 的问题

1.精度问题

在shadow mapping 由光源点生成的一张深度图中,由于深度图的本质是一张纹理,而纹理是一种离散化的数字信号,从深度图还原源场景深度信息时难免对发生精度不同的问题。

Image

而由于精度原因容易产生自遮挡的问题。

自遮挡问题产生的原因是:

Image

解决方案:

Image

上面左图显示了这种自遮挡的现象大多出现在原本没有阴影的地方。这些地方本该直接被光源照的,但却出现了条纹状的阴影。其原因是光源是倾斜照射的,并且Shadow Map产生的深度图的分辨率有限。

解决方案是容忍一段区间的遮挡物,即将阴影图中的深度值偏移一段。这一段距离就称为bias,如下。

但这种情况的 bias过大变会造成上面右图的人物的模型和阴影没有连上的情况。

此外还有一种解决方案是Games202中讲解的学术界(工业界中不用)中用的一个解决方法:

记录最小深度和次小深度的平均,作为后续的深度进行比较。

Image

工业界不用的原因

  • 要求物体双面渲染(这在游戏中完全不可能),有正面就得有反面,面片也得做成box
  • 开销太大,可能并不值得,虽然O(n),但是GPU里面并行处理下会爆炸(不过实时渲染不注重复杂度只注重速度)

问题: 必须要是两面的

2.走样问题

Image

由于单一的shadowmap会存在精度不足,我们在性能与效果中平衡提出Cascade Shadowmap技术。

Cascade Shadow Mapping是一种用于实时渲染的实时阴影技术。通常在实时渲染中,光源(如太阳)的影响区域比较大,如果只使用单个深度图(Shadow Mapping)来计算阴影,很容易出现阴影质量不佳或者阴影断层的问题。而阴影CSM技术可以将一个视锥体分割成多个级别,每个级别使用不同的投影矩阵和深度贴图来计算阴影,从而提高阴影的质量和稳定性。

阴影CSM的基本原理如下:

将摄像机的视锥体划分为多个子视锥体:将摄像机的视锥体沿着近裁剪面到远裁剪面进行划分,将每个子视锥体映射到一个具有固定大小的2D矩形区域内。

对于每个子视锥体,渲染深度贴图:对于每个子视锥体,使用投射矩阵将场景渲染到一个深度贴图中,并保存深度值信息。

计算阴影:对于每个像素,使用与Shadow Mapping类似的算法来比较深度贴图中对应点的深度值和当前像素与光源的距离,来判断该像素是否被阴影所遮盖。

合并结果:将所有子视锥体的阴影贴图进行合并,并将阴影应用于场景中的对象。

中等篇

软阴影的形成

Image

umbra

本影指的是阴影最里面的区域,它看起来是最暗的。换句话说,本影代表光完全被阻挡体阻挡的阴影部分。

Penumbra

半影是一个 物体阴影的一部分,其中只有一部分光束被遮挡体阻挡。半影区就是我们在图形学中的软阴影部分

antumbra:

是指遮挡物体似乎完全位于光源的中心区域内。 (这在咱们的文章中不做讲解)

理想中的点光源会造成硬阴影,但是现实中的光源由于本身存在体积,会形成拥有半影区的软阴影。

硬阴影与软阴影之间的关系不是简单地将阴影的边缘模糊化处理,而是由于现实生活中的光源都存在一定的面积和体积,而这种面积和体积会产生软阴影。

更多自然世界中的阴影的知识可以从下面链接中了解。

什么是影子:13 个有趣的事实 -​zh-cn.lambdageeks.com/how-is-shadow-formed/#um​编辑

PCF的原理

Image

如图,上图为硬阴影,下图为软阴影。

PCF相对于传统的shadow mapping 做了那些改变:

之前的ShadowMapping过程中,假设现在得到了一张阴影图,接下来需要对一个着色点的深度 �(�) 和阴影图的采样结果 �(�) 作比较,得到一个二元的结果即为在阴影中为1,不在阴影中为0。正因为这种二元性,才产生了硬阴影的没有过渡(或者说走样现象)。

PCF的做法是得到阴影图后,如下图所示,选择一个以该着色点映射在阴影图中的位置为中心的 n x n 的filtering(核),用这个着色点的深度值 �(�) 分别和filtering中每个深度值的采样结果 �(��) 进行比较,最后得到一个 n x n 的二元比较结果,再对这个 n x n 的二元的比较结果进行filter(平均),最终得到这个着色点的阴影可见性的值,而这个结果不再是非0即1的值,而是一个在(0,1)之间的浮点数。

总结:

PCF技术通过对阴影贴图进行采样的方式,对像素周围的多个采样点进行插值和混合,从而更加准确地确定每个像素点的阴影强度。具体而言,PCF方法将每个像素的阴影采样点划分为一个网格区域,并在每个区域内进行多个采样。通过对这些采样点的深度值进行比较和插值,可以得到一个更加平滑和准确的阴影效果。

这项技术的重点在如你去如何理解Filtering(本质上是平均)的意义。在这个过程中,Filtering的尺寸决定了阴影的软硬程度。Filtering的尺寸越大,得到的阴影越软,尺寸越小,得到的阴影越硬,如下图可见。

Image

经过PCF之后就可以得到一个相对真实的阴影结果。基本上不会存在错误!

Image

PCF的缺点与改进措施概述

在实时的渲染中PCF的致命缺点是慢,原本的在shadow map贴图中的一次查找变成了 7乘7 甚至是 9乘9 的像素。

所以,如果想在实时渲染中使用这种方式的软阴影技术需要对渲染过程进行优化:

在抗锯齿的是时候的第一个算法一定是SSAA,但是这样抗锯齿处理算法需要4倍的显存...,但是MSAA其举出思想依旧是一个像素点采样多次,但从原来的全部整个屏幕全部的像素,变成了屏幕画面的边缘部分。

PCF的优化也是同理-如下图,软阴影与硬阴影的之间的变化随着阴影的投射物(笔杆)与阴影的接受物(书本)的距离有关

Image

(由此我们就可以引出PCSS,即在阴影生成过程中 blocker distance <-> Filter size呈现一定的关系)

PCSS的原理

PCSS 是非常经典的一个制作软阴影的算法

PCSS的核心原理是根据光源大小和着色点与遮挡物的距离自适应调节PCF的滤波核大小。阴影边缘的滤波核大小由半影距离决定,如下图所示。 通过相似三角形原理可知, 半影距离由光源的尺寸 、光源与遮挡物的距离 、以及着色平面与遮挡物的距离决定。

下图用来详细说明对应的数学公式来源,通过相似可以得到 ��������� 而我们通过 ��������� 的大小就可以对应出filtering 的大小。 ��������� 越大 filtering 就越大。

Image

PCSS首先假定光源是一个区域光,传统的点光源,聚光灯和平行光,都对应着某种模拟但从广义上来讲他们依旧是属于面光源。

����������=(��������−��������)∗����ℎ�/��������

那么根据上面的操作我们可以总结PCSS生成软阴影的步骤:

● 步骤1:Blocker Search 某个着色点连向光源,找到shadow map上该像素周围一块区域的纹素所记录的深度值,把区域所有texel都找一遍,判断是不是遮挡物,如果是遮挡物,则累加,最后除以遮挡物的个数,以这个平均值作为遮挡物的深度即上面的 �������� 。

● 步骤2:Penumbra estimation 用$d_{Blocker}$计算得到 ���������� ,从而计算得到filtering尺寸

● 步骤3:PCF 利用filtering尺寸,进行可见性值的计算。

注意在可见性计算部分可以,最简单的可以从周围的取若干像素信息然后平均混合;也可以根据一定比例插值;比如按照泊松分布来进行采样。

PCSS算法的优化

在PCSS算法中步骤1与步骤3比较慢。

step1 寻找 blocker的效率低下 step3 在 filtering 进行采样依旧是很耗费性能。

优化方法1:稀疏采样 缺点:由于稀疏草药会出现噪点,需要在最后在图像空间上做一次滤波。稀疏采样计时滤波之后会产生抖动。

优化方法2:对于PCSS计算的过程中做一系列的近似操作,这就引出了VSSM (Variance Soft Shadow Mapping)

VSSM的原理

VSSM的核心思想是快速寻找 blocker and filtering ,他的快速寻找是通过一系类近似操作降低时间复杂度。

可见性值的优化处理: 在刚刚步骤3的核心是找到着色点的可见性值,而可见性值是通过,p的深度值 �(�) 在阴影图中的filtring �� 中排第几。换句话说,需要得到 �(�) 占 �� 的百分比。

近似处1

我们将深度值,近似的设想为正态分布,正态分布图像由期望和方差决定(也就是说我们只要知道Filtering中深度值的期望与方差就可以大致知道深度分布的一个情况)。

剩下的全部问题在于期望(均值)和方差的获取。

  • 期望通过 SAT和mipmap。
  • 方差,数学公式计算 �(�)=�(�2)−�2(�) :

一块区域的平均值(方差)的计算:

使用MipMap

优点:

  • 快速、近似、正方形

缺点:

  • 插值结果只是近似。当查询区域在某层上不太对齐像素格的时候,需要双线性插值。
  • 当查询的范围不为2的n次方时,还要再进行一次层间插值,即三线性插值
  • 如果查询区域是长方形区域查询,还得加入各向异性过滤

使用SAT (类似算法中的前缀和) Summed Area Table可以用来高效地计算图像上任意矩形区域内所有像素值的和,而不需要遍历该区域内的每个像素。这对于一些需要频繁计算图像区域总和的算法非常有用,如图像滤波、特征检测等。

具体来说,Summed Area Table是通过对原始图像进行一次积分得到的。对于给定的像素坐标(x, y),Summed Area Table中该位置的值表示了原始图像中从(0, 0)到(x, y)的矩形区域内所有像素值的累积和。换句话说,Summed Area Table中的每个元素表示了其左上角矩形区域内所有像素值的累积和。

特点:

  • 百分百准确范围查询结果,但是计算花销较大

得到 E(X) 和 D(X) 之后我们就有了正态分布图像,接下来就需要计算可见性。

可见性值的计算

我们需要通过正态分布,确认百分比数值(可见性值)。

在概率论中,PDF(概率密度函数)为连续型随机变量的概率密度函数,CDF(累积分布函数)为概率密度函数的积分。

也就是说,对于一个值x,只需要求出CDF(x),就可以得到百分之多少的值是小于x的,即1 - 可见性的值。

Image

CDF一般比较难计算,VSSSM又找到一个不等式对它进行近似,即切比雪夫不等式:

�(�>�)≤σ2/(σ2+(�−μ)2)

​ 所以有:

���=1−�(�>�)≈1−�2�2+(�−�)2

同时切比雪夫不等式有一个苛刻的假设:t必须在均值的右边。

(当笔者做到这里的时候有一个疑问:把阴影区间的分布的CDF(x)为什么不将正态分布图像转变为标准正态分布后查表得出呢QAQ)

VSSM加速PCF步骤的总结:

  • 生成shadow map的同时,生成一张存放深度的平方的平方深度图(Square depth map)。两个通道分别存放即可,不需要额外一张texture,
  • 求深度图上某区域的均值,MipMap或者SAT,O(1)
  • 求平方深度图上某区域的均值,依旧MipMap或者SAT,O(1)
  • 知道均值,根据公式得到方差

根据切比雪夫不等式直接求出该点可见性Visibility

VSSM 的问题

VSSM 做了很多的假设,所以会存在种种的问题。

比如漏光(Light leaking)

当物体的深度不是呈现正态分布的时候会出现的问题。这是一个很明显的错误,(为了解决该问题可以使用Moment shadow mapping)

Image

虽然VSSM很快,但是准确度有些堪忧。

高级篇

距离场软阴影

距离场,它反映了任意一个点到某个物体的最小距离。将它可视化后如下:

Image

优点:

  • 快速(查询快)
  • 质量高

缺点:

  • 需要预处理(慢)
  • 需要大量存储空间

ray-SDF intersection

在ray marching的过程中,是解求光线打到物体上的点。

SDF(p) 是点 p 到达最近表面的距离,在ray marching过程很重要的概念是步长,每一次射线前进的距离就是步长也就是SDF(p)。正因如此,就可以认为SDF(p)为点p的“安全距离":从点p出发,按任意方向走SDF(p)距离,都不会碰到物体。 有了“安全距离”的概念后,选定一个起点 �1 后和方向后,按方向走 ���(�1) 距离到 �2 ,再按方向走 ���(�2) 距离,递归直到打到物体。(我们认为当直线与最近平面的距离小于某一个值的时候就是大中了物体)

Image

Distance Field Soft Shadow

SDF还可以应用在软阴影中。在软阴影中,我们用SDF来近似得到一个着色点被遮挡物遮挡的程度。 我们引入"安全角度“的概念:将光源抽象成面光源,从着色点 P沿某方向 ���� 看向光源,将光线从 ���� 朝物体方向旋转最大角度 � ,光线不会打到物体,则 � 为”安全角度“。

那么 � 的计算如下:

对于光线上任意一点Q,它的”安全距离“为SDF(Q),则”安全角度“为光线方向和着色点到圆切线的角度。 于是,安全角度的大小可以反映阴影的软硬程度(Visibility)。安全角度越小,遮挡越多,越趋近于硬阴影。安全角度越大,遮挡越少,越趋近于软阴影。

Image

如上图所示,安全角度的求解方法

问题又变成了如何求 � ?一种思路是求反三角函数,

�=���������(�)|�→−�→|

用简单的乘法运算去近似该公式

�=min�⋅���(�)|�→−�→|,1.0 。 这个近似式的k项,它决定阴影的软硬程度。当k小时, ���(�)|�→−�→| 需要更大的值(更少区间)才能>=1,最终映射到1。当k大时, ���(�)|�→−�→| 只需要较小的值(更多区间)就能>=1,最终映射到1。也就是说,k越大反映阴影更硬。

Image

参考:

  • Real-Time Rendering 4th Edition-2018-英文版
  • http://www.ownself.org/blog/2010/percentage-closer-filtering.html
  • games202
  • https://www.yuque.com/gaoshanliushui-mbfny/sst4c5/sl2q1b#49a7623c

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

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

相关文章

基于springboot的教学在线作业管理系统(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

一文图解爬虫(spider)

—引导语 互联网&#xff08;Internet&#xff09;进化到今天&#xff0c;已然成为爬虫&#xff08;Spider&#xff09;编制的天下。从个体升级为组合、从组合联结为网络。因为有爬虫&#xff0c;我们可以更迅速地触达新鲜“网事”。 那么爬虫究竟如何工作的呢&#xff1f;允许…

补坑:Java的字符串String类(1)

常用方法 字符串构造 来看看源码里面String的构造方法 普通字符串 //"hello" 是字符串常量&#xff0c;没有\0标记结尾String str "hello";System.out.println(str);//helloString str2 new String();System.out.println(str2);//没有输出String str3…

摊位展示预约小程序的作用有哪些

无论市场还是街边&#xff0c;小摊小贩往往很多&#xff0c;组成了丰富多彩的线下购物环境&#xff0c;而在实际发展中&#xff0c;摊位的需求度很高&#xff0c;但由于种种原因&#xff0c;导致在实际发展中&#xff0c;也有一定难题&#xff1a; 1、摊位预约难、信息查看难 …

IDEA的优化配置教程

前言 IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以…

多门店民宿预定系统酒店预订管理系统源码/公寓/农家乐小程序源码

技术栈&#xff1a; thinkphpuniappmysql 支持H5APP小程序 主要功能介绍&#xff1a; 在线预订 支持在线支付或到店付&#xff0c;支持配置免费取消订单时长&#xff0c;支持到店付保留时长设置 房间搜索 支持按日期搜索房间状态&#xff0c;支持按日期区间搜索房间状态…

Python tkinter库利用Scrollbar对象实现Text组件右侧滚动条

在Python的Tkinter中&#xff0c;可以使用Scrollbar来实现Text组件的上下滑动。首先&#xff0c;需要创建一个Scrollbar对象并将其与Text组件绑定&#xff0c;然后将Scrollbar放置在Text组件的右侧&#xff0c;使其能够控制Text组件的上下滑动。 运行结果 以下是一个简单的示例…

Postman常见报错与解决方法,持续更新~

postman中文文档 基本操作&#xff1a;从控制台查看请求报错 如果 Postman 无法发送你的请求&#xff0c;或者如果它没有收到你发送请求的 API 的响应&#xff0c;你将收到一条错误消息。此消息将包含问题概述和指向控制台的链接&#xff0c;你可以在其中访问有关请求的详细信…

SmargGBD(GB28181设备接入模块)如何对接wvp-gb28181-pro

技术背景 我们在对接SmartGBD&#xff08;GB28181设备接入模块&#xff09;的时候&#xff0c;除了常规的海康大华宇视等国标平台外&#xff0c;有些公司会选择wvp-gb28181-pro。 众所周知&#xff0c;WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网络视频…

SAMBA文件共享与DNS域名服务

一、SAMBA文件共享 1、什么是SAMBA SMB&#xff08;Server Message Block&#xff09;协议实现文件共享&#xff0c;也称为CIFS&#xff08;Common Internet File System &#xff09; 是Windows和类Unix系统之间共享文件的一种协议 客户端主要是Windows&#xff1b;支持多…

openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库

文章目录 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库120.1 密态等值查询概述120.2 使用gsql操作密态数据库 openGauss学习笔记-120 openGauss 数据库管理-设置密态等值查询-概述及使用gsql操作密态数据库 120.1 密态等值查询…

【dbeaver】添加mysql高低版本选择驱动

添加mysql高低版本选择驱动 连接到数据库->全部->查询mysql MySQL 版本驱动 8.0 MySQL 5 版本驱动 5.7.x 其他需要就&#xff1a;https://downloads.mysql.com/archives/c-j/ 密码查看 项目设置密码&#xff1a; File -> Project security ->设置密码 It i…

可视化 | echarts饼图改编

echarts模板来源 &#x1f4da;改编点 &#x1f407;基本样式 去掉legend、label&#xff1a;show: false背景透明&#xff1a;backgroundColor: "transparent"去除功能标签添加载入动态animationEasing: elasticOut, animationDelay: function (idx) {return Mat…

Mac安装与配置eclipse

目录 一、安装Java&#xff1a;Mac环境配置&#xff08;Java&#xff09;----使用bash_profile进行配置&#xff08;附下载地址&#xff09; 二、下载和安装eclipse 1、进入eclipse的官网 (1)、点击“Download Packages ”​编辑 (2)、找到macOS选择符合自己电脑的框架选项…

安全框架SpringSecurity-1(认证入门数据库授权)

一、Spring Security ①&#xff1a;什么是Spring Security Spring Security是一个能够为基于Spring的企业应用系统提供声明式&#xff08;注解&#xff09;的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean&#xff0c;充分利用了Spring …

Linux-vi/vim命令

1.vim/vi编辑器的三种工作模式 ①命令模式 ②输入模式 i打开 ③底线命令模式 :打开 2.命令模式 vi 文件路径 vim 文件路径 如果文件不存在则创建新的文件&#xff0c;存在则使用vi/vim打开 3.快捷键 模式命令描述命令模式i在当前光标位置进入输入模式命令模式a在当前光标位置之…

【2】Gradle-快速入门使用【Gradle项目结构概念】

目录 【2】Gradle-快速入门使用【Gradle项目结构概念】安装本地安装先决条件 官网安装教程 Gradle 快速指南初始化项目查看Gradle的项目结构了解Gradle Wrapper调用Gradle包装器了解Gradle的项目结构了解settings文件了解构建脚本 IDEA中使用Gradle创建一个新项目创建一个Sprin…

环形处理习题,举例:约瑟夫环,魔方阵

目录 约瑟夫环 魔方阵 约瑟夫环 题目描述&#xff1a;有n 个人围成一圈,顺序排号。从第1个人开始报数从1到3报数凡是报到3 的人退出圈子,问最后留下的是原来的第几号? 环形处理:依次遍历数据集的每个元素&#xff08;每个人依次报号&#xff09;&#xff0c;直到遍历到最后…

【Linux】编译Linux内核

之所以编译内核&#xff0c;是因为gem5全系统仿真需要vmlinux文件&#xff0c;在此记录一下以备后面需要。 此过程编译之后会获得vmlinux和bzImage两个文件&#xff1b; 主要参考知行大佬的编译内核与gem5官方教程 文章目录 一、Linux源码下载二、安装编译依赖三、编译1. 内核编…

5种常用Web安全扫描工具,快来查漏补缺吧!

漏洞扫描是一种安全检测行为&#xff0c;更是一类重要的网络安全技术&#xff0c;它能够有效提高网络的安全性&#xff0c;而且漏洞扫描属于主动的防范措施&#xff0c;可以很好地避免黑客攻击行为&#xff0c;做到防患于未然。那么好用的漏洞扫描工具有哪些&#xff1f; 答案…