屏幕空间实时全局光照------计算机图形学高质量实时渲染(七)

文章介绍了屏幕空间实时全局光照技术,包括光传播体积(LPV)、VoxelGlobalIllumination(VXGI)和屏幕空间环境光遮蔽(SSAO)。LPV通过3D网格传播光线实现快速但不精确的全局光照;VXGI提供更高质量但计算量大的光照追踪;SSAO则是对全局光照的近似,通过屏幕空间信息处理得到环境光遮蔽效果。文章还讨论了各种方法的优缺点和应用场景。
摘要由CSDN通过智能技术生成

屏幕空间实时全局光照(Realtime Global Illumination)(In Screen Space)

本节课内容:

在这里插入图片描述

Light Propagation Volutions(LPV)光传播体积

某个大佬的LPV算法简述
https://zhuanlan.zhihu.com/p/412287249

LPV:在3D空间中去传播光线,从而利用它做出间接光照从而实现GI。
在这里插入图片描述
LPV历史:最早是在Cry Engine3中被引入的,其初衷是用来做Crysis系列(孤岛危机),如果你是一名系列爱好者应该知道2007年Cry Engine2做出来的显卡危机,其使用了我们下文要讲的SSAO技术,而Cry Engine3中的一项主要技术是LPV。

LPV有两个不错的优点:

  • Fast
  • Good quality

RSM存在的问题

RSM有它自己本身的问题,LPV可以很好的解决一部分RSM的问题。
在这里插入图片描述
**主要问题:**如果我们能获得任何一个shading point上来自四周的radiance的话,就可以立刻得到其间接光照。
**核心思路:**我们假设光在传播的过程中,radiance是uniform的(intensity会平方衰减)
**核心解法:**将场景划分为若干个3D网格,每个网格叫做Voxel(体素),在计算完直接光照后,将接受到直接光照的表面看作间接光照在场景中传播的起点。

在这里插入图片描述

LPV详细步骤:

在这里插入图片描述

1.找出接受直接光照的点(RSM的方式)
2.把这些点注入(inject)到3D网格中作为间接光照(虚拟光源)的传播起点
3.在3D网格中传播radiance
4.传播完后,渲染场景

1.生成RSM

在这里插入图片描述

  • 与RSM一样,首先通过Shadow Map找出接受直接光照的表面或者物体
  • 对得到的光源数量可以通过采样一些进行简化从而降低次级光源数量,最后获得一系列虚拟光源。
2.注入光照

在这里插入图片描述

  • 预先把场景划分为若干个3D网络(体素)
  • 把虚拟光源注入到其对应的格子内
  • 一个格子内可能包含许多不同朝向的虚拟光源,把格子内所有虚拟光源的不同朝向的radiance算出来并sum up从而得到一个往四面八方的radiance
  • 由于是在空间上的分布,也就可以看做是球面函数,自然可以用SH来表示(工业界用两阶SH就可以表示各个方向上的radiance初始值)
    在这里插入图片描述
3.光照传播

在这里插入图片描述

  • 由于是3D网格,因此可以向六个面进行传播(上下左右前后),由于radiance是沿直线传播的,我们认为radiance是从网格中心往不同方向进行传播的,穿过哪个表面就往哪个方向传播,比如穿过右表面的radiance,就传播到右边的格子里(不考虑斜角,比如右上角方向,我们认为是先到右边格子,再到上面格子)
  • 每个格子计算收到的radiance,并用SH表示
  • 迭代四五次之后,场景中各voxel的radiance趋于稳定
4.渲染

在这里插入图片描述

  • 对于任意的shading point,找到他所在的网格
  • 获得所在网络中所有方向的radiance
  • 渲染

LPV存在的问题以及解决方法

存在的问题

LPV也有自己的问题,那就是和VSSM一样的问题:漏光。
由于我们认为radiance是从格子正中心向四面八方发散的,当遇到这种情况时。
在这里插入图片描述
按理说点P反射的radiance是无法照亮墙壁的背后,但是由于我们的假设,会导致墙壁后面也被间接光照照亮,也就是所谓的漏光现象。
在这里插入图片描述
如图,你看房屋的下部本不应该被照亮,但由于使用了LPV导致了light leaking现象。

解决

我们是可以解决漏光现象的,那样需要我们划分的格子足够小,这样会导致存储量增多,而且传播过程中传播的格子量增多,也就导致了速度慢。
对于两个格子之间的可见性也进行了假设,假设相邻格子间都能看见,同时工业界会用不同大小的格子,也就是Cascade层级加速结构,来优化LPV的方法。
老师放出了两个小视频来证明LPV的效果很稳定,对于动态的物理处理的也非常好。

  • Q1: 这是预计算吗?
  • A1:不是,这是实时的,每一帧都要去做这个计算。
  • Q2:每个格子存储的是light transport吗?
  • A2:可以这么理解

Voxel Global Illumination(VXGI)

VXGI与LPV的区别

VXGI也是一个2-pass的算法,但是与RSM有一些区别:
在这里插入图片描述
区别1:次级光源从RSM中的pixel -->VXGI中的voxel(格子)

RSM中次级光源是像素中所包含的微小表面,这些表面是根据shadow map来划分的
而VXGI把场景完全离散化成了一系列微小的格子,可以理解为场景是由一堆乐高堆起来的,如图,这些是最细的层级,也就是最小的格子我们可以在这一层基础上去建立一层大点的格子,依次类推从而根据场景的不同划分建立处一个Hierachical(层次)树形结构的体素。

区别2:光线从传播变为了追踪

在LPV中,我们将受到直接光照的点注入到场景划分的Voxel之后进行传播,只需要传播一次就可以知道场景中任何一个shading point 受到间接光照的radiance。

VXGI中第二趟我们从camera出发,就像有一个Camera Ray打到每一个Pixel上,根据Pixel上代表的物体材质做出不同的操作,如果是glossy则打出一个锥形区域,diffuse则打出若干个锥形区域,打出的锥形区域与场景中一些已经存在的voxel相交,这些voxel对于shading point的贡献可以算出来,也就是我们要对每一个shading point都做一个cone tracing。可想而知,这个速度比起LPV来说是很慢的,但是是可以优化的,暂且不提。
在这里插入图片描述
作图将场景划分为一系列的voxel,之后再划分成一个hierachical树形结构,右图就是hierachical的体素。

VXGI具体步骤:

Pass 1: Light Pass

不管如何我们首先肯定是先要算直接光照找到哪些voxel会被照亮,那么我们先从接收到直接光照的patch开始,不管是RSM还是什么先找出接受直接光照的patch.
(可以理解为是通过RSM找出直接光照的体素,也就是次级光源的体素)

但是由于场景是由voxel来表示的,那么对于任何一个格子来说,跟LPV的注入一样,但是这里不在记录格子里表面的出射分布或者说认为表面是diffuse的半球分布,也就是不再像LPV一样将所有的radiance加在一起求各方向的初始值,那么也就是说可以支持反射物(patch)也是glossy。
在这里插入图片描述
记录的是直接光源从哪些范围来(绿色部分),记录各个反射表面的法线(橙色部分),通过输入方向法线范围两个信息然后通过表面的材质,来准确的算出出射的分布,这样就比LPV认为格子表面时diffuse再用SH来压缩的方法要准确,然后建立更高层级格子的这些特性。

Pass 2:Camera Pass

从这一步开始考虑场景的渲染了,对于任何一个体素,知道了Camera Ray的方向。

  • 1.对于glossy的表面,向反射方向追踪出一个锥形(cone)区域;
    在这里插入图片描述
    基于追踪出的圆锥面的大小,对格子的层级进行查询,就是对场景中的所有体素都要判断是不是与这个锥形相交,如果相交的话就要把对于这个点的间接光照的贡献算出来(我们存储了体素的光照输入方向和法线方向,因此可以算出其输出的radiance,将cone区域内所有体素的radiance都算出来从而在shading point得到间接光照),也就是根据传播出的距离远近找对应层级的体素,然后找覆盖的范围。(论文中说查询相当于是mipmap的操作,好好看vxgi的论文,并试着复现)。
    2023年8月7号重看表示,那玩意不是mipmap,是clipmap。

  • 2.对于diffuse的情况来说,通常考虑成若干圆锥,忽略圆锥tracing时的重叠和空隙。
    在这里插入图片描述

LPV和VXGI对比总结:

LPV是把所有的次级光源发出的Radiance传播到了场景中的所有位置,只需要做一次从而让场景中的每个voxel都有自己的radiance,但是由于LPV使用的3D网格特性,并且采用了SH进行表示和压缩,因此结果并不准确,而且由于使用了SH因此只能考虑diffuse的,但是速度是很快的。

VXGI把场景的次级光源记录为一个层次结构,对于一个shading point,我们要通过corn tracing 找到哪些次级光源能够照亮这个点。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果的质量非常好,与光线追踪的结果非常接近,但是开销还是太大,应用受到了限制,对于VXGI我们需要预先对场景体素化,这也是一个很大的问题,由于每一个shading point都要做一些cone tracing,操作已经非常像离线渲染了。

屏幕空间中的实时全局光照 Realtime Global Illumination(screen space)

首先我们介绍一下我们讲了这么多的几种方法都是什么类型的:

  • LPV和VXGI是属于在3D空间的GI
  • RSM是属于在图像空间的GI
  • SSAO和SSDO是属于屏幕空间的GI

那么我们需要知道 什么是屏幕空间?

1.使用的所有信息都来自“屏幕”,也就是做全局光照之前屏幕上能看到的信息,这些信息也就是做全局光照之前的直接光照信息
2.也就相当于对这张图做一个后期处理,从而来“弄”出全局光照。
3.为了与此区别,我们把RSM与SM的方法称为图像空间,因为信息是来自从灯光看向的场景,所获得的信息。

接下来我们开始讲屏幕空间是如何去做全局光照的,首先来讲SSAO再讲SSDO

SSAO(屏幕空间环境光遮蔽)

在开始介绍的时候,我们说过Cry Engine,SSAO最早应用的游戏是使用Cry ENGINE2做出来的孤岛危机一代,AKA显卡杀手。
在这里插入图片描述
那么我们为什么要来搞这个环境光遮蔽呢?
首先我们来知道什么是AO:
在这里插入图片描述
左边是进行了AO的,右边是没有进行AO的,之间的差别还是很明显的.

  • 通过一系列的contact shadow让物体与物体之间的相对位置表示的更明显,从而让物体相对位置感更强。
    在这里插入图片描述
  • AO是非常非常容易去实现的

SSAO:
1.AO是一个对于全局光照的近似
2.在屏幕空间意味着从camera渲染场景得到信息,而非是场景中的所有信息

overall ,在屏幕空间对于全局光照的近似就是SSAO。

三个重要的假设:

  • 由于我们不知道间接光照是什么,因此我们假设任何一个shading point上来自任何方向的间接光照(incident lighting)是一个常数
  • 虽然我们考虑了任何一个shading point上来自任何方向的间接光照是一样的,但并不是每个方向都可能接收到间接光照(incident lighting),也就是不同位置的visibility是不同的。
  • 假设物体是diffuse的,即使是一个glossy物体我们也以diffuse去渲染。
    在这里插入图片描述
    我们可以看到:
    左边是任何一个shading point上来自任何方向的间接光照(indirect lighting)是一个常数。
    右边是我们考虑了任何一个shading point上不同方向的visibility后得到的结果。

一句话说就是在环境光一样的情况下考虑遮挡关系.

在这里插入图片描述
图中红色部分表示被遮挡,黄色部分表示未被遮挡,我们可以明显的得出一个结论,左边的shading point 要比右边的亮一些。

接下来我们来理解一下它背后的理论,为什么说他是一个对GI的近似:
在这里插入图片描述
回到我们的老朋友rendering equation来,light(蓝),brdf(黄),visibility(橙)
在这里插入图片描述
还记得我们之前说的,RTR中最常用的近似吗,把一个product integral中的一项除去并除以一个空积分进行归一化,由于这里我们要考虑的是各个方向的visibility,因此把visibility项拆出去。
在这里插入图片描述
蓝色方框中分母再将立体角在这里插入图片描述拆成sinθdθdφ之后对θ和φ分别积分得到的结果是π,整个积分的结果我们称其为Ka,其实际意义是从一个点网所有方向看去按cos加权平均的平均visibility。
在这里插入图片描述
橙色方框中积分的结果,由于我们假设了所有方向的间接光照是一个常数,假设了物体是diffuse的,因此BRDF也是常数,因此最终结果就是漫反射系数x间接光照强度Li,由于也间接光照强度Li你可以随便指定,漫反射系数也是你可以随便指定的,因此就是橙色部分的结果是你自己来定义的一个数。
在这里插入图片描述
AO就是:shading point 的加权平均visibility 乘以 一个你自己定义的颜色

深入理解:

  • 1.我们可以把f(x)整个积分拆出来并归一化这个操作,换成求f(x)在g(x)的覆盖范围内(support内)的平均值,由于brdf是diffuse的,是一个常数,间接光照也是一个常数,因此g(x)就是一个常数,所以AO做这么一个拆分是完全没有问题的。
    在这里插入图片描述
  • 2.一个比较难的理解,在之前的公式中,我们可以看到,老师并不是对dwi进行积分,而是对cosθ,dw进行积分,那么我们是怎么把cosθi 乘以 dwi都拆分拿出来呢?
    在这里插入图片描述
    这里我们需要引入投影立体角的概念:
    在这里插入图片描述
    立体角是单位球上的一个面积,关于cos中的θ,我们认为θ是从北极开始到南极是180度,那么立体角乘以cosθ得到的是什么呢?
    在这里插入图片描述
    是我们把单位球上的面积投影到了单位圆上.
    在这里插入图片描述

SSAO终极简单理解:

  • 间接光照是常数----Li为常数
  • BRDF是diffuse的-----brdf是常数c/π(lambert漫反射模型)
  • 因此这两项可以直接从积分里面拿出来,最后rendering equation就成了下面的形式,也就是算visibility的积分。
    在这里插入图片描述

但是将BRDF和lighting提出来后积分里剩下的部分由于缺少了分母归一化这个操作,所以得到的结果并不是加权平均的visibility,如果在一开始这么讲的话,会不理解Ka的来源。

那么接下来我们只需要取求得visibility部分就可以了,也就是算加权平均的visibility,在世界空间下可以通过ray tracing做,但是在屏幕空间下我们该怎么去做呢?
在这里插入图片描述
我们需要在shading point往不同方向trace判定究竟有多少方向被挡,这样说其实并不准确,我们以一个极端的例子来看,在一个封闭的屋子里,不管你从哪一个shading point去trace哪个方向,不论trace的光线会不会打到周围物体,我们这根光线不会出去这根封闭的屋子,也就是最后的结果只能是被遮挡住,所得到的Ambient Occlusion只会是0.

这是因为,反射光肯定是在优先的距离里反射过来的,也就是间接光照是从一定范围内来的,不可能是从无限远处,因此如果我们做tracing肯定也是在一定范围内的,这样就解决了tracing无限远的话一定会被遮挡住这个问题。

但是出现了新的问题,就是超出这个范围的光照就被我们忽略了,也就是我们忽略了那些在距离外的间接光照,如果我们限制范围太大,那么所有东西都有可能遮挡住,如果范围太小,我们会忽略大部分incident lighting,因此我们限制在一定范围内,这是一个trade off。通常会选一个合适的范围,也就是找到一个合适的球的半径R。
在这里插入图片描述
但是在SSAO中我们不是这么去计算visibility的,他做了很聪明的假设,他并没有去往四周trace光线,因为那是一件非常麻烦的事情。

SSAO的做法

  • 任何一个shading point在以sp为圆心,半径为R的球的内部随机撒一些点,然后判断这些点能不能被shading point直接看到
  • 从camera出发渲染,我们肯定是可以看到深度图的,而且深度图z-buffer我们是可以把他看成是场景的一个简单近似,也就是我们从camera看到的下图中的白线,球内部的点是可以投影到camera然后找之前记录的深度,如果深度更深,则表示在物体内部,被遮挡,反之则未被遮挡。
    在这里插入图片描述
    上图中蓝色区域部分表示的是场景物体,也就是说蓝色区域外的绿点是可以被shading point直接看到的。

但是我们可以看到中间图的一个红点出现了问题,因为我们从camera看过去,这个点比所圈部分的深度深。因此虽然这个红点是能够被shading point看到的,但是由于是从camera出发,这里被判断为了看不到;
在这里插入图片描述
同时并没有考虑cos,也就是没有考虑法线,没有进行加权,因此这个假设并不是物理准确的,但是在实时渲染中看起来问题并不是太大。

因为rendering equation通常只考虑法线所在的那半边,因此做这个判断也值判断法线所在的那半边是没有问题的,也就是后面那个半球的采样点没有用处。而由于SSAO的时代并不能获得场景的法线信息,因此SSAO采用了另一种方法来替代,那就是在整个球采样红点过半的时候开始考虑AO问题。
在这里插入图片描述
以中间为例,半边一共五个点,两红三绿,因此visibility就是0.6,但这是未加权平均的visibility。
由于是在场景深度上做的,因此在地板上由于临近屏幕空间中的凳子的遮挡,也出现了错误的AO。
在这里插入图片描述
如图中的所圈部分,我们知道那一片的地板是不可能被石头椅子所遮挡的,但是在开启了SSAO,由于我们是从camera出发去判断深度的,所以这一块不可避免的出现了错误的AO。

采样中的问题:
在这里插入图片描述
选Sample数量与PCSS一样,也就是越多的Sample效果越好,但是这也会越慢。
但我们可以用少量的sample,得到一个noisy的结果,然后在这个noisy的结果上进行一个denoising来实现降噪,这些降噪的模糊和噪声在和场景中的其他效果与光照叠加后就会变得非常不明显,从而获得比较好的综合效果。
在这里插入图片描述

在这里插入图片描述

SSAO的进阶法 HBAO

我们上面说的是没有法线的方法,当有了场景normal后,我们就知道去采样哪半球,就可以只去算半球的情况了,同时也可以对不同的方向来加权(靠近中间大,靠近两边小),也就是Horizon Based Ambient Occlusion --HBAO
在这里插入图片描述
HBAO的效果明显比SSAO要好很多,有效的减少了错误遮挡的问题(柱子后面尤为明显),但是要多存一个屏幕空间的法线 。
在这里插入图片描述
HBAO好的最重要的原因就是只考虑了一个半球。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值