实时光线追踪
Real-Time RayTracing
本节课内容:
- 1.原理
- 2.核心技术motion vector(动作向量)
- 3.trmporal accumulation/filtering是什么
- 4.有什么样的问题
这节课主要是讲基本思路,下节课讲具体的如何运用RTRT去解决问题。
Real-Time Ray Tracing(RTRT)
RTRT is the future
2018年,英伟达宣布发售GeForce RTX系列(图灵架构),开启了一个25亿美元的市场。
我们先来介绍一下RTX,RTX本质上只是硬件上的提升,并不涉及任何算法的部分。
其本身是作为硬件上的一个突破,因为在显卡加装了一个用来做光追的部件,由于光线追踪做的是光线与场景的求交,结合101我们知道光线要经过BVH或者KD-Tree这种加速结构,也就是做一个树的遍历从而快速判断光线是否与三角形相交,这部分对于CPU来说并不好做,因此NVIDIA设计了设计了专门的硬件来帮助我们每秒可以trace更多的光线。
并且虽然trace那么多光线,但是一个光线并不代表一个光路样本
每秒可以trace 10 Giga的rays,也就是100亿根光线,看起来虽然多,但是要对每个像素都trace因此要先除以分辨率,比如1K或者2K,除以几千万之后得到的结果还是很多,但我们还要除以每秒的帧数,而且我们并不是用所有的时间都只去做光线追踪,剩余的时间我们还要去做降噪,后期处理,gameplay本身,因此1秒中并不是全部时间都在做ray tracing。
1 sample per pixel就是每个像素采样一个样本,从而得到最后的光追效果。
那么什么样本是一个光路的样本呢?
至少有四条光线才能构成一个最基本的光路:
- primary hitpoint(从camera出发打出一根光线打到的交点,用光栅化代替)
- shadow ray(primary hitpoint 和光源之间连接进行light sampling并判断是否有遮挡)
- secondary ray(在hitpoint根据材质采样出一个方向打出一根光线,它会打到一个物体上从而得到secondary hitpoint)
- secondary shadow ray(从secondary hitpoint与光源连接判断是否会被光源看到)
图中第一步是rasterization(光栅化)是因为与primary ray做的工作时一样的,与其每个pixel去trace一条primary ray,不如直接将整个场景光栅化出来,两者是等价的,光栅化得到的结果不正就是每个pixel都穿过了一条ray吗?
而且光栅化速度更快,因此大家把所有的primary ray替换成了一趟rasterization,也就是在第一步我们做完了所有的primary ray,因此对每个shading point来说所包含的只剩下了三条光线,shadow ray,secondary ray和secondary shadow ray.
我们知道path tracing本身是一种蒙特卡洛积分的方法,本身会产生噪声,我们采样的样本越多,其噪声越小,但是在101中,我们用64spp都得不到很好的结果,何况1spp,因此我们知道1spp最后会得到一个很noisy的结果。
大家应该猜出来了,RTRT最核心的技术应该是降噪。
实时光线追踪与path tracing相比,只是进行了一算法上的简化,算法的核心思路不变,它本身的突破是由于硬件的能力提升,且1spp是在20系列时的特点,现如今的30系列可能会支持更多的spp。
从图中我们可以知道,即使是1spp得到的这么糟糕的结果,通过降噪我们仍然可以得到一个很棒的效果,那么接下来我们来了解如何去降噪。
首先我们需要知道在1spp下我们想要得到的结果:
-
filter之后的quality要好(no overblur,不会糊成一片,no artifacts,没有像裂缝那种可见的bug,可以保留所有的细节)
-
速度(降噪的速度要快,也就是要在2ms内完成降噪操作)
引用一句秘籍greed is good
从上面来看我们会认为这是不可能的任务,在1spp下得到一个噪声那么大的结果,你既要求降噪之后质量好又要求速度快,特别对于以前的很多方法在这里不适用:
Sheared filtering serise(SF,AAF,FSF,MAAF,…)Sheared方法不行
Other offlinefiltering methods (IPP,BM3D,APR,…)离线方法不行
Deep learning series(CNN,Autoencoder,…)深度学习不行
时域降噪(Temporal)
降噪的方法有很多,但是针对实时光线追踪的降噪方法很少,那么工业界是怎么解决这个问题的呢?
我工业界来这里只为了三件事:
(时域降噪,yyds)
temporal
temporal
还他妈是temporal。
核心方法:
首先假设整个看的场景的运动是连续的,就是camera以某种轨迹看向不同的物体,帧与帧之间有大量的连续性。
motion vector,它是用来告诉我们物体在帧与帧之间时如何运动的,也就是图中A点在motion vector下可以知道在上一帧A点对应的位置B点.
我们认为当前帧是需要去进行filtering,前一帧时已经filtering好的
利用motion vector来知道当前帧某一点在上一帧的对应位置。
由于我们认为场景运动是连续的,所以认为shading也是连续的,上一帧得到的降噪好的结果比如颜色之类的,可以再当前帧复用,相当于增加了spp,但并不是简单的上一帧1 spp + 当前帧 1 spp,由于是一个递归,因此上一帧也复用了上上一帧的结构,因此spp其实是很多的,可以理解为一个指数衰减,每一帧都有一个百分比贡献到下一帧。
这种方法叫做时间上的复用,通过在找某一点在不同帧上的对应关系去复用已得到的结果,至于空间上的我们在下节课去讲。
这里的temporal我们根据motion vector去找对应关系。
几何缓冲区 ->The G-Buffers
在介绍具体细节前,我们引入G-buffers。
G-Buffer,全称Geometric Buffer,译称几何缓冲区。
在screen space我们可以得到很多的信息,比如之前的screen space ray tracing,我们在screen space 得到了每个点的深度相当于从camera看去我们得到了一张深度图。
同样的我们不止可以通过screen space生成深度图,还可以生成像是直接光照下生成图,发现图或者每个点的diffuse Albedo(也就是颜色kd项)
也就是在渲染过程中,我们可以免费得到额外信息,如下图的三项:
也可以存储per pixel depth,normal,世界坐标(通过rgb三通道来存x,y,z)等,只需要将这些信息各自生成一张图存储在g-buffer里,当需要的时候拿出来用。
下图为一张Gbuffer中存储的内容
总结:Gbuffer存储的是Screen Space的信息。(因为他记录的是camera 能看到的信息)
使用后映射(Back Projection)求motion vector:
首先声明:
frame i:当前帧
frame i-1:上一帧
我们如何找到当前帧的一个像素在上一帧的哪里呢?
首先我们要知道,我们找的不是像素的位置,而是当前帧像素里包含的内容在上一帧哪一个像素里。
也就是我们需要知道是透过当前帧(frame i)中蓝点这个像素我们所得到的点的世界坐标,投影到上一帧(frame i-1)中对应的是哪个像素。
根据这个思路:
我们首先要求出这个点的世界坐标,如果G-buffer中有世界坐标信息的图,我们可以拿来直接用
如果没有我们可以计算得到:
我们知道一个点的世界坐标需要通过MVP矩阵和视口矩阵从而得到在screen space上的坐标,因此我们可以逆向思考,让screen space这个点按逆顺序乘以他们的逆矩阵就得到了世界坐标。
到此我们求出了这一点的世界坐标,对于他在上一帧的哪里,由于我们知道整套渲染的流程,因此对于每一帧之间时怎么移动的肯定也知道,因此如果物体移动了的话,我们只需要用将当前帧世界坐标乘以帧移动的逆矩阵多久得到了上一帧中这个点的世界坐标:
到此我们知道了发生移动后的上一帧的点的世界坐标,接着我们需要将他变回屏幕坐标上,因此我们需要乘以MVP矩阵和视口矩阵,关于图中的各种矩阵,由于我们是掌握着渲染的整个流程,因此每个矩阵都是已知的:
到此我们求出了frame i上的蓝点内对应的信息在frame i-1上的哪里,也就是我们通过back projection方法求出了motion vector。
Temporal Accum./Denoising(时域累计/降噪)
在得到了motion vector后,我们就可以把当前帧(noisy的图)和上一帧(没有noisy的图)结合在一起,最简单的方法就是线性blending在一起,比如上一帧结果0.8+这一帧结果0.2得到新的结果。
我们在此定义:
- ~:unfiltered表示没有filter噪声挺多的内容
- -:filtered没有噪声或者噪声比较小的
- 空间上的降噪
- 这个是时间上的降噪。
这个是时间上的降噪,做了一个线性的blending,认为上一帧是降噪好了的。
α表示平衡系数,当前帧的贡献,在(0,1-0,2)之间。
现在我们来顺一下时间上的降噪的过程:
- 1.如果在进行rasterization(prinary ray)时得到了世界坐标信息的图存储在G-buffer中则直接得到世界坐标。
- 2.如果没有其信息,则在当前帧的像素通过逆视口变换和逆MVP变换得到世界坐标。
- 3.已知motion矩阵,将世界坐标逆motion得到上一帧的世界坐标
- 4.将上一帧的世界坐标进行正MVP变换和视口变换得到当前帧中的像素在上一帧中的位置。
- 5.将两个值线性blending起来从而得到当前帧的最后的结果。
滤波绝不会让一张图变暗或者变亮。
我们知道没有东西是完美无瑕的,那么代价是什么呢?
时域的局限性
Temporal Failure
时间上的复用十分好用,我们应该尽可能多用,但是如果在他不可用时候该怎么办?
失败原因1:切换场景(需要导入时间)
failure case1 :switching scenes(burn-in period)
突然切换场景由于我的上一帧并没有新场景的任何信息因此得到的结果肯定不准确,再比如切换光源,假设在迪厅中场景中任何物体都不变换,只是将红灯忽然变为绿灯,由于上一帧中的信息光源为红色,因此如果复用会导致我们得到的结果偏红而不是偏绿,因此时间的复用在此不可用。
因此需要一个时间也就是 burn-in period,去累计个新场景的几帧信息以供后续进行复用。
失败原因2:后退的走廊
failure case2:walking backwards in a hallway(screen space issue)
我们以图为例,加入我们的camera 从离门最近开始倒退,我们知道在倒退的时候周围的信息会不断的增多,因此我们当前帧新出现的物体无法在上一帧的屏幕空间内找到相对应的点,这肯定会带来影响。
失败原因3:突然出现的背景(去遮挡)
failure case3:suddenly appearing background(disocclusion)
左边为上一帧,右边为当前帧,我们可以看见本来后面箱子后的内容是被遮挡住的,但是推走后变成未被遮挡住,此时我们去求箱子后遮挡部分的两帧屏幕对应位置会发现,右边的蓝点所显示的对应位置为左边的蓝点,这里是没有出错的,因为在屏幕空间确实对应的是蓝点,只是无法显示遮挡后的内容,这是屏幕空间的问题,如果进行线性blending的话肯定会问题,这就是disocclusion(不遮挡)的问题。
我们对上一帧的东西参考了80%甚至更多,自然会产生这种残影/拖尾的现象。
工业界的解决方法
因此为了避免残影的出现,工业界有两种解决方法:
clamping(拉向)和detection(判断),可以分开单独使用也可以两者一起使用。
clamping(拉向)
对于clamping方法来说,我们是把上一帧拉到接近当前帧的结果,以刚才的黄色箱子和白色墙壁为例,不正是因为当前帧里去了80%黄色墙壁的值才导致了残影的出现吗?如果我们在任何时候都把上一帧的结果,先给拉近当前帧的结果不就使得两者之间的颜色很相似,从而弱化了这一不正确的现象吗?
我个人理解是,上一帧的黄色,我们把他拉近白色,然后再将两者线性blending,这样我们得到的结果不仍然是接近于白色的吗?
detection(检测)
detection的思路是我们要判断是否仍要使用上一帧的结果,仍然以黄色箱子和白色墙壁为例,当我们做完motion vector之后,我们增加一步操作来判断所对应的是不是同一个物体,在工业界我们渲染是认为每个物体都有自己的编号,如果编号不同,那么认为motion vector就不在靠谱了。
因此我们对α进行调整,此时我们不再用80%或者更多了,我们可以认为是非0即1,0%上一帧,100%这一帧,但如果差的不是很多,我们就稍微减少其百分比。
但是我们知道,之所以引用上一帧是因为他没有噪声,如果100%相信这一帧相当于重新引入了噪声,但我们可以将当前帧的filter变大一点,让结果模糊一点但噪声小,这是没有关系的。
我们可以看到残影现象没有了,却产生了噪声。
除了这些还有很多其他的问题,比如:
但其实大部分情况下是shading 的问题。
以这个场景为例,我们认为光源从左到右移动,而场景几何并不发生移动,因此我们知道任何一个像素的motion vector是0,但是由于我们一直在复用未移动的帧结果,就会导致拖影的阴影出现。
对于这种地板上反射出来的情况来说,由于地板是不动的,因此其上面的每一个像素点的motion vector为0,当我们移动物体时,其地板需要一定时间适应,之后再在地板上反射出当今场景中的物体,也就是反射滞后。
因此传统的motion vector是搞不定这种情况的,因为变的是shadow和反射现象,我们实际想要追踪的是shading的变换,其几何不动因此motion vector为0,从而会导致各种现象。
今天的文章
光线追踪和实时渲染_计算机视觉算法与应用分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/80127.html