GAMES 图形学系列笔记(十二)

21.动态全局光照和Lumen (Part 2) | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV1Ya411g7Th

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好那么第2part是什么呢,唉我既然已经知道了,我在硬件上做retracing,非常的快对吧,那接下来我就要做个事情,就是我要把这些光子注入到这个世界,对不对,然后呢。

我把这个世界先获得直接的第一次光照的结果,然后我基于它我就可以算我的第二次光照结果,但实际上没有那么简单了,但是呢一般讲lumen的时候呢,很多人一上来就讲什么screen space的一个pro对吧。

讲了这个怎么采样啊,怎么点,反正我看到那一趴我就晕掉了,我说我大概知道你在讲什么,但是我的第一反应就是老哥,你不是应该先把光打进去嘛,对不对,你会发现他讲到最后的时候会给你讲一讲,光是怎么打进去的。

但是呢我们这节课反过来讲说哎,光是怎么打进去的,那实际上就是在这个lumen里面,他搞了一套非常特殊的东西,叫做mesh car,我先不讲mash car的这个细节,我先讲这个我们到底要解决什么问题。

就是当我们算全局光照的时候,其实从光的视角我们去照亮整个世界的时候,其实整个世界里面,无论你看得见的还是看不见的pixel,它实际上都会被这个光给照亮对吧,那么这些每一个被照亮的照亮的这个物体表面。

我们叫做比如说叫facet小表面吗,它实际上呢都是为我的这个GI的一个贡献者,就是我的光源之一,但是呢我们有个困难,就是说这么复杂的场景对吧,很可能是一个我现在看不见的一个石头的表面,被光打到了。

它会照到我了,那你用rs版的话,那你实际上就是用光的方向投了一个投影,但是呢rs m的话呢,你只能作为一个is bing对吧,它很多地方它是有这个比较大的局限性,而且呢就是说这个表面上的话。

很多复杂的几何的细节我们都不知道,那么在lumen里面,他提了一个什么方法呢,哎他想了一个办法,就是怕场景,你所有的物体啊,我给他拍了个快照,但这个快照拍的方法呢其实是以相机精度。

相机的位置为这个RAVVLOD的,就是说我靠近我,相机占领,我离我的这个相机的位置比较近的这个物体,我会给你的分辨率会高一点,然后呢相机远离的物体,我面前低一点,但是呢我从六个角度拍你的快照。

就是拍什么拍照就是你被光照亮的样子,因为我并不知道这些光经过一次帮两次帮形,到底是你天顶上的东西照亮的东西呢,还是你这边侧面的东西,还是这边,也许我看,比如说我举个例子啊,比如说我以我这个笔为例。

你真正我眼睛看到的就这一个面,对不对,但是呢有可能是你这个面上一个面照亮了,这边一个面反射给我了,对不对,那么有可能是上面这个面对吧,被光照了诶,这样过来一个东西,那我怎么办,我就对这个物体啊。

六个面给他拍这个六四快照,这个就比较麻烦,就大家知道GI就很麻烦,因为GI它是个全光路的,就direct lighting,很多时候你只要在乎我眼睛看过去的东西,但是呢我做JI的时候。

我需要知道它的全光路到底发生了什么,那么对于每一个物体,我对对它六个面进行采样,我想知道它被光直接照亮,被光照亮的是个什么样子,而这样的话呢我六个面拍下来,你觉得这里面举个例子。

就是说比如说这是这是我们在应用里面,我们自己截的,我们自己搭了一个场景,然后呢你可以看到就是这是它的生成的一个car,这个car的话呢,每个car的它有六个面对吧,你们看到这个细节没有。

它其实呢他是用a b b box,就是用那个轴对称的,沿着那个XYZ轴做的这样的一个面,这样也尽量简单一点吧,好我生成了他的car的之后呢,诶我就会首先把cut,把这个物体从这个角度我拍下去。

我拿到什么呢,拿到他的ABELE,拿到他的normal,拿到的它的一个depth,depth是从绑定开始算的,所以精度不用很高,如果你带反射的,带发射的自自发光源的话,我把你miss也发出来。

所以大家看到真正的GI确实是很丰富,很复杂,就在于就是我场景里每个物体都要排好,那场景物体是很多,对不对,有些物体其实离我很远,有些物体很小,那怎么办,哎我其实是有一套这个啊,应该在这一趴。

就是说它实际上是有一套的方法,就是说当你我的相机近的时候呢,我给的分辨率高一点对吧,我拍的更细一点,比如说我侧面有一个石头,这个石头可能只有2米高,但是呢它可能占据了我平面1/3的地方。

那我平面近处的东西,很可能会受这个石头的影响,远处呢可能有个雕像,它有5米高,但它距离我100米远,那其实呢我这个car的不用给它太高,它的精度可以低一点诶,大家这个思想就是这样的话,我可以怎么样呢。

我可以充分的利用我这个我能存储它的空间,那我存储这些CR的就是那个mesh card,地方在哪里呢,这个东西我们叫做surface cash,哎,这个surface cash就非常有意思了。

它总共分配了一个4096×4096的,这个空间,把每一个这个instance就是每一个mesh的,就其实这边准确的讲应该是每一个instance,注意啊,就是说你两个mesh可能是从几何上一模一样。

但是你放了两遍,那就是instance,注意这里面是讲的是instance,每一个instance它的car在里面packing好,它总共只有4096×4096这么空间,所以呢它这里面就会有些。

随着你的相机的移动啊,随着你的这个就是说主要是相机的移动对吧,那我有些物体就可能会被swap out,有些物体就会被放进来,没关系,因为这个CD你的东西呢主要是用来做GI的,所以呢你多放几个物体。

少放几个物体死不了人对吧,因为dear collection不需要用这个东西好,那么这个surface这个cash呢,这里面特别容易混淆的一个东西是什么呢,就是它不是一个单张的texture。

它是一系列的texture,这个cash形成的集合,它这里面会包括什么呢,会包括他刚才讲到的,比如说他的ABE对吧,包括什么呢,它的normal对吧,还包括他的depth,对不对。

那这样形成了一处东西好,那这里面的话你capture的这些东西的话呢,每一层的这个AIDO啊,or pity啊,这个它的depth啊,他的normal都会用一些硬件支持的。

这个compression method去压缩一下,很简单吧,我们做所有的rendering都知道,我要让内存尽可能的小对吧,4096×4096已经很大了,大家想想看这个什么都不干,4096×4096。

他就是16个兆了对吧,你还有这么多层对吧,轻轻松松给你上百兆的空间就给你用掉了对吧,那这个就是我们的surface cash,这样的话我有了这样surface cash之后呢,接下来我干什么事情呢。

就是说我们如何这个我用这,这这个标题是我自己写的,就是说其实他前面有很大一部分工作,就是当一个光照进来之后,这些光啊,其实在我的这个场景里面直接照亮了一些东西,对不对,照亮这个东西可能是它的正面。

可能是它背面,可能是在反面,I don’t really care,哎,这些光还可能在里面,BS对吧,BS的一大堆我也不care,但是呢最后我希望这些radiance。

最后能存储到我的surface cash上去,为什么呢,因为想象一下我的这个世界啊,本来是很多很复杂的几何,当我去做真的各种各样的全局光照的时候,实际上我的一个问题就是如果我看到了一个点。

我去做一个采样诶,我想知道他的那个地方,它到底radiance有多少,那我如果直接在那个就是这个几何事件里面,去问那个面片,你的光热是多少,实际上的过程是非常非常复杂的。

而且每一点的材质都是不一样的对吧,但是呢如果我把整个这个世界,它的最粗的这个光照信息,用这么一种uniform的方法表达出来之后,我在这个世界,你无论做什么样的一种retracing的话。

就是那个蒙特卡罗retracing的时候,我去都能够采样到那个点的表达,所以你可以理解成,就是说surface cash是对这个世界的一个,就是光照信息,其实就是为我们india lighting。

光照信息提过一次表达,我们希望把这个那个这个radiance arradius,固化在上面,这个这个地方又又又去那个怎么说呢,又去祭出了我们的风头。

map这个想法就是说其实呢他用这个就是surface card,这么多的那个mesh card,把它packing成一个surface cash的话,实际上是把所有的风头光子全部固化在上面了。

哎这个我这个土法炼钢,我是这么理解这个事情的,那么在这里面的话呢,我们就产生了一个问题了,两个问题,第一个就是说这个pixel就是那个service开始那个点,它在这个光的照耀下,它到底有多亮对吧。

它有可能会被shadow挡住的,对不对,那我怎么去知道这件事情,第二件事情是什么呢,哎这里面我只有一次的,第一次我竟然知道你的AIO,知道你的normal对吧,那我可以跟主光源算出来。

说到你这儿的第一次的这个光照的强度都大,但如果你是mt bs,我怎么办对吧,我因为我到处收集光的时候,这个光照上我我也不知道你是1month n次month,但是最后我要把这个视频方的光源全部收起来。

所以呢这其实就是我怎么去在surface cat里面做lighting,哎这里面这个就比较复杂了,这也是其实我觉得lumen比较难懂的部分,这张图呢是我们土法炼钢自己画的,其实包括一些名词。

我自己都优化掉了,比如说啊,其实他这个时候最核心的呢,要生成一张什么图呢,就是下面那张图叫surface catch final lighting,不好意思,那张图我觉得我应该标个不同的颜色。

就是说service cash,我们刚才讲了不是有四张图吗,有abele normal对吧,OPPITY还有什么呢,还有他的这个呃depth对吧,但是其实啊你这么多都有了之后,我给你一个光在场景里面。

其实他最终是要选出他一张lighting图的,这因为这张lighting图上面就储存了,乘上百万的小灯泡,它是我lumen工作的整个基础,好,那我怎么样的算他的lighting呢。

我的这里面我自己肉身标记了三步,第一步呢,实际上呃你用一个最简单的方法做它的direct light,很简单,就是说对于surface concash上的每个像素,它的空间就有个位置对吧。

那我跟黑跟光源对吧,算一个它的设定值,但这里面的话呢,其实刚到五炮的第一个问题就是,如果你的沙雕力怎么办,那很简单,我做过shine map对吧,我用光年做SHTP,我其实知道visibility。

至少我不会错的太离谱对吧,那么第二步呢其实是比较复杂的,就是他为了做这件事情的话呢,他在word space里面其实建了一批这个对光的这个,WORKALIZED的表达,诶。

他很多计算机是基于这个WORKLIFE的表达,那这个表达为什么这么这么重要呢,因为你有了这个表达之后呢,你上一帧的这个WORKALIZED的这个光的表达,可以被这一帧就是它的第三步可以采集回来。

然后呢采集回来,这个采集回来不是只是采集一根光线,它实际上是回很多根光线,这样我就能够猜出surface上的delighting长什么样子好,我猜出了你的INDIRELIGHTING长什么样子。

我把这两个合到一起,就变成了我的这一帧的这个final lighting,诶,我从我的这一帧的final lighting呢,我又把它采样成这个workspace workalized的表达。

这个这个放在哪呢,给他下一针用,你现在这个时候很绕,就是这个替云纵左脚踩右脚,左脚踩右脚,但是呢这个东西他这个方法其实是非常的巧妙,但这个方法其实呢也不是他首创的。

其实在以前老的一些ROG上也抢到这个id,就是说我们的光啊,在每一次render的时候,我只算他的一次bouncing对吧,但是呢我去再采样一个上一帧里面的那个一次,BING的数据。

我用那个一次SPONSE数据,对我这个你的每一个空间点进行lighting的时候,我把这两个lighting效果叠加在一起,实际上是什么呢,它就已经是二次BING了,诶这个在数学上大家可以自己去推一下。

那我随着时间的积累,你比如说第一针的时候只有一次BING对吧,当T加F0,我们一般叫F0到F1的时候,其实我就有这个两次BC的值了,我F2的时候,其实我就有三次BBC的值了,它实际上这个猫体方形的数值。

就可以一次的积累,其实在那个呃如果我没记错的话,应该在那个SSGI里面,其实他可以用这个思路也做这个MULTIPING的结果,对吧,你就要从previous frame取出去。

你其实一样可以做这样的一个事情,所以这个呢是他的LILIACTION,一个很关键的一个思想,那这个东西的话其实讲起来比较复杂,我不不是特别有信心啊,完全给同学们讲清楚,但是呢我尝试把它梳理一下。

所以呢大家看到我这边人人肉,打了一个很大的标记叫123,那我接下来就从一步,两步三步给大家去讲一下哇,已经两个小时了,好刺激,那吉尔和拉丁刚才也讲到了非常简单,第一步对吧,那我很简单。

就是说我对这个这个配置的话呢,我就是每一个配置我去找这个lighting对吧,那我呢就是sampling一个shadow map,我就知道这个shine map,我就知道我这个点实际上对这个东西有没有。

那shine map怎么怎么去sample里呢对吧,那很简单,我也不用真的渲染沙滩map,实际上大家想到了我RETRING是不是很方便啊,对不对,我就在我的SDF里面去走啊对吧。

我就是我眼睛看到那个mesh cash,那个那个那个点,那个点的话,它空间上有个位置,然后呢,我就去问他和光的那个那个点和光的连线,我做一个,我再发一条光线,那我用SDF1查,我就知道了。

这光线到底是可见不可见,所以刚才你看我画了那么多屏幕,讲retracing,这个时候就已经用上了,对不对,哎那这时候我就可以把这个direct lighting就算出来,因为我知道你的AIDO。

我知道你的法向,我又知道你的光长多大,那我自然就知道你的那个direct lighting是怎么回事,对吧,当然这里面假设就是点光源那个方向光源,或者是那个那个那个spotlight对吧。

好那么如果你有多光源怎么办,哎它其实很简单对吧,它它就是说那那很简单,那就是我对于每一个,就是这个这个这个那个那个那个surface cash,里面的一个text的话,我一个往下算一遍。

把你们累加在一起就可以了,因为我这个是当个小电小电灯泡用的是吧,我也不care我,我我假设我是一个defuse面的一个反射对吧,所以我就可以把这些光累加在一起,这个东西其实非常的重要,为什么呢。

就是大家想想看,我今天做所有的GI的算法,如果我假设场景里只有一个光源,有积压效果的话,很可能是不可能,因为当时当artist真的去构建这个环境的时候啊,它的光啊是可以随便打的,他会给你一个主光。

然后呢做个场景场景里面再放个光,我这个地方是不能限制那个designer的,所以的话呢这个时候其实任何一种for real time,那个for gaming的就是for游戏实战用的解压算法的话。

他一定要支持多光源,你看这样的话它就会非常简单的支持了多光源,而且效率还非常的高,好诶,这个时候啊,这个时候呢我们要做第二件事情,就是说这个如果我们去去采样这些,这些光的时候啊。

实际上我们实际上呢就是在在这一趴,跟大家讲一下,就是诶稍等,Promission information,就是说我们对进行光源形采样,其实这个它只能对于很近的物体有用,为什么呢。

因为如果我们去踩得非常远,它就会出现一个什么问题啊,出现就是说我们那个要hit掉很多的物体,对不对,所以我们真真正能精确的知道你hit到哪个物体,hit到他哪个表面的这种recasting啊。

他其实做不远,那我这个时候我要去求一个点对吧,他的那个那个cashing,他的cash lighting,如果跑的特别远程嘛,我就必然要用那个前面讲的那个global的SDF。

但是GLOBTF他有个大问题是什么呢,他只能找到采样点对吧,他只能找到他的normal,但你并不知道你hit到了哪个instance,哪个物体,所以那时候怎么办呢,他就想到了一个办法。

他说啊对于近处的物体,我可以精准的把一个物体表面的这个采样的,这个radiance给你达到,但是对于远处的物体又怎么办呢,我把整个场景以相机为中心,做了一个MOLISE的表达。

这样的话你的瑞只要你用global sdf hit到了,那我就给你提供一个那个点上的亮度,因为那个点上亮度我就能做我的灯泡了,对吧好,那传统艺能就来了,很简单,我做一个clip map对吧。

这个clip map里面的话呢就是我四层,然后呢每一层64×64个,这个WAKO它这里面的数据非常有意思,就是说他每个WORKO我们查了一下是0。78米,哎我们的同学还是很强的。

我们真的是看原代码就能看出来的,0。78米,然后我们反算了一下,为什么是0。78呢,应该是0。78×64,好像正好是50×50米,哎我觉得这个这个这个就是哦,这个原作者应该是一个公制单位的热爱者。

因为你知道很多美国人是用什么英尺啊,这种东西我就用的特别头疼吗,但是用米的话,一个是欧洲人,欧洲人喜欢用米对吧,那就是说啊他就是50米乘50×50米,那这样把它缩到一个3D的texture里面。

那这样的话对于每个OXO呢,我在六个面存储它这个亮度,这样的话其实我再去做这个就是image cashing,我做那个intro lighting的时候,其实我就可以去永远hit他一个东西了。

这个东西其实在后面非常的有用好,OK那怎么去对空间进行采样呢,刚才讲的就是,比如说在那个比如说SBUGI里面,比如像那个VXGI里面呢,它一般都是用保守观察号的方法去做对吧,但是呢在这个lumen里面。

他的方法呢就比较巧妙,因为他觉得我既然整个场景我都是有这个mesh,SDF表达了,对不对,那我就用SDF啊,它很简单,他就说他先呢就是说找了一个,他把这个这个WALKMAN呢分成大概是我如没记错。

是44的这个tile还是更小一点,或者每个WORKO,他其实就知道这里面有多少个incident,大家想象一下,如果在12米的范围里面,你不可能框太多的mesh对吧,然后呢我从它的这个边上。

比如说这条边我可以随机的设一根锐进去,如果我能打中任何一个mesh的话,实际上表示什么呢,我这works里面是不会空的对吧,而且我能采样出来你的这个法向啊,你的颜色啊,这些东西其实他就是没有用到硬件的。

Rust riser,直接用他的mesh sdf,他就可以获得自己的这个vocalize,的这个世界的表达,所以你可以看到就是整个lumen,他的很多计算机基础啊,用的全是F,但这里面还有很多的细节。

比如说诶我一假设我做了多次采样,我喝得到很多的面对吧,或者我沿途采到了很多的点,怎么办,这里面的lumen里面的它都有很多的细节去展开,那我们这边今天不展开,但是你大家就要记住,就是处理完之后呢。

我就能得到这个世界上的一个works lies的表达,那那这里面就讲了一个前后多个hit怎么办,它它是在一个44的这个town里面,这个东西是做什么的,其实我的理解就是它的空间切成很多小格子。

这个格子当然比VOX要大一点,那么它吧比如说我有1000多个物体对吧,或者是1万多个instance放进去的话,那我在每一个小的tale里面这个区域,比如说34米的这个区域里面的cube里面的话。

它顶多也就是七八个五六个物体,这样的话我在这样一个就是比如说呃,比如3米乘3米的这个cube里面,我去设一个瑞,只跟大概四五个物体进行求教的话,这个效率是非常非常高的。

所以它的VOLATION速度也是非常快的,那么这个selection的话呢,就像我前面讲VXCI呢,它的更新也不需要每一帧全部更新对吧,它只需要每次你相机移动了,或者场景里的物体移动了,诶。

我只会把弄脏的那几个地方,把它更新一下就可以了,这细节我就不展开了,但是呢他大家记住一点,就是它是用SDF的求教,快速的就得出了每一个WORKO的,第一个就是有没有东西,有东西他应该法向朝哪。

它应该深度多深,然后呢他的lighting应该是怎么样的,他就这个方法就弄得落获得了那么好,当我知道了空间的这个WAKO的表达,我知道这个焦点的时候,那我怎么知道这个walkle lighting呢。

哎这个时候其实就比较有意思了,它实际上呢是这个东西就是个鸡和蛋的问题了,就是说我假设把空间上的所有的表面的WORKO,全部找到了,每个WORKO有六个面对吧,我就朝外面的面有有用。

朝你们那面全没有用的好,这个面我怎么知道他的生命是多少呢,诶刚才不是讲了,我有这个这个surface cash嘛对吧,那么surface cash呢回到这张图啊,我觉得这个这个要怪我时间太紧张了。

没有办法讲的很清楚,但是我觉得还是要回到这张图来来来,如果对于我的第一针的时候,大家可以认为这个时候我的WORKO,那些空间上的WORKO全是黑的,你不用管他对吧,那你既然因为TF0的时候。

F0-1是一帧,这一帧不存在,所以呢INDUALIGHLIGHTING也是没有的,只有direct lighting,这个时候你发现没有诶,我surface cash那个final lighting。

实际上就是直接光照的结果,对吧好啦,那没关系啊,你直接光照的结果,假设我已经知道了空间上的works的表达,然后呢我又知道这个每一个WAKO的这一面,比如说比如说这个VOXEL啊,这个这个不太好。

我就讲这个吧,比如说这个地方你看到大家看到这个啊,相机近点这个地方这个WAKO对吧,这个面OK我知道在那个就是surface cash里面,它对于哪个card的哪一个面的哪一个pixel。

我可不可以知道,其实我甚至可以知道它的整个覆盖面积,那我怎么办,那这个WORKO的这个面的亮度,是不是可以直接取那个cash里面的值啊,这个地方到底是直接取一个点还是filtering。

我已经不太记得了,但是呢啊lumen里面肯定是有办法可以取代,但是它最核心的思想就是,我用这个surface cash的final lighting的结果,去照亮我的这个WORKO的lighting。

诶,好这个works the lighting呢,我把它存在,那等我下一帧去再去更新,我的这个surface cash in发达了nineteen的时候诶,我就用这种WORKALIZE的这个世界的表达。

去这个帮我去做这个in det lighting,诶,而且这个时候呢我取得的东西的话,天然的就具有multi bing的结果,这个方法其实非常的巧妙啊,那但是呢实话实说他在工程上特别的复杂。

而且这个这个就是works lighting呢,实际上和后面他讲的那个worst space pro,是特别特别容易混淆的,那这里面我给大家做个区分,就是说这里面的这个works lighting。

它指的它的每个面,它首先是一个是一个是一个cube的六个面,而且每个面呢它只存一个亮度,啥都不存,但是呢worth后面讲的那个worth it probe,它实际上是一个空间上的光场分布。

他那个作用是什么呢,那是照亮别人的,明白我的意思吧,他是照负责照亮别人的,而这个你们存的是什么呢,哎我被照得有多亮啊,这两个概念很容易混淆,但是大家没办法,我们只能够就是大家这个这个这个容忍一下。

确实是很复杂,但是你确实会发现这样的一个算法,他就真的很巧妙,就是通过因为这个方法为什么好呢,大家想想看,我们rendering的话,111秒钟有30帧对吧,你这样的这个light在。

如果场景的相机动得不是特别的快对吧,光动的不是特别的快,假设像很多时候我们都是相机基本固定嘛对吧,然后那个光也差不多不会太动了,但实际上不出十几针吧,你就能得到十几次boss的光的结果。

这样呢这个光啊看上去它就很自然,哎这个东西为什么很重要,就是我所以我们自己还做了个实验,就是我们用lumen的效果,我们动了一下光之后,我们可以明显地感觉到那个光啊。

就是它会有一个大概可能是零点几秒的感觉,那个光嗯慢慢就变亮了,其实难的就是这个works lighting,他在给你传递那种MULTIFUNCTION的那个结果对吧,这个很有意思。

就是大家有机会可以看一下好,这就是我这边顺便小小的黑一下,就是我们看到很多lumen的截图的时候,他一般给你的都是一张竞争对吧,一张竞争,然后呢你看起来非常的漂亮,那张竞争你就会看着很漂亮的话。

大概率是开了高配,而且呢已经炫了,大概有比如说哎这个0。5秒或者一秒之后,这个多少次BING的结果看上去非常自然,但是如果这个动画的话,比如光和相机动得非常的快的话。

其实我觉得就现在的这个real time gi的技术的话,都还是蛮挑战的,OK好,这就是我们的整个light cashing的pipeline,它最核心的就是让我们怎么解决,就是说我的光源怎么来。

就是我要算基,我要知道空间上无数的光源,那这些光源呢,我就用通过这个方法把它cashing到我的surface cash,其实我的surface cash1套之后呢。

我又用surface cash还在一个WORKALIZE世界的表达,你又做了一套这个东西,不仅是说A帮我去更新,诶,不好意思啊,我这个PPT写的我还要再优化一下,时间实在太紧张了。

就是它不仅是帮我们去算那个surface cash的那个,Final lighting,其实这个workspace works lighting的话,在我后面的那个problem里面也是有用的。

为什么呢,刚才我讲到一个细节了,就是说当我一根锐射出去之后,如果我没有办法用那个就是PROMESH的STF,我必须要用global s t f的话,刚才讲过global s t f的问题是什么。

就是他拿不到你到底诶,稍等是这个这意思,他拿不到,就是说那个你到底hit重了,是哪个instance也拿不到他,你更拿不到你hit动作是哪个面,那个那个面上的他的一切信息都拿不到。

所以呢这个时候你只能在global的这个works lighting里面,去找到它的lighting,所以这个数据就是一套一套对应好的,哎呀我我现在已经突然想起来,这个突然想出来这个PPT怎么画了。

他真的就是数据是一套一套对应好的,就放在这,那么这一趴呢我就不再讲的足够太深了,就不展开,但是呢大家理解一下,就是说他用一个就是说啊surface cash对吧,把整个空间把整个场景表达成一个个的六面。

六个面的那个剪影,就相当于说我本来本来一个人的物体诶,我用六个平板把它罩起来,你们知道在那个呃在做LD的时候吧,有一个叫impose技术点吧,就是说诶我一个远处的物体,我用几个面表达成IMPOSTER。

就大概能表达它的样子,其实你可以认为那个surface cash,看你那个mesh car的技术的话,其实很像这个一个为lighting准备的这个IMPOSTER,那么好。

我又不是所有的物体都能用impostor去表达lighting,也不是所谓letting impossible impose表达。

我同时呢要做multi bouncing the global nation,那怎么办呢,诶他想到了一个方法,就是说我把空间整个把你这个这个哎呀,这个PPT真的要优化一下。

那个就是把你空间整个给你WORKALIZATION,就变成一个表达一个一个更加粗的,但是呢它能表达几百米范围之内的,这样的一个场景的,这个这个这个lighting的这个信息。

你无论是近处的promise的表达,还是远处的整个场景,大致看看它的亮度的话,其实都可以表达,这里面其实还有个细节,我们今天没有展开,比如说有些比较复杂的东西,比如说terrain对吧。

terrain你肯定不能用match cut cut cut cut去表达,那你怎么办,诶terrain他还得单独处理,其实lumen里面还有很多的细节,比如说啊我这边在市面荡开一笔。

比如说你中间假设有一些participate media,半透明的一团雾对吧,那它的光照怎么算,哎这里面有无数的细节了,对不对,那我作为一系列的课程也就不展开了,反正这里面坑特别多。

所以我觉得这个作者还是非常的了不起啊,就是真的把这个技术工程化了,因为全局光照real time real globe dation,而且PDNCALIZE,它真的就是一个非常非常复杂的一个问题。

那么他基本上用了这样的一个方法,然后呢能能踩到cashing了所有的radio,那这个时候呢我就比较简单了,对于每一个这个surface cash的东西呢,他呢说那我既然你对这个世界有这样的表达。

我就知道怎么去sample你的in your lighting了,他的算法是写死了的,我记得我如果没记错的话,我们呢是这样写死的,就是说哎对于surface cash上每88,它定义成一个TL,注意啊。

就lumen in的名词真的是从用率特别高,这个tile这个词在各种地方都有用过,而且每个地方的tell,它表达的意思都是不一样的,所以这个地方的tale指的就是在surface cash里面。

他选择88的这个text,然后呢它采四个样,这四个样呢实际上是在你们JERING的对吧,然后呢他设了16根锐射出去,这个瑞呢跟谁求交呢,哎跟那个WORKO,你空间上的WORKO表达进入注意啊。

就是surface cash不会用自己去做intern lighting,他永远是在那个啊WORKO上面,就是那个worko lighting上去取,他的那个就是那个结果。

然后呢诶我就可以获得这样的一个intro lighting,他把这个intro lighting呢存成什么呢,存成了一个就是这个sofil harmonics,那为什么除了存在SURFHONEX呢。

大家想想看啊,就是我这个空间上这些数据,我真正在shading surface cash上的每一个pixel的时候,哎你看这里面这张图,你们可以看到就是它是8×8,里面有64个点对吧,它只有四个采样。

所以对于每个点来讲的话呢,他要找相邻的四个点去插值,那差值最方便的是什么呢,用SHCOFM去差值,大家仔细推推导一下,就知道这里面还是很巧妙的一个一个变化,我有了这个差值玩的SH的表达的话。

我是不是就可以可以算出来,说这个球面上的间接,这个INTERFLIGHTING对我的shading的结果,实际上我这个时候我的结果上就会加上一层,这个就是dua lighting的结果,那这张图上呢。

就是你可以看到就是这边亮的是它直接光照,对吧,那个intro lighting是在间接光照,这里面,其实那个直接光照它是HDR的,所以你看上去它会偏亮,但是实际上的话呢它这些亮度差得很大。

然后最后合到一起,你可以形成一个你想要的final,结果这个图本身做的呢我觉得不是特别好,但也没办法,因为呃原作者没有提供比较好图,所以我们只能在unreal里面自己写代码,这个东西抠出来了。

后面我们有时间的话,我们会扣得更好一点,但是呢这些东西的话,实际上是啊,我们真的是从代码中深抠出来的东西,对吧对吧,大家原谅一下,那么其实的话呢,这样两个lighting就可以结合在一起。

形成我们想要的这样的一个multiple lighting,而且这里面为什么这个方法非常巧妙呢,就是说其实真实的游戏场景非常的复杂,他用了这样的一个surface cash的这个思路啊。

他还把有一个很难的问题给解决掉了,就是自发光,哎大家如果在这个做游戏的时候,其实自发光这件事情是真的很难,为什么呢,自发光这件事情如果你只考虑它本身变量的话,那很简单,在最终颜色上硬生生的加上去一个光。

对不对,但是我们设想中的自发光是什么效果,比如说哎我这个武士这边有一条灯带,很帅对不对,但你旁边假设我靠近了一个墙,这边假设有一堵墙啊,你希望这个蓝色的光,是不是能把墙稍微硬亮一点点对吧。

我甚至还希望有那么一点点软阴影的效果,那这个怎么解啊,这个其实非常的难啊,因为你知道在游戏里面,我们处理一个光源原始的做法,我觉得渲渲染一次对吧,我最让我们在前面人队里讲了很多方法。

能解决MTILISOURCE的问题,但是我这是一条光带啊,大哥我这个很难是一条光带,我怎么去渲染它,诶,他用这个就是这个surface cash的方法的话,其实即使是一个光带。

我实际上也能够把它整体的cash到我的这个,这个这个就是lighting里面去,我在第一帧的时候,这个光带不起作用,对不对,但是呢我通过这个左脚踩右脚。

我把它三零到我的WORKO的那个light space里面去,诶我下一针就把它给卷回来了,诶再卷两次,卷一次,卷两次,你就能看到那个墙那个地方就会被照亮了,这个地方,其实我个人觉得还是非常非常的巧妙的。

所以surface action说句实话,我乍一看的时候,我我我我我喷了很久,我说好麻烦啊,为什么我要给每个mesh还踩六个面,这个好蠢啊,因为呃呃不好意思,不能说脏话。

就是这个这个反正我就觉得好麻烦对吧,很很很很,你还要去做atlas还是做packing,还要做这个那个内存的分配啊,想想头都疼对吧,我以前特别不喜欢,就是实现那个virtual texture那个算法。

因为就觉得特别麻烦,而且特别容易写出bug,但是呢你仔细想仔细想仔细想,你发现哇这个方法还是很有道理的好,那这个就是其实呢这个地方,我觉得那个mesh cashing啊。

包括那个works workitty啊,其实他都符合刚才我讲的SDF的一个设计思想,就是说我把一个irregular的东西,就是你想在世界里面的这些物体的表达,非常的复杂,对不对。

我用mesh cashing,用用match card,用surface cashing,再加上works lighting的话,把它变成了一个uniform的regular的表达。

那我接下来无论是做他任何的一个积分也好,这个卷积也好,采样也好,都会变得更加的简单,你看这个采样采样采样,这个时候采样的基础是什么,是数学的表达,对吧,我我所以说我觉得学完104的同学的话。

我觉得大家会非常有兴趣,回去学一些什么信号处理啊,什么什么这个这个理这个这个局,那个应该是那个呃应该是线性代数,大家肯定要好好去学的对吧,包括一些几何的一些东西,包括一些比如说像一些数分啊。

一些高等代数的东西,大家都会想学,因为这些东西真的是密切关联的,对于我们来讲好补水了,我们继续往下讲,我们已经讲了两个小时,20分钟,预计今天要三小时起飞了。

好其实呢就是对于整个这个surface cash啊,他的这个更新还是挺废的,所以在lumen里面他做了一个bug,他就说哎我每一帧的话对,直接光照我最多不超过,我不是40996×4096吗。

每一帧的时候唉,我最多不超过1024×24个,TEXO更新对吧,那么for intro lighting呢,因为大家知道间接光照更新起来,其实还是很废的,因为他要在那个很多的那个这个WORKLIES的。

这个世界上去采样,对不对,虽然我讲了基于SDF的采样效率很高的,基于GLOBUSDF是更快了,但是它本身还是挺废的,那怎么办呢,他说诶我每次最多更新512512texture。

所以对于每一个mash card来讲,它都要排排队,说哎我也想更新,我也想更新,那他就要设置一个priority,去进行这种这个去去去管理它,然后呢去选择更新,所以呢这里面其实有一些一整套的。

比较复杂的排队算法,还有bucket salt这个算法,但这个算法的细节我已经就不展开了,因为有兴趣的同学可以去看它,但是你只要和就这一趴lumen,大家就知道了,光到底是怎么设计呢。

且在这个世界里面我把它抓住的,对这个就是我先讲叫freeze,你把这光抓住,就像我,大家也就我又要再提我心爱的phont mapping了,就是phont map里面,最后我要把这些光子。

把它固定在这个mesh的表面,我只要把你这光子固定住了,接下来我就可以做CD了,好,那接下来呢,我们现在只是把这个shading cash住了,那接下来我们要干什么呢。

哎我现在虽然知道了这些光子在物体的表面,但是当我一个做shading的时候,实际上我知道比如说这个mesh的这个表面的,它自己的亮度,它的照度对吧,其实并不能作为我任何一个mesh。

就是任何一个像素设定的基础,我得把对于一个对于一个呃屏幕上的像素而言,我老师指着自己的身体,我现在变成了一个rendering object了,对吧好,那比如我要渲染这块好,那我呢是要把我周围半球面的。

所有的radiance全部拿到,我要得到一个什么东西呢,叫prom a对吧,搞了这么多,其实你这个光照,就是你这个地方还没有办法渲染,因为你只是知道说比如说我面前的这个灯,比如说这边有个灯对吧。

我放到这边来这个灯啊,这这个mesh,比如它它的各个各个点的照度是多少,这个我这只手的照度多少,当我要训练这个肩膀的时候,诶,我要把这些这个radios全部变成一个proper的表达。

所以接下来硬核的东西来了,我怎么去分布这些prop,然后呢对于每一个屏幕上的点,我到底怎么用probe去这个这个这个lighting,所以呢它的第三排也是这个lumen讲lumen的时候。

特别容易上来就讲了东西,就是说我在screen space怎么去分布这些prop,并且能采样到我要的东西,那其实呢他又在worst space做了一些prop采样,所以他搞了两种以上的prop。

这样让你能够永远的踩到东西,所以这是我们的第三方,但那第四趴那就讲了什么呢,我竟然有了这么多的prop对吧,那好我拿到一个screen speed pixel,我怎么去用这些prop做shading。

基本上讲到这一趴,整个lumen就讲完了,好我们到第3part了,也就是lumen的这个经常提的一个东西,就是这个screen space part,在屏幕上的part,这里面呢其实它的基础的idea。

我个人觉得还是非常非常巧妙的,因为啊就是我我我想起来了,今天我还有一有1part没有讲,叫dd j i对吧,diffuse这个dynamic,diffuse global innovation对吧。

还有最新的一些国内的工作,就SDFDDGI对吧,这些工作其实啊problem这个东西呢,你最自然的一个想法是什么呢,在空间上均匀分布,我撒无数个采样点,然后呢,用那个点对一个球面空间的光照进行采样。

因为我既然已经得到了一个surface cash,我又得到了一个WORKO的这个这个,这个surface的这个lighting the cash,其实我去构建这个prop是可以的。

但是呢当我真的去渲染一个场景的时候,场景里面他的这个起伏是非常非常多的,那你的pp怎么分布呢,靠近camera,我放的密一点,离开camera放的远一点,可以的,但是呢当我出现了一个几何结构出来之后。

你比如说1米1米,一米隔一米放一个problem的话,实际上它并不能保证,你真的能够表达广场的变化,但这个变化如果你表达不了的话,实际上你照出来的东西看上去就很怪,就是我们经常用一句行话讲。

就是看上去很平哎,这是所有的,就是如果预先生成好的这个proper displacement的话,他都会有这个proper distribution都会产生的问题,而lumen呢他就比较大胆。

他说我就在screen space打prop对,很粗暴,意思就是说我狠一点的话,我屏幕上的每个像素点,我对它进行整个球面的广场的这个pro采样,那我选出来了一定是对的对吧,但是呢他还没有那么粗暴。

因为如果每个像素点都去踩一个的话,那实在是太疯狂了,他就说那我还是悠着点,我每隔1616个pixel诶,我踩一个screen space的这个problem,这个为什么16×16这个事情有道理呢。

其实很简单,就是说啊你相机看的话,如果离你近的地方,1616个pixel啊,它其实在空间上的距离不会太远,而间接光照呢这个东西它是个低频的东西,所以呢你在这么近的距离里面。

它的virus其实确实不会很大,那么它高频的东西呢,就像我前面讲过,就是它可以用那个表面自己的,这个就是说法线啊,这些材质的细节可以表达出来,所以低频的光照间接光照它可以直接上采样。

而且它每个prop的采样呢,它采了两个数据,第一个当然是radius了,其实呢还包括了一个hit distance,那他对这个东西的,就是他怎么去存储这个problem呢。

这里面一个细节就是用就是那个就是啊叫啊,OCITRON那个main,这个mapping呢,实际上是参数化里面一个非常经典的一个mapping,就是这个这个map,如果同学们在做任何的GI算法。

包括采样算法,我会建议大家去研究一下,其实它很简单,就是说我们在在图形学里面经常遇到一个问题,就是在球面上撒采样点对吧,那最简单的采样是什么呢,经纬度采样对不对,经纬度采样呢。

如果你把它映射到一个2D的texture,它会出一个问题,就是说天顶它采样密度特别高,靠近赤道采样率都很低,那大家一直希望一个分布相对均匀的采样,但是呢它这个采样还有一个特点。

就是我给你任何一个一个一个就是一个方向,我能迅速地知道它的UV空间的位置,那这个数学上他就要求一个是连续的,一个要非常简单,而这个八面体的这个球面映射呢,他就满足这个特点。

第一个它的任何一个方向映射到2D的UI,计算非常简单,就是下面这个SHADER,同时呢它可以进行BINARINTERLATION,因为你相邻的两个TXT之间的采样点的采样,在纹理空间的差值。

基本上逼近于在球面上的差值,所以它是一个非常好的参数化,所以这样的好处就是说诶,我可以用一个不多的采样点,相对均匀地分布在球面上,那么在这个就是crispace prop里面的话呢。

他用的这个采样精度是8×8,也就是说对于整个球面空间的话,哎我上面这个方向大概才四个,下面这个方向才八个,这个方向要踩八个,诶,我大致均匀的分,当然这个不是严格的大致均匀,这样去分布了好。

那么然后呢他有一个非常有意思的思想,就是说那我每隔16个screen pixel,我做一次采样,但是呢如果你在这个screen里面,因为我有depth,我就知道你这个彼此之间。

在真实的物理世界的距离有多大对吧,worst page距离有多大,如果你两个相差特别大,比如说朝向一看,我就知道你们俩根本不共面的,对不对,比如说虽然这个在视觉上投影上,就是在相机位置。

你看上去很相邻的两个pixel,在在真实的物理空间上距离非常远,那怎么办,那你1616个text采样,它其实是有问题的,如果你强行的这么干的话呢,你就会把很多光照的细节模糊化掉了,这个东西怎么去理解呢。

我记得在天文学上有一个概念叫做试灵心,大家有没有听说过,就讲的是两颗恒星,你看上去很近对吧,好像谁相伴的谁,比如小时候我们去听神话故事说,诶这个食指两颗恒星在一起,什么北斗七星啊,我们在一起什么在一起。

但实际上天文学老师,天文学家会告诉你说,他只是在试在视觉上看上去很近,但实际上他们真正的距离非常远,为什么呢,他们的深度值是不一样的对吧,他们很可能相聚了是几百甚至上千公里光年,对吧。

那实际上呢在这个lumen screen space,这个我的这个低度采样的时候,就会出现这种情况,那我就需要有一个方法,就是说如果我发现啊,我在这个16×16的这个采样区域里面。

它其实很多点之间的这个距离,在真实距离非常远的时候,我认为这个采样精度不够,那我怎么办呢,我去refine,我把它藏密度在那个在那个grade里面,我把它再增加一倍,变成8×8,8×8不够怎么办。

我再给他refine一下,我变成4×4,这个听上去就很神奇了吧对吧,那怎么知道这个东西我要去refine它呢,诶它是基于一个基础的假设,就是一个有效的差值,这个有票的差值怎么去定义呢,就是说想象一下啊。

我对于一个16×16的这个这个,这个这个这个这个一个tile,就是我一个spring weet prop所取得这个区域,假设我任何一个pixel我要去渲染的时候,我要设定的时候。

我要从这四个problem这个采样,就是那个从我临近的四个probe之间去取取,它的差值,我这里面的取,比如说取16个或者取32个点,我去采样的时候呢,我这个点呢其实除了我自己的空间位置之外。

还有什么呢,还有我的法向,我就会得到一个平面,我把你这四个prop的中心点投影到我的平面上,我去看你的投影距离的权重,诶,这个时候作者就开发了一个非常high的一个函数,大家看到了,这里面就说诶。

我距离的平均相机到那个点的距离,还有他要乘上一个这个到ex f的那个,就是那个ex p就是他的那个多少次幂对吧,还给了一些很牛逼的一些常数放在一起。

然后呢他说你这个error只要累计大于某一个press hold,我就认为这个采样点是不能用了,如果我这些采样点足够多的不能用的话,我认为就是你这四个采样点对我是无效的。

这个思想就是在基于我的这个点的法平面,去做投影距离进行插值,包括我的空间距离差值啊,这个思想其实啊如果我没记错,好像是在那个r seven里面,还是在那个就是啊WAI里面都用过这个思想。

就这个思想其实是被证明了,是个很有用的一个思想,因为这个思想的话呢,其实哦哎好像是S级里面用了也用了这个思想,就是说这样我就可以就是避免,就是我的采样是无效的采样,为什么呢。

因为我相邻的两个pixel之间相距,可能会在真实世界里相距可能会非常远,对不对,那么同样你踩过来的这些,这个这个这个就是props,它在物理空间的位置可能是非常的远,那对于我这个点所设定的时候。

如果我用了你这个pro实际上就是无效的,当我这种无效率大了足够多的时候,那我认为这个采样就是不够的,所以呢我就要申请,你把这个tile再给我去细分一下诶。

我再去采用一个额外的pro这种adaptive sampling,实际上是这个lumen,我认为是一个非常聪明的一个做法,因为这个方法你听上去可能非常的复杂,但实际上呢。

他对存储空间的消耗并没有大家想象的那么大,为什么呢,他把screen space所有的prop做了一个APOL,那大家想想看啊,我们做texture uv的时候,一般是不是一个方形texture对吧。

但是呢我们在绘制的时候,屏幕一般是什么样子的,一般是一个长条形,那好那假设我屏幕上的pixel都是1616的,你们发现没有,我把这个prop就是每个prop是个88嘛。

我就占用88的那个那个那个text,我当当当当存进去的时候,你发现没有,下面正好有一节空间是没有用的,对不对,诶,他的聪明的地方就来了,他把你这些需要refined的这些problem。

我就把它packing在它的下面,反正我就存个index就好了嘛,就相当于我每个spring pop我会存一个值,说哎我这个problem有没有被refine,如果有被refine。

你你的位移应该在哪里诶,我就把它存在,那同样的,我你我找到这个如果是L0的这个problem,觉得这个反过来就D最大最粗的那层problem,找下去发现它需要一放,我就找到往下一层,哎。

往下那个project又存了,说哎你还可以再往下走,所以你看他其实没有用多少额外的存储空间,因为你text分配的时候,反正是个方形,放在那下面的地方我都用起来了,但是呢哎我就可以对我的视空间的这些。

这个这个这个lighting的信息啊,进行了一个什么呢,叫做adaptive sampling,自适应的一个采样,这个对这个rendering来讲其实非常的重要。

这个我个人觉得是lumen非常巧妙的一个想法,哎我我我们在分析前面的工作的时候,好像这还是第一个提出来,用screen space的方法去这个进行这个radiance采样。

而且他他还搞了一个这个adaptive,才这样的话就避免了,就是以前我们讲这个比如说啊VXCI啊,我们讲的这个就是那个R3嘛,这些东西,它其实你本质上它都是UI风的采样对吧,像r seven里面的话。

它其实已经有一点点adapt的思想,大家还记得r r seven里面有那些红色的pixel吗,他觉得不够怎么办,哎我还在对他进行采样,其实呢在这个lumen里面的话。

screen space prop的话呢,它的这一套adapt to something,我个人觉得还是非常精彩的一个想法,对,其实我为什么这么有兴趣,给大家去把鲁曼讲清楚呢,我个人觉得就是说。

lumen其实是一个非常具有启发性的,一个算法体系,就这里面的很多算法你不止可以用在GI上面,你肯定会用在一些你其他要用的rendering上面,好,OK那这个地方我就讲到这儿了。

好那这里面呢就是这个是我们课程组啊,土法炼钢的一个一张图啊,如果大家一定要这个原谅我们的粗糙,那么但是呢虽然粗糙,但是我们的结果非常的真诚,就在这张图上,大家可以看到。

就是我们是把lumen的这个QUEPROM打印出来了,你可以看到那种啊应该是黄色的区域吧,哦应该是红色的区域,暗红色的点是1616的resolution,而那个黄色的呢就是这个啊,8×8或者4×4的。

为什么8×8和44没有做区分呢,代码要改的数量地方太多了,我们就懒得改了,所以我们就偷个懒,就是把8×84乘四就统一标记出来,就告诉大家那个地方被refine,大家可以看到。

就是说所有被refine的地方的话都是几何,他这个就是变worries比较大的地方对吧,这个也是很直观的看到了,其实说实话,我我们看了几乎所有的lumen的这个这个presentation。

那大家能看懂的话还是蛮挑战的,OK好那就是就是说这是我们突法炼钢的一张图,OK好,那其实我们在进行这个crisped prop,采样的时候呢,其实我们用了JERING对吧,那接触的原因是什么呢。

就是防止这个东西看上去太repeat啦,或者过度太太太太高了,但是呢当你有多少次多次接触你的结果的话,那实际上它在时序上又变成了一次这个multi bing,这个采样诶。

这个其实也是我们在这个我们最早最早讲那个,按ta类型的ta啊,讲到这个,其实像那个SGI里面,也都用了这样的一个技术,就是我要不停的接触我的采样,但这个就是一个很细节的东西,我们就不展开了。

好那这个时候就来了,我们最痛苦的东西了,我们已经大概知道我们怎么去分布,我们的problem了,那我们就要去采样了呀,采样怎么办,我们不是说8×8嘛,对不对,那我就我就往球面上8×8的这个。

参数化方向去采样就完事了呀,但是呢这个对于真正的RENEE来讲,肯定是有问题的,为什么呢,因为窗户在哪里,我不知道对吧,我在一个房间里,我的英doc里面窗户在哪是一个很重要的问题,因为我的采样。

如果不是使劲地朝着窗户那个方向去踩的话,相信我任何GI的算法算出来的结果,都是像那个怎么说呢,就是像是那个秃头般一样的,就是七七黑一块白一块,非常丑,哎所以接下来一个很重要的东西。

就是我怎么进行important sampling好,那这个大家看到了,就假设我们不做这个important3330的话,我们看到了lighting的结果大概是这个样子的对吧。

但是我这个因为这是原作者提供了一个图嘛,他到底开了哪些上网没看到,我们也不是特别清楚,但是很显然他在讲就是没有input30,我们会怎么样好,但这里面的话呢最重要的一件事情是什么呢,就是找窗户。

就是我要尽可能往窗户的那个方向多设一些锐,对吧,这个其他的地方无关紧,要是能少设一点,就少设一点,哎这就是GI的妙处,就是你需要environment advance,环境感知啊,这个听下来很高大上。

对不对,那但是呢其实我们的render里面很土好,那实际上呢我怎么在进行这个important呢,我们可以看到就是这个lighting函数啊,它本质上是一个一蒙特卡罗retracing对吧。

蒙特author蒙特卡罗这个这个integration对啊,下面的这个概率函数呢,它的我要尽可能让我的这个概率函数,符合上面这个函数的分布,那上面这个函数呢是两个函数的积,一个是光,一个是什么呢。

一个是我表面的BRDFA,这就是找到这个问题的因子了,第一个你需要知道光在哪强对吧,第二个你还知道什么呢,我的法相在哪,我的法向在哪,就告诉我说哪些东西对我来讲可能重要一点,因为你就算光在这儿。

我的法相在这,那你我你就光对我有什么意义呢,对不对,我我其实是我是背对你的,我可能要更多的要踩一下背面的光对吧,所以这件事情就比较复杂了,没有那么简单好,那怎么做呢,那首先我们先怎么去鼓激光诶。

这里面lumen就有一个很巧妙的思想,他说呢,哎呀我当前帧我想知道光亮的地方在哪儿,这个哎呀,不好意思,我打的是英文,打错了,待会我们负责在这个今天真的是火线赶出来的,这个这真的是这这一这一页。

可能是上线之前不到半小时吧,我在这疯狂的在那手打的应该叫approximate,gradient importance from the last frame props对吧。

大家原谅我这个英文的type,但是它实际上讲的是什么呢,哎很聪明,我我既然想知道光在哪怎么办,我把上一帧的problem踩一遍吧,也就是说我并不知道这一帧的光在哪,但是我做一个假设。

就是光的变化没有那么快,那我从上一帧的这个这个prop里面的话,我去从最近的上一段的screen space prom里面,我去做一个采样,就是把它们的值积在一起,合在一起,我就大概知道哪个地方亮。

哪个地方不按,那怎么知道呢,其实很简单,就是说哎你不是什么SH啊,或者什么东西啊,哎我把这四个指路性价值,我一样可以得到一个8×8的,这个明暗相间的这个图,这个图中亮的地方就是光比较亮的地方。

就是相当于是在我这个位置,我大概猜测天会亮在哪儿对吧,所以这个last frame其实在GI里面是非常有用的,就上一帧的数据千万别丢,它有很多妙用,哎这就是他用的第一个方法,就是我去估计一下好。

第二个方法呢,唉我这个方罗姆,那normal大家天然的想到,就是说哎对于我这个problem,我不是知道我这个pixel是哪嘛对吧,就算你JERING,我一定JERING在一个点上。

那我的normal实际上的话就有明确的方向,那我就沿着normal做一个cos nope对吧,那下面的半个那个就是区域肯定是黑的嘛,这个听上去是不是很合理啊,很科学合理啊。

哎但是这里面有一个很大的错误是什么呢,因为你在FRAMEBUFFER里面拿到的那个normal,是一个像素的normal,那个normal是非常非常高频的,大家想象一下。

如果我下面的max是用nut做的哇,那个细节不要太多啊,但是我对于一个比如说啊一个小区域而言,那你们可能cover了,比如说32×32,1000多个pixel,如果更大一点,有更多的pixel对吧。

那1000多个皮索的真正的它的大致的法向朝向,并不能由我这一个单独的这个采样点的法向,所代表大家思想是不是这样的,那如果我这个时候去在这个位置去做一个light,prop的时候。

我是不是要考虑我周边所有的诶几何的,就是screen space连接的这个几何的,它的normal的朝向是这样的,他所以呢他是个什么呢,它是个distribution,唉。

它不是一个单一的一个normal的点,这个地方是特别特别容易弄混的,那他怎么做呢,他这时候就想到了一件事,就是说我在做shading的时候,哎我其实肯定large bob是要插值的嘛,对不对。

他就想了个办法,他呢就是在大概这个32×32的,这个范围里面,32×32什么概念,我不是一个一个一个TOL,是16×16吗,为什么三十二十三二,因为你对这个screen space进行by inia。

TEMPLATION的时候,你会发现你的一个prop的值最多会影响哎,离你最远32个pixel的值,大家想象一下,就是两个两个之间连接,是不是这样的,对吧好,那我在这个3232里面有多少个pixel呢。

1024个pixel,那我把1024个pixel的normal的,所引发的这个distribution function全部加在一起,我是不是要疯掉了,对不对,这个就要死了,那怎么办呢。

哎我认64个点去载你们去采样,你看各种hack啊,而且这个采样呢它还不是一个简单的,就是说我把我就在周围,32×32的区间里面,我就随机砸了64个点,没有他呢还要去做一个什么呢。

Death’s weet,就确保我们的depth彼彼此之间,因为我知道我这个prop这个点在哪里嘛,就是你们我们的DESWEET在我的投影平面上,彼此相差不要太大,这里面有一整套的这个数学的这个古籍。

它简单的讲就是说你的投影距离我太远,法向这个就是那个距离我太远的地方,我全部给你扔掉一堆的hack,然后呢我把这些normal的每个normal。

它其实每个normal的importance是不是个cos loop,对不对,每个cos lol是不是就一个SH对吧,我把这些SH全部积分在一起诶,最后我才可以得到一个什么呢。

norm的这个diribution function,那我有了这样的一个东西的时候呢,哎我大概就知道哪些区域从normal上看,哪些方向,从NO more上看,我需要重点的去采样,我就得到一个BTF了。

好,那接下来呢我们要做一个很有意思的这个,这一页我发的有点早了啊,这个normal视频function,因为这个原图上也讲的不是很清楚,就在讲到下下一页的时候会讲的比较清楚,那我下一页跟他讲。

这个里面呢它就有一个非常巧妙的一个想法,他说啊对于每一个就是screen space prop,我最多呢还是只采样64个,为什么呢,因为我硬件那么多的prop对吧,虽然说我是16×16。

但实际上呃我还是有,大概我想想可能要将近上万个吧,还赚十几万个prop对吧,每个prop要设设那么多的锐的话,实际上现代硬件也是扛不住的,他他就给了一个想法,就是说我能不能够在我需要采样的地方。

采样加密一点,比如说这个这个方向它很重要,我做设四根采样锐主曲,但是呢我存储的时候呢,我还是把它们合到一起,存一个存成一个TXT,因为就相当于说大家想一下这个,这当然是一个这个这个最早的思想。

其实在摩托卡老师内里面就有了,就是说我在做这个retesting的时候呢,那个地方,我因为发现那个地方可能光源很小很密,我会把这个地方射线射的密一点,但是呢最后我在做shading的时候呢。

我可以把这些射线所有的结果,因为他们彼此的角度很接近嘛,所以我可以把它合到一起的,就是做设定的时候,我们并不需要做那么多次的这个这个累加对吧,所以的话呢我要保证总的采样次数不变。

但是呢我要有他的importance诶,这个时候就有一个他一个非常巧妙的一个算法,这个标题是我自己写的,就是说它实际上是说我所有采样的数量,设得瑞的数量是不变的,所有的这个pro都是64根尾射出去。

但是呢我算出来了,你的这个BRDF,就是你的法向所这个所提供的这个这个这个PDF,也就是你的importance function对吧,和你的lighting,lighting是从上一帧抠下来的。

你的important function,我把这两个诶一卷积在一起,我觉得到了哪些点是重要的,哪一点不重要的,那我这时候呢有64×64个点,我怎么做呢,哎我对这个点进行排序,我这样一排序我就知道什么呢。

就是最不重要的那些那些那些方向,和最重要的那些方向,那我呢设置一个阈值,我就从最不重要的方向1231次走,当我找到三个,就是倒数前第三个,前三个,这个就是最不重要的方向,当然假设他们的这个PDF值。

都小于我的阈值的时候,就意味着什么呢,我那个最需要采样的那个方向,我可以对它进行一次super sampling,为什么呢,因为本来只能采样一次,我给你再加三次的话,你不就四次了,四次就意味着什么。

意味着你就可以进行一次refined,sampling的对吧,那以此类推,就是说我通过这个PDF的值,我把你最不重要的方向全部过滤掉,然后呢,让我的采样尽量集中在这个很重要的方向。

这个方向可能来自于你的法向,朝那个法向的分布,也可能来自于光源,诶,这个地方其实是非常的巧妙,就是64根瑞,这也是lumen我认为非常巧妙的,很实战化的一个东西,因为这样就让我的硬件的时间。

成本就可以算出来了,这样的话你看这里面就一张图,就是这个acs pro,它的光线,你会发现它就会集中在墙上相对比较亮的地方,那这样的话,它整个这个rendering的结果就会好很多。

那就是你有这个就是啊fix bug这样的,Adaptive sampling,就基于这个光墙,基于你个normal的方向和没有的话,他两个的noise真的是不一样的,但是它它有很多前后的对比。

其实你根本不知道这些东西,比如说因为它有很多种field dream dnose的方法,每一次你看了都说哦这个东西上去很重要,但是后面一个图的时候,他又说又很重要,但是你不知道这一层层的怎么样。

所以后面等我们有时间的话呢,我们把东西实现的时候一步步的看,大家可以看得更清楚一点,OK好,那么同样这个结果也是这样,前面的话他没有做这个important sampling对吧。

后面这个光方向做了important,important sampling的时候,他很显然这个场景你们看到都有共同的特点,是什么,都是室内诶,都是有一张窗子对吧,窗子就是我们的GI的一生之敌。

那么有一扇窗子,那这个时候呢哎我们这看到就是你有import sample,我对光的采样就会好很多,那我这样的一个积压的效果就会稳定,非常的多好,那有了这样的东西的时候够不够还是不够。

你看我们这边又来了,我们要降噪,我们要进行这个过滤,进行filtering,那么只要你做CI这个FILIN,就是你逃不掉的东西好,那它怎么做filtering呢,其实是这样的。

就是其实按1616的这个screen space,这个这个TOL去做的problem,它采出来的信息其实还是非常非常不稳定的,有很多的noise,那怎么办呢,他每一个prop我在旁边找。

临近的这样的一个一圈对吧,他一般讲33这个kernel,我把周边的prop的这个光线,我把它filter出来,但是这个proper之间的fil train啊,就比大家想象的要复杂了,这里面的大家想想看。

我每个prop我是射出去了什么呢,我设置了64根啊,68乘八六十四根锐对吧,那我旁边那个prop我是把那个锐就是同方向的,我就直接把它给加到一起,这样对不对呢,哎其实是不对的,为什么呢。

因为我旁边那个problem距离我不是一个距离吗,那他呢很可能他测的那根锐啊,他射到的这个物体离我非常的近对吧,他呢那个东西呢其实在我的这个prop里面,他我看过去的角的射线角度是完全不一样的。

这里面举个例子,就是前面有个有一个反射物在我的球在我前面,注意啊,他不知道他是反射物啊,然后说不定光源在头顶上照下来,所以那个那个面罩的非常亮,我这个light probe一定要踩踏了,对不对。

那我我取得我的NEIGHBORNPM呢,他那根锐其实是方向是朝下的,但是呢我如果把那个瑞直接用到我上面的话,那我会发现他彻底用错了,为什么呢,因为对于我这个problem来讲的话呢。

它的方向是从上面过来的,所以呢当我去加权这些re的时候,我是要看你的方向,如果你的方向跟我不一致的话,我认为这跟ray就这个方向是一个不一致的差值,哎你发现没有,这个for循环很好玩。

他写的是说我所有的neighbor prop的,所有的R我都要做一次可用性的一个检测,比如说这里面它就hard code的一个,这个是我们放代码翻出来的,他写的是说如果这个夹角超过了十度,我就不用了。

这个RIO,你这差十哥们,我就不用你了,我只相信我自己,不相信你,OK那好,那如果呢呃呃如果这个东西不处理,你看到这里面就有这个error了,大家看见没有,就是说这个墙上会有很多的noise。

就是因为他在临近会踩错很多东西,好这个听上去很有道理对吧,但这个呢就又产生了另外一个问题了,假设我邻居的那个瑞啊,他其实射的是非常非常的远,你把那个远处的那个焦点拉回来,这个角度呢也是对的,也没问题。

对不对,但是呢你去看你自己,你发现你自己发出来同样一个角度测试光线,你射到的距离其实很近的,所以你们两个锐之间,就是蓝色的和绿色那根线的夹角,虽然小于你的十个度的这个press hold。

但是呢你很明显,你的hit distance和他的his distance有很大的差距,那你又在哈克的一把说,不好意思,虽然我们俩的夹角对吧,看起来好像那么的接近。

但是呢你好像是在100米之外打中了一个东西,但是呢我自己在同一个方向测试,我发现我在5米之外我就被拦住了,所以你那个踩出来了,那个那个radio大概率是对我是无效的,那不好意思,我还是用我自己的诶。

这个地方它又能解决这个问题,因为他这个你不解决的话呢,它就会出现这种漏光的问题,比如像这点这个case里面,你发现那个毛巾的这个内侧面,它跟靠墙的那个地方诶,如果你生硬的不考虑这个差值呢。

它就会发白很多,光漏进来了,被插值插进来了,但是呢如果你考虑这个问题的时候,你会发现诶它这个光也开始变得比较有道理了,怎么样,无数的骇客啊,对,所以它这里面光的差值就是prop之间。

光的差值是非常讲究的好,那整个在一起的话,你就会看到这个结果就会好很多对吧,所以lumen是一个,我个人觉得还是非常实战的一个技术,就是他的每一个细节考虑的,真的是我用一个词形容叫什么呢。

叫周到得非常的周到,哈哈OK好,那接下来的话呢就是说诶,我们虽然在screen space里面可以做这么多的prop,但这个prop第一个数量非常大,第二个的话呢它这个是就是shading呢。

他跑的太远,其实它的效率并不高,那lumen呢又想了一个办法,他说我呢就是在这个screen sweet pop,你就去找一些周边的东西了好吧,但是呢对于非常远的东西。

其实呢你会发现他那个方向啊就射得远之后,他基本上大差不离的对吧,你每如果每一个scrsweet pop,每个ray都跑了那么远,其实你的效率是很低的,但这里面讲一个细节。

就是说我们经常讲硬件的hardware retracing对吧,其实retracing呢,它的性能不止受这个你设了多少个瑞的影响,其实还受什么的,你的场景复杂度的影响,场景复杂度的影响之外呢。

还影响什么,你这个锐到底跑多远,如果你的retracing recasting,你只是非常近的话,它的效率非常的高,但是呢如果你射得非常远,比如说我一下子投个100米远的话,它的效率就会非常的低。

那我们就有一个比较漂亮的想法了,我们呢在worst space里面预先放好一些prop对吧,这个prop里面呢我就把那些远的那些lighting,把它cash在那。

这样当你的这个screen space prop,我要取一个方向的锐的时候,我就可以找一个沿途的比较靠近的一个worth,Facet pro,我把你那个方向的光线给你取出来,诶,这个想法是不是很有意思。

哎这真的是很有意思,因为这样的好处是什么呢,因为如果你的场景啊不怎么动,你的你的哎这个已经跳到后面去讲了,但是其实这两个真的是有,就你会发现它确实没有办法顺序讲清楚。

因为如果你的场景是一个相对静态的场景,光源呢也基本固定,比如说主要是太阳为主对吧,你的相机仍会走来走去,那你screen space的一个probe啊,其实一直是不稳定的,每一帧都要去更新,对不对。

但是呢我家是在worst space里面,预先撒好了一些problem,这个worst space prop,假设我用clip map方法去部署的话,前面已经讲了无数遍了对吧。

我动的时候我只需要在边缘处增加几个problem,后面删掉几个prop,这件事情我就搞定了,其实我只要更新一点点的prop,但是的话呢我就可以获得一个远处很好的,这个光线的这个采集,所以这个地方的话呢。

lumen就非常聪明,他说哎我还要再做一层worst space radio cash,而且呢它的目标非常明确,就是你去解决比较远的这些光怎么来好,那么这个里面这是我们土法炼钢啊。

给大家那个截下来的这个图,你看这个场景都是我们自己搭的,嘿嘿除法连高,然后呢这就是workspace probe的这个分数,大家看到没有,哎他一样的也是个clip map,所以呢他给了一个很神奇的数字。

就是六十四十八乘三对吧,我也不知道为什么是48×3,但人家就选了这个数字,然后呢他大概做了四层对吧,大概clip map的距离大概是50米左右,那么它呢因为是worbased problem。

因为他可能会被srt space兄弟们采用super space,大家记得它的采样角度是多少,在整个球面上也就8×8,其实球面上8×8,自己想想是不是非常的稀疏啊对吧,那我作为老大哥。

我放在外面是作为你们的参考的对吧,给你们试试你的最后的救赎者,那我是不是应该踩得更密一点,这样的话,无论你是上面那个球面的那个那个SCRESPACE,Prop,还是下面那个problem。

你这个方向随便来,我这边的力度都扛得住,都跟得上对吧,你看从这张图上可以看得比较清楚,所以呢它这个采样呢就会这个比较密一点,它会踩到什么呢,32×32,差不多1000多个瑞。

大家想想这个RESPACE这个worst space prom,它就是比较霸道一点,他第一个他踩的距离远,第二个呢它的采样密度是高的,这样的话我很多时候screen speed pop,它不用跑很远。

它只要跑到附近的,what’s the problem就去借他的光嘛,哎这里面就讲了一个很有意思的概念了,叫connected race,我把光怎么接起来,这里面就有点像老中医接骨头啊。

就是这个光我们把它分成一节节的,也就是说the screen space那个problem里面呢,我只是踩这个瑞啊,就往前走那么一丢丢,当我走到这个临近的worst space。

这个problem的时候,哎大哥你的这个方向也有也有也有人,你射出去了吧,那我就不走了,我就接下来问你了,说那边到底有没有东西,如果有东西,那东西有多亮对吧,这个就有道理了。

所以呢这个时候呢其实它的方法就很简单,就是这里面有个很有意思的概念,就是说我在这个screen space里面去做retreating,的时候,我大概只会找最近的一个worst space。

包围他的这样的一个bounding对吧,然后呢我取它的这个对角线长度的两倍,其他我就不走了,这里面有个细节啊,就是那大家会问这screspite prop,这个锐走的这个长度呢是不是个定场呢。

哎其实不是,为什么呢,在近处的screen supp的话呢,他的那个workspace,那个problem的那个那个,那个那个那个那个就是那个那个WORKO啊,它其实密度会高一点。

所以它那个距离就是比如说一米乘一米对吧,你两对角两倍,大概323米左右,但是呢如果你到了远处,一个它虽然也是在你的spring space,但是远处的一个房子那个地方距离你看50米,在那个时候。

你的这个就是war space的那个那个,那个那个WALKO啊,他其实已经比较大了,所以那时候的RIN呢跑的距离就会比较远,诶这个地方一定要注意这条,千万不要写死了,他这个是有很有很深的道理的。

那同样的就是我的word space probe那个那个瑞啊,它采样的时候它也会skip掉自己的对角线,长的那个距离,就是我没有必要进出的,我不要踩了。

因为我认为进出respace pop已经采完了对吧,我只给你提供你踩不到的地方的一个rap,这样的话我的recasting的这个起点可以往外推,这样变相呢也可以缩短我的距离,同时避免重复采样。

你看这个事情是不是很有道理好,那这个时候呢当然了,会有很多的artifact,这里面讲一个很有意思的artifact,就是说哎我毕竟啊,就是我从这个screen space设一跟ray出去啊。

你很难找到exactly,就是我即冲过worst space,那个那个那个那个点的,那个中心点的,这个这个,这个那个就是那个那个那个那个workspace prom,同时呢我又那个瑞呢。

我只能沿着那同样的方式去找,那这样就会产生一个很有意思的问题了,这个artifact这个ARTIFA就很有意思了,就是原作者提供的嘛,就是说哎我在screen space找了一个probe对吧。

然后呢他在worst space那个,因为我是跑出去去找的嘛,那world space的话呢,他很可能会跳过靠近我的一个阻挡物,我这个时候就会出现漏光的问题对吧,那怎么办呢。

哎这个rendering的万能的hack大法就来了,我们就让光线弯曲一下嘛,你看就是说我们做这个gaming啊,就rendering有一个很神奇的东西,就是我们有的时候呢其实是不是那么特别care的。

物理的完全的正确光线需要它拐弯的时候,它光线就给我改拐弯嘛,他的想法其实蛮简单的,就是说你求到我的那个最近的war space,那个那个采样的SFL那个编码,我可以找到你的焦点。

我用那个焦点和你的中心去找一根线,然后呢我用那根线的连线出去,其实光是转弯了,但是这个转弯的特点就是说避免了不正确的,这个就是说visibility的问题,但这个呢实际上啊我个人认为是一个hack了。

但没关系,但是但确实它能解决一部分的漏光的问题,但不是所有的问题,其实这个案例给的不是特别好,其实我本来想改一个这个图,这个案例会看得更清楚一点好。

那其实呢我们的worst space这样的一个problem呢,放在这了对吧,那大家仔细想想,就是每一帧我到底要更新多少,我SPM呢,哎这里面就有一个很有意思的细节了。

这个这个这个很很重要的一个实现的点,就是说其实刚才我讲了这么多的probe,但是在lumen至少我自己看下来他的shading,我们看下来shading是什么呢。

它还是用screen space prom,因为你只有这个screen space这些这些pixel是有用的,因为我去渲染它对吧,worthy prop只是帮助我去快速的去采集这些。

帮我这些在就贴近我物体表面的这些prop去,或许远处的光线,所以呢那我的word probe去采样的时候呢,如果这个这么大的空间是没有东西,而且也没有物体,也不在我的spring space里面的话。

其实那些地方的problem是不需要采样的,诶这这就很有意思了,所以呢他这个WORKO啊就是worfacet prop,它只有被screen space prop有差值需求,有什么叫有差值需求呢。

就是说我的那么多screen prom里面,它周围的八个spice pop它会标记为marked,那只有这些被Mark的worst space park,才有必要进行采样,所以它可以采集的那么高。

什么30 243 12对吧,也可以踩得很远,就是因为他不需要,那个刚才讲的是48×48乘48,再乘4×4,那么多的problem,每一次都要去更新,那个就是那么多的瑞,他其实不需要了。

第一个就是它只有Mark的worth space prop,需要被更新,第二件事情呢,唉刚才也讲到了,就是你不动的时候,如果场景没有变,光没有变,它也不需要更新,你看它这个地方是处理得还是很巧妙的。

那么这两个光接到一起的时候,你看到它就启动,比如像这张图里面,如果你只是用这个screen space的这个这个prop的话,他如果只有2米的话,你看到的结果大概是这个样子的。

但是呢如果你word space给它增加一下,你可以看到这个光看上去就准确的多了对吧,你看到这个结果就看起来更加符合我们retracing,真正一个想,我们这个就是GI真正想实现的效果对吧,OK好。

因为大家看到就是在没有这个,这个这个就是worst space prop的时候,它实际上这个光其实是很不正确的,是漏了很多东西,因为很多WZ它不对,但这个时候它的光就相当于正确一点,就是原作者给出来了。

那我们就假设他说的都是对的,好哎呀,我们已经三个小时了,很棒啊,看来我们今天要刷新记录了,lumen确实确实是个硬菜,真的是个大硬菜,OK好,我加油加油,继续大家讲完啊,我已经开始讲的有点耳鸣了。

OK好,那接下来最后一步呢,其实也是我们最后呃第四个face了,我忘了写face for了,你看这个这个这个确实这个写的太仓促了,那么其实就是说我要去shading了。

我要去把这个屏幕上每一个像素都要给它点亮,那我就用用什么呢,这里面有一个细节,就是说我要用screen space pro,所以刚才折腾了那么多东西对吧。

他最后呢他还是在每个screen space的prom里面,把这个光啊给收集好,真的这个真的很折腾,大家看看前面我用match card生生生成了那个car surface,对吧。

我还做了works lighting,大家还记得那个work lighting的东西吗,已经忘了,差不多对不对,好,这个时候我在进行screen space,这个这个probe reciprom呢。

我还要对它进行这个adaptive sampling对吧,然后呢我发现这光采样的距离不够,我还得在这worst way再给它加一个pro,把它光给它接上,然后我还得要进行filtering。

还进行important sample,搞来搞去,搞到最后诶,我最后还是在屏幕空间生成了无数的,密密麻麻的screen space pro,好,这个时候我们呢怎么办。

哎呀伟大的super homex就起作用了,因为虽然我做了important sample,但是呢是实际上如果对intro lighting,我假设真的用它一个方向采集的光啊,他那个光啊还是很不稳定。

还是有很多的JER,那怎么办,我们就把这些光全部投影到S上面去,其实S本质上是什么呢,相当于对我们的整个这个intro lighting光啊,进行了一个低通滤波,把它变成了一个低频信号,那你啥也不干。

你把这个光投影到SH之后,哎这个property它就引用它来做shading的时候,它这个样子看上去就柔和了非常多,那么那这就是我们最终那个设定的这样的结果,看上去就很漂亮了对吧。

当然大家知道如果听懂我前面讲的东西,就知道这张图是不正确的,为什么呢,这张图上面那个prop的采样是uniform的,对不对,我们刚才讲adaptive,下面还有很多小的那个就是8×8的。

4×4的东西挂在下面,但没关系,这不重要,这是细节,最后你能看到这么漂亮的一个结果,那么总体来讲呢,lumen是一个非常复杂的系统,其实今天我讲了讲这么多啊,讲了快三个小时。

lumen本身讲了快两个小时,实际上它还是有很多细节我没有展开,因为他真的是个非常工程实战的一个方法,也就是我为什么在前面花了那么多时间去讲,那个去lumen的那个那其他的GI算法。

因为它真的是这些GI思想的集大成者,包括我还怎么备课,紧张了,我还把dd g r给秒掉了,本来我还给忘掉了,我还想讲一点那个哈very retracing的东西,后来想想算了,来不及了。

我们就全部扔到二零系列的课程吧,我们就一零系列先讲到这儿,那简单回到lumen本身的话,就是这个OVERWORLD,我们去讲一下,就是说实际上呢他是利用了一个核心思想。

就是对于不同的retracing啊,其实在硬件上它的成本是不一样的,其实最快最快的就是基于global s t f对吧,那其次呢就是在屏幕空间,我进行linear的step去插值。

那么比他稍微慢一点的就是match sdf,就PROMASHSDF差距那个retracing,但是呢这里面有个前提条件,就是说你这个跨的步骤不要太大,不要一下子involve太多的mesh进了。

如果你太多的mesh的话,它速度其实是非常慢的,那么high zb呢它其实这个respace retreating呢,它稍微比这个linear的step要慢一点,但是呢它的这个cos要高一点。

但是呢它的准确度其实会更高,他比那个neon step更高,那么hardware retreating的准确度肯定是最高的,但是呢他的cost就比较大了对吧。

那么就是hardware的这个基于的surface cash,我也可以进行hardware tracing对吧,当然我讲过就surface cast,它本质上是IMPOSTER对吧。

但是呢它的成本也很高,这张图也是原作者给出来,就是他你可以看到他在工,因为他要解决一个非常难的一个工程问题,就是说在一个实战的游戏里面,真的把这套GI算法变成一个real time。

而且能处理很多的动态光源,这种复杂的情况,以及包括刚才我讲的,我个人觉得非常巧妙的就是那个surface cash的方法,因为我以前特别难以解决的一些,比如说自发光的物体怎么去照亮环境这件事情。

他好像就自然而然就把这问题给解决掉了,好,那么其实呢,这里面这就引入了一个大名鼎鼎的一个图,就是说诶lumen到底是个什么算法,有人就说包括我自己以前也黑黑他,我说lumen他就是几个算法的缝合怪对吧。

那为什么大家会说这句话呢,实际上就受这张图的影响,只是官方给出来的说诶我在每一个SQUEEPROM,我到底是怎么获得他的这个IRRADIANCE的,就是他的radiance的那红色区域就是什么呢。

我是用screen space的垂线的方法获得了非常快,那么绿色的区域是什么呢,我是用mesh的方法取得的对吧,blue呢就是哎我我mesh df,如果蓝色的话呢,它就是在这个就是说更远的。

我只能用GLOBSDF去的,其实这个地方讲起来就很糙了,但实际上大家仔细看,如果每一个pixel,他的那个就是那个他做那个prop train的方法,是单一的话,我们应该看到什么样的一张图。

是不是应该三个颜色的图,但现在我们看到的图是什么呢,是个渐变图对吧,所以我大胆猜测一下,就是说对于每一个RECIPROP,我要踩这个八乘八六十四个方向,那么这64个方向里面有多少个方向。

我是用screen space trace多少,我用math df的trees多少方向,我用这个global df trace,其实呢在这里面是有一个权重的,所以我们可以看到这样一个渐变的东西对吧。

那更具体的详细的去讲啊,就是说其实lumen的核心,我觉得有个核心的点是怎么快速的做tracing,那么它这里面就讲的就是说,第一他首先的话是用scratch screen space trace。

我如果呢它基于high zb去trace,最多50步,如果能trace得到,那很好,我就把这个结果拿过来对吧,如果screen space trace我拿不到怎么办,我用mesh sd f trace。

那match stef trace的话呢,我其实你可以发现它trace的距离非常近,只有1。8米对吧,他这原我们是在这个代码中翻去看的,然后呢,就是而且呢它只在,就是说这个位置在我相机的40米之内。

我才会用mesh staff,那这个时候呢我可以返回更详细的数据,就mesh id啊,这个hit word position啊,normal啊对吧,我可以直接把他送到我的final。

我去sample in他的final好,因为我有那个surface cash,对不对,那如果再远一点,比如说200,这个就更远的距离的话,我一次性这假设前两个条件都不满足,要么你推线的距离太远了。

我特么1。8米配的东西,或者说我的这个position就是我70的position,超过了40米怎么办,我就一股脑设20米的阴影,瑞我走我我用的是什么呢,我只用global s t f。

但是呢GLOBTF我能拿过来东西什么呢,只有walker lighting,所以works lighting其实非常的重要,对于我们的整个lumen的这个广场的采集,因为你可以理解成就是problem。

是我采集的结果,但是我采集的源头,下面是我的surface cs和我的works来,下次我有更多的学习准备的时候,我可以把这个图画的更清楚一点啊,否则的话这些概念是特别特别容易混淆的。

然后呢这里面再补充一条,就是原原作我没有讲的,就是说如果我的global sdf这个tracing对吧,re retracing也失败了,怎么办,诶其实人家还有一招,你就踩到天球上去。

铅球我们就sky sky box上面,你天球反正是无数无数无穷远,对不对,我采来的就是天光哎,这个hack其实非常有道理的,因为大家想想看,就是说对真实的场景表达的时候,我对上市的很多problem。

天上有蓝天白云啊,这些东西鱼可能云还在动啊,那其实它对于我表面的光照,其实影响还是蛮大的,天光其实很多时候是很亮很亮的,所以我觉得这个其实不是hack,如果我们在写lumen的时候把这一趴少写的话。

我个人觉得对效果应该会影响特别大吧,OK所以这就是一个整个lumen他的这个tracing呢,它整个结果,所以这样的话大家就能理解那张图,它到底在讲什么好。

那其实这里面呢我要特别想high一下SCI对吧,SJS这个怎么说呢,听上去是一个hack screen space对吧,但是呢其实lumen他SDI在lumen中还是蛮重要的,这也是那个官方给的一张图。

就是说如果我只有龙门,我看到的结果是这样,大家可以看到下面那个倒影看着很粗糙对吧,但是对于高频的,对于近出的这些东西的话,其实s gr还是蛮重要,大家仔细比较一下这两个字的区别对吧。

所以所以说呢我要小哦,假设有人想黑鲁班书啊,你下面用的就是SC,这个黑的就是既对也错对吧错,肯定lumen本身很复杂很丰富,但是呢,lumen确实离了SCI的一些基础思想的话,确实也很难work。

所以我一直认为就是lumen这个方法很了不起,他是过去这十几年吧,我们对real time gi的研究之后,一个集大成者,也是第一个真正把GI哦,应该不能叫第一个。

其实以前有一个我记得有个中间的叫什么lighten,他也尝试把dynamic gi变成软碳的,但是呢这个这个这个公司,好像现在据说是不在了,没关系,大家会前赴后继。

那么我们去做这样的一个real time gi,的这样的一个方法,OK那么其实lumen呢他最了不起的地方,我觉得还是在工程上,他真的完成了交付,也就是在PS5的这个硬件平台上。

大家知道PS5它的GPU还是很强的,但CPU其实一般吧,GPU其实也跟现在的这个显卡来讲,还是有一些差距,但是它能做到3。74ms就做完了对吧,而且呢如果你愿意把这个屏幕的。

比如screen space那个light problem,Worst beat problem,分辨率在下降那个四倍对吧,但你其实你的效率可以更高,就是可以从将近四秒3。74ms啊,下降到2。

15ms,刚才讲错了,不是秒,是毫秒,秒就完蛋了,哈哈秒的就是offline的那个计算了,那么当然了,这里面你去SACRIFED,你去损失掉的是什么呢,哎就是精度,那这里面你可以看到。

就是这个里面的话是相对比较low,resolution的,这样的一个就是screeneprom or swift prom,你看到这样的一句,这个结果去看上去已经非常非常amazing了,真的。

但是呢如果你用他的FORESOLUTION的时候,你可以看到更多的这种光照的细节,所以其实1616的这个pixel的这个选择,我相信这个作者自己肯定也做了大量的尝试,也就是8×8肯定试过了。

32×32肯定也试过了,这可能是他们最后觉得是一个,大家最能接受的东西,而且这个东西我猜呢可能和他们在UU5里面,和这个就是NI的这种复杂的场景,这个密度去进行了一个配合。

他们选择了一个最好的这样的一个适配哇,我们已经讲到了哇,我的天呐,讲到了11点了,同志们真的要陪我翻页了吗,好OK那这是他lumen的一些结果了,这边说实话,这个结果我个人觉得还是非常的了不起。

就是它基本上就是过去一些offline的这个,这个这个retracing的这个render的结果,其实就是我们很多比如说室内设计师,效果图公司啊,所梦寐以求的一些效果啊,金一天的话随着硬件的发展。

随着算法的发展,我们几乎可以实时的产生这个结果,这个其实对整个电影行业,对于过去那些离线渲染行业的冲击的话,还是包括动画电影行业吧,我学的都是一个巨大的影响,也非常有非常巨大的影响对吧。

这也是奠定了未来10年,我们下一代的游戏引擎的渲染了一个基础标杆,也就是我们认为GI应该是下一代,顶级引擎的标配,就是你只要做下一代引擎的,你的基必须是摇弹的,而且这个呢我认为lumen呢。

其实只是这一系列伟大征程的开始,真的这是我个人的感受,就是说你可以看到lumen还是做了大量的妥协,也是基于这一代的硬件,在未来10年随着硬件的发展的话,real time gi的话将会变得更加的成熟。

可能会变得更加的简洁,所以我认为lumen是这个方面的开山鼻祖,就奠定了这件事情,所以我觉得他的创作者的话必然会载入史册,而这是我个人作为一个程序员吧,我觉得还是要这个奉上我的这个这个双膝。

就是表达这种敬佩,这工作做的非常的了不起,OK好,那最后啊今天时间非常的仓促,所以我根本就没有时间去写总结,那最后呢想到了用一张图去表达我的心情,那又把我们的祖师爷卡基亚给举出来了,就这张图。

大家记得我们在那个rendering的第一节课,用了这张图,所以说其实啊我们整个rendering体系,我们在解决的就是这个问题,就是怎么样的把卡提亚的这个方程real ta算出来。

其实这里面lumen只解决了GI吗,比如像TRANSLUENCY啊,像那个fur啊,像透明物啊这些东西的渲染对吧,其实还是很复杂的,所以这其实也是未来我们的,就是游戏引擎的一个征程对吧。

所以说对于高级的游戏引擎技术,其实,所以大家如果真的想立志进入游戏引擎行业,我觉得大家一定要做好就是啃硬骨头的准备,千万不要认为游戏引擎是一个哎人人都可以,哎呀,我这句话说的是不是打自己的脸。

我说人手一个自研引擎,那今天我要讲另外一句话,就是游戏引擎其实深度非常的深,他真的是计算机科学的最前沿的东西,就是有很多很复杂的技术,所以的话呢就是我们要有敬畏之心,对这种前沿的技术好。

那接下来呢就是我们这节课的reference,课程组的小伙伴们还是花了很多时间,但在这节课我们真的是特别特别的干,真是爆肝啊,就就好多次开会开到晚上11:12点,就大家一个算法。

一个算法的撤开一个一个就是因为很怕讲错,虽然我一上来先挂了个免死金牌,如果讲错了,大家千万不要打我,但是呢我们在准备的时候还是态度端正的,就尽量避免讲错,所以我们还是花了很多时间,去研究这些相关的东西。

这里面有些东西我今天没来得及,比如像DDGI对吧,其实大家有机会可以真的去研究一下这些东西,包括像SDFDDGI对这些东西,然后呢解压的话有一系列的东西,包括像hardware tracing。

有些东西大家都可以看一看,大家也可以想想,就是有HARBTRACING之后,那lumen这样的框架怎么去优化,其实他们原作者也做了一些,有团队还是花了很多时间去做了很多工作。

我们我真的再次感谢我们的课程组的努力,然后呢我其实是一个工具人对吧,我负责把这些知识表达出来,剩下的东西啊都是我们课程组小伙伴,他们真的在过去的,可以说是一个多月里面非常的辛苦。

因为lumen的这套体系非常的复杂,然后在课程的最后阶段呢,我们又提高了要求,就希望能够把GI的整个体系给讲清楚,所以大家又去展开了做了很多的研究工作,那我们也争取奉上了。

这个我们能拿出来最好的一个讲GI,讲lumen的这样的一个课程,希望同学们能够接受和喜欢好,那接下来同学们有什么问题问我们对,第一同学问我的第一个问题,就是说硬件光追发展的这么快。

但是lumen还是做了一整套基于SDF的这个软件,光追对吧,那就是说在未来的这个引擎里面,软件光追和硬件光追是不是都是必须的啊,这个问题实话实说啊,也是我最近思考的很多的一个问题。

因为harry tracing呢其实从NVIDIA在猛推这个东西嘛,实际上我们都看到他的potential,比如说我们现在是三零系列显卡,马上我们将面对四零系列显卡,据说四零系列显卡。

他的那个real time retracing的能力又会加强很多,但是呢就是我们真的实测下来呢,就觉得hodor retracing,它本身的这个能力还是没有达到,就是我们的需求。

因为其实我我上次我现在讲三零系列显卡,我们测了一下,大概是啊十个billion,就是100亿的retreat recasting profit啊,per per second1秒。

那这个呢作为这个GI来讲的话,其实还是不够,尤其是你说一次半次两次半次对吧,但是呢其实就是lumen自己的作者,他们现在也在尝试,就是说如果你有harder这个retracing的话。

我可不可以用harder retracing取代掉部分的,比如说基于距离场的这样的一个retracing,那这个方向呢我个人觉得还是非常值得尝试的,但这件事情的话呢,我个人觉得蛮挑战。

因为lumen本身是一个很复杂的系统,他最后能work啊,其实他每个参数都是很精细的,调校过的,包括lumen,如果大家真的去玩它,你会发现他还是有很多broken case。

就是我们最近我本来那个来不及了,否则我给大家展示一下,我们最近自己用虚幻五搭了很多case,我们就看在这种场景下,不但是这个绝对不是黑龙吗,恰恰相反,我们很清楚你做这样的一个real time。

接下算法的话,其实你很多时候很难做到,就是说面面俱到,那反过来讲,就是说现在我自己认为比较大的一个不确定性,就是说hardware retracing这件事情到底能走多久,因为大家知道现在的显卡。

它本身已经做得非常大了,功耗已经很高了对吧,我们已经基本上hit到了摩尔定律的一个,一个一个边界了,在未来的比如说5年或者10年,hardware tracing可能它的性能会增加一个数量级。

那他可能对于GI这个问题的话呢,并没有本质的去改变,那么另外一个就是在很多场景下,比如在游戏主机,它的硬件换代速度会比较慢,比如在移动端对吧,它的硬件换会更慢,那这个时候我们怎么去做一个积压的方案。

所以我个人觉得就是啊,lumen的局距离场的这种reaction的话,很可能还是目前我们找到一个比较好的一个,software retring的一个方案,对,这是我目前我对这个问题。

我保持的是一个open minded,就是还是开放的一个状态啊,对这个同学问的问题就是直击灵魂,他说lumen的效果非常的好,但是呢听完我们的课,就发现这个系统非常的复杂。

那是不是那个就是我们要就是是不是很难维护,对吧,那我们要不要开发这样一个类似的系统,那这个问题其实是一个直击灵魂的一个问题啊,就是啊lumen是一个非常非常复杂的一个系统。

所以我觉得呢大家确实可以认真思考一下,对于你自己的case对吧,你是不是实现它的部分的算法,实现它部分的效果,比如说我在B站上,看到很多小伙伴会发一个视频,说哎我自己实现了lumen的效果对吧。

然后做的很漂亮,但确实是就是说,如果你不要达到那么高的工程级的需求的话呢,你可以取他部分的算法,也能产生非常好的效果,但是你把它全套的算法全部实现一遍的话,这个对你的编程功底,数学功底。

包括系统功底要求确实是挺高的,而且呢刚才同学问的那个问题,提到那个点,就是说他是不是好维护,我个人觉得也是lumen,接下来面临的一个非常大的一个挑战,就是说因为我们在做游戏的时候。

就知道游戏引擎它所面临的场景是极度复杂的,举个例子,比如说刚才我随便提了一个东西,比如对于地形terrain,你没有办法生成mash card对吧,你没有办法生成Mac mashcard。

你就不能够直接把它放到那个那个surface cash,里面去,那这个时候他怎么去进行这个采样,那么第二个问题呢,比如说像中间我刚才讲的有些气体,participate media对吧。

就比如中间有一团雾出来了,对不对,那他的鲁门怎么,它的光照怎么去处理,那还有呢对于就比如说非常动得非常快的场景,这里面很多东西都在动对吧,那这个时候因为他动的速度非常快嘛。

比如说我要做一个像sonic这样的游戏对吧,大家跑的非常的快,那lumen能不能work,所以这些东西呢,我个人觉得都会是一个实战化的,lumen系统的一个很大的挑战,我们也非常期待能看到几U5的。

有lumen全态效果,这样游戏出来,这里面的话,也能对这些问题给我们提供一些参考,我的预测就是说啊今年明年吧,GDC上应该有一系列的实战的游戏,产品的文章会讲到,就是说在自己的产品中。

我用lumen这个技术,我需要做哪些调整和优化,才能实现一个真正的sheep wall的,这样的积压的效果,就是sheep就是什么呢,可以发售了的一个解压效果。

因为今天lumen的demo to be honest,他还是个技术代码,它还没有变成一个商业级的产品啊,第三个问题就是很有意思,他问我说,实时动态GI,会不会成为下一代这个3A游戏的标配。

那我个人的观点是yes,是的,因为人眼就是这样的,你一旦被training好了,一旦习惯了那个东西的时候,你是非常不习惯那个东西是没有的,那么就是GI这个东西呢。

它on hand off其实直接就定义了,你是一个就是就是像古老的这种塑料化的,这种渲染的感觉,和一个你感觉很实景化的感觉,就像刚才我展示的那个几个,就是那个室内仿真的那个效果嘛。

那个效果的话呢如果再去调一下,它已经非常逼近于你用相机拍出来的效果,那么一旦人接受的说哦,游戏就应该是这样的话,那大家其实可能很难接受这个东西没有的情况,包括我也看到有些人很有意思,就是用GI的效果。

再加上那个就是NP2就是什么呢,就是卡通化的渲染,它也能产生一个以前的那个卡通化渲染,不能产生的效果,所以我个人认为就是说啊虽然它非常的难,非常的复杂,但是的话呢可能未来五到10年游戏的主流。

可能就是这个方向,因为硬件的算力啊也会逐渐的增加,所以这里面的话呢也会给我们提供更大的空间,所以啊其实说实话,我并不认为,lumen今天算彻底完全解决了积压的问题。

但是呢它确实是在整个游戏GI的这个历史上,迈出了我觉得是关键性的里程碑性的一步,好的那今天的话哇,将近三个多小时我没有刷新的新的记录,怎么样,同学们对我们这一节课的内容还满意不满意。

那我希望我们的肝对吧,中秋节都没有休息,我今天是我压力最大的省份,今天下午都快已经爆掉了,你知道吗,我准备课的时候其实非常暴躁的,因为每个细节我都会扣,那anyway。

就是说啊希望同学们还满意我们的这个结果,然后呢最后再跟大家预告一下,我们啊明天会有我们的50万播放的彩蛋出来,也跟大家嗯轻松一下,换个换个脑子,另外一个的话呢,下节课两周之后,我们给大家讲NNIGHT。

那又是一场硬仗了,真的是一场硬仗啊,希望同学们哎呀,我得吃点补品吧,然后那个然后呢,我们104的课程就第一趴就算全部结束了,希望同学们也会喜欢我们这个课程,然后后面的话呢。

我们有更多的精力可以跟在皮克罗上,包括在更多的一些内容专题上,给大家提供我们的帮助,也很希望就是呃怎么说呢,能够把我们中国所有热爱引擎开发的同学,聚集起来,我们一起做一些有意思的事情。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好谢谢大家好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

21.时域调制 (IV) | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1KM41117Ss

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

好诶,时间差不多了,今天就正式步入到我们这个食欲调至四哈,这个已经我们呃讲了四节课了,这个内容还是非常多哈非常多,今天就给大家来到了进阶光成像的一个第二节,这有点卡,上节课我们讲到了嗯。

这个基本的一个就是间接光调制。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成像的一种基本原理,就包括我们从像素结构,然后套是两个像素,并之间是怎么调制诶,包括我们遇到了有多少个变量啊,啊比如说我们左右两边的增益不一样,我们需要多少个测量来去解决这么多未知量啊,包括一些偏置啊。

一些啊resist no reset电压的问题,我们需要最后我们发现我们可以用四相位方法,用四次测量唉,来解决这么多未知量的一个问题,从而构建了我们经典的一个啊。

这个arc tan来去解相位的这么一个公式,当然到了最后,我们还是遇到了一些比较头疼的问题啊,比如说像我们这个多路径,因为这个相位啊,它不是那种我们直接光测量的一个pose,像我们像直接光啊。

直接光成像的啊,可能是我声音比较小哈,这个我现在喉咙不是很舒服呃,直接光成像它本身它是一个脉冲啊,就是我们回回回过来的一个波,本身虽然说还是有这种各种脉冲的叠加,也就是他after pose。

就是他那个后面的一个道路径的叠加,但是对直接光成像而言,我只需要检测它第一个相位的一个位置,我就可以解决多路径的问题,但是间接光成像呢它就很头疼,他就很头疼,因为我们测到的是相位,它多次反射的光诶。

它是经过一个correlation,它是一个混合的过程,也就是一个由多到一的一个映射,所以说呢我们这个问题就会变得非常头疼,我们这一个东西会有非常多的解,然后我们会这个多路径问题就会变得非常困难。

所以说人们提出了一个用两个呃,频率比较近似的一个高频的做一个调制,然后形成一个波包啊,形成一个波包,这样的话高频本身我们知道上节课学到了facer,image,频率达到了一定程度之后。

我们这个它的整个pser,就可以在一个360度的一个,实际上我最后所呈到的一个嗯就是传感器上,就是我们计算经过计算,它最后就会平均掉在这个360度上,平均掉,我们就会这个登陆进去变成一个offset。

频率足够高的话,我这个动力性效应它自然而然的就会消失,但是呢我们知道这个器件自个儿它不太可能去,就很轻松的达到一个非常高频的信号,所以说我们通常是用两个比较高频的一个信号,比如说两个100多兆啊。

这个时候可以实现的诶,两个信号稍微有一点点的一个频率差,这样的话就会形成一个包包啊,通过包包的形式啊,来一定的程度缓解这个啊多路径的问题,像今天这个第一部分啊,我们会啊讲一讲。

继续上节课的一个micro micro的一个imagine,去讲一讲这个director和direct一个分离的问题,然后呢啊我们会发现这个在食欲调制上,就我们这个encoding function。

就是我们这,因为这样是不是就好了,微微,诶好了,我们继续好,我们从这一页从头开始哈,就我们遇到一个scattering medium,就刚才啊像我们遇到了那种,比如说像雨,像雾啊,大雾呀或者是灰尘天气。

这种是非常头疼的,而且这种同样的一个问题,更严重的是我们在水下,我们想做这个水下time of flat image的时候,就会变得非常困难,就理想的情况下,我们这个一个光源打出光。

然后经过我们这个场景的一次反射,直接被这个深色捕捉到,所以说呢与之对应的,我们这有一个直接的一个radiance,就是我们sense上捕捉到这个radiance。

但是呢经过我们这个scatter medium,就是我们这种散射型的一个介质啊,我们这个光源发出来这个光,它不再是直接被这个物体反射,它可能会被前面的一个呃就是散射体啊,首先经过反射。

经过散射体的反射进入到传感器,这个问题是非常头疼哈,像我们之前的多路径,我们知道我们多次反射,始终是在我们这个multipath的后面啊,我们multipath始终在这个直接反射的后面。

但是你有了这种这种这种散射体呢,它可能会反射的波,可能会在你这个真实的信号的前面,这个时候你就不知道我到底哪个信号是好的,是坏的,这就变成就,你要是想通过这个直接就是先验知识在家,那就不灵了不灵了哈。

最后我们在传感器上拿到了一个信号,就是唉经过这个散射体反射,跟你原本信号的一个啊乱七八糟的叠加哈,你这个很难受的,这个我们最后就拿到了一个face error,这个face可能是偏甜的,也可能是偏厚的。

这种就就非常头疼,这怎么办呢,我们理想的情况下,唉我们知道理想的情况下,它它的ground truth是一个,就是它是一个深度图,深度图就会一个平面就会变成一个弧,因为是我们从一个点。

连到一个各个平面的一个距离,受到这种scattering medium的一个影响,我们知道他的项目提前了,也就是我的一个error就比之前小了,就是相位提前了嘛,这个时候我们整体的一个测量值就偏小。

就是蓝色的,是我们就是不管没有没有校正过的一个测量值,同样的我们还是用这种双屏的一个原理,用两个高频,两个高频,然后通过两个高频的一个correlation,形成一个包包。

这样的话我们本身的调制频率是非常高的,我们在这两个高频下,我们有可以去分解这个深度上面的,一个小的一个immigrity,这样的话就可以在一个啊,相当于一个比较高频的一个测量下,来实现。

我们对这个这种散射体的一个道,路径的一个校正,本身呢,我们要实现这个直接光和间接光的一个分离,我们发现这个就direct radiance,跟着director radiance,哎。

我们发现我们最后我们的实际测量,是一个直接加上一个整体的一个偏置,我们把这个啊直接信号它的一个赋值啊,赋值就也就是它的整个分封值的一半来,即为amplitude,整体的呢呃到这个峰值的中心呢。

我们把它记为offset,解为o实际上我们最后想要计算的一个值,就是直接关了一个峰,峰值,就是两倍的一个amplitude,然后它的一个整体的偏执呢,就global的偏执。

就是一个o减上a这么一个很小的一个值号,当然我们发现我们要解这么一个,把这个直接光和间接光这个量解出来,我们需要三次测量,三次测量来把这个量具体的算出来。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看一看啊,来怎么样实现来这个direct direct的一个分离哈,我们左边这个是一个渲染一个康奈尔box,它是一个直接,就是我们直接一个点连到那个连连线,它的一个深度,然后右边呢。

实际上就是我们一个间接的一个分量,间接的一个分量,这个间接的分量它是嗯在多路径的问题里面,就是多次多次反射在这种chedule medium,就是因为我们这个散射体的一个,提前的一个散射哈,这里面啊。

就我们把这个相当于多路径,跟这个这种scatter medium统一了,实际上它都是对相位的一个干扰,只不过是前向干扰和后项干扰,它本身都是一种多路径的效应哈,这种多路径的问题。

在这种拍这种我们把这个问题统一之后。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们就可以啊,用这种micro的一个image的一种方式,两两个高频,但是有一点点的一个频率差,来去统一的解决这个问题,比如说我们在拍一个墙面的问题哈,就是两个墙之间有一个锐角,有一锐角。

我们我们理想情况下,也就是我们这个direct component,就是理想的一个深度的一个位置,它就是理想的一个这么一个角,但是呢我们经过这种就多次反射呀,或者是一个偏执的一些问题。

它就会有一个global的一个分量,这是当时啊他们做的一个原型啊。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是这个,这这个实际上是我们组的一个变形计哈,这个这个这个东西在我们组那时候,这是一个p m d的一个camera board,就是最早的像德国那个psmixer device。

后来可能是被那个英飞凌收购了,这个是可以搞到125Hz,当时是用了两个啊,接近125Hz,20 125兆赫兹哈,125兆赫兹的两个比较高的一个频率,两个比较接近的高手频率来实现这个marko的。

这么这个image当然我们要验证的验证,一般哈大家验证这种多路径啊,或者是呃这种多次反射的这种问题的时候,大家都会用一个这种叫v字型的一个墙角哈,实际上只是两个板哈来做一个啊。

仿真和实验的就是两种方式的验证,就有一个墙,我们把这个固定住,另一个墙是可以移动的,然后中间我们选择一个固定的一个角度,然后呢我们把这个就是传感器哈,把这个相机一般是放到5米左右的一个位置。

也可以3米5米,这个就看你的这个调制频率了,这个尽量不要产生挖平这种问题,比如说你100兆的时候啊,它的一个挖平距离就是1。5米,那60兆呢啊实际上就是2。5米,当然你也可以降了十兆,大家可以类推。

就是呃15米哈,对不对,然后这个时候呢,简单地考虑这个就是多路径的一个问题,哎我们发现这个锐角理论上它测量哈,我也可以看到这45度的一个锐角,60度的一个锐角,还有90度的一个直角。

我们拍摄出来了这个这个深度图啊,它是有一个严重的变形的,好严重的变形,大家也可以可以很清晰的从这个图里面看到,他这个到底是怎么变形的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是呢我们用两个比较高频,然后有一个但是有一点点频率差,去拍这个来解决这个ambiguity的问题的时候,就可以比较好的比较好的恢复出来,他这个正确的角度,我们可以看到理想的情况下,这个45度。

它就是实际上就是一个理想的一个角哈。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是呢你只考虑一个单屏的啊,单屏的一个传统的一个time of flight,它的一个mi error就可以达到86mm哈,86mm就是8cm多,我这一个偏了一个8cm多哦,好家伙,这个有点大。

大概10%的误差了哈,但是呢,当我们用这种mo就mo time of flight,它那个mierror可以降到2。8mm,就非常接近光荣柱子了,就比它一种普通的一个单品的一个top,可以提高啊。

三四十倍的一个进度程度啊,这个就是解决了一个多路径问题的一个影响,当然也不是完美解决哈,就我们最后发现这个还不是很完美,这个也不是很完美,所以后来呃哪怕到了今天,这个多路径依然是这个研究的一个热点问题。

大家可以看到这60度的一个呃角。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拍摄出来的一个情况,60度的时候哎。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个偏差也是不小哈,像传统的就是达到了7cm,90度也到了5。6cm,就是mo time of flight,就这个思路就很好啊,我们用了这两个高频来去呃,相互correlation。

然后形成一个播报诶,这个时候就可以形成一个有效的一个深度的,一个辨别能力,大家可以看一下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们记录到了这个形状,跟我们啊最后频率的一个关系,这频率不断升高,升高升高,它的精度也会变得越来越高,啊这个是实拍的一些效果,实拍的一些效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个就实现了一个啊director跟global的一个分离,就是我们这个director,就是我们最后想要的一个啊,真实的一个就是深度的一个值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来我们总结一下我们前面啊这种time of flight,遇到了一个问题啊,这这这种呃indirect illnation,经常是受到这种多路径啊,scattering medium一些影响。

它影响都是比较消极的哈,但是呢我们解决的方案是什么呢,就是用一个两个比较高频的一个信号,但是这两个高频的频率比较接近,我们用这两个频率的测量,来去抵消我们这个道路径的一个。

还有这种scattery medium的一个影响,但是呢我们这个测量频率要到了多高,才能说真正的实现我们这种精细的测量呢,就我们本身的一个测量范围,从我们的一个比如汽车或者是一些啊卫星啊。

或者是飞机上的一些雷达的使用,可以到公里级啊,然后到这起车载几十米呀,到我们就是日常生活啊,厘米级分米级啊,到我们最后比如说呃生产线上,我们要做到一个啊毫米级甚至亚毫米级。

就是几就是几百微的这么一个精确测量,那从我们这个就是测量本身那个频率,就是呃效果来看,就我们不一样的这种测量范围,它对这个我们深度测量的一个表面,平整度的要求也不一样,比如说啊要到了一个米量级哈。

就是千米量级,我们通常就是就是几几赫兹啊,或者是几百赫,几k赫兹,我们不断不断的变得清晰,我们需要更高的频率来去实现这些精细的测量,包括到啊就是g赫兹呀,甚至是到太赫兹。

来实现这个毫米微米级的一个三维测量,就我们比较经典的一些器件啊,比如说像这种pmb的一个camera neo哎,这个时候就是可以实现一个厘米级的一个,三维精度的一个测量,然后呢这个也有g赫兹的一个d哈。

这是啊以前做通信用的哈,以前做通信用的一般哈,这个成像啊都是跟着通信后边哈的,通信有了刚需,把这些器件搞出来之后啊,大家搞成像的时候就发现诶这期限挺好,调制频率挺高,我们可以用一下。

其实呢本身现在还有很多太赫兹成像,太赫兹成像的技术可能太多了,就不再给大家详细的讲这些太赫兹的技术了,我们总结一下前面的一个啊time fly的成像,包括我们讲到了facer与美景。

我们可以通过这个facer就发现诶,我们可以描述我们这个向角的变化,可以描述这个向角的它的一个角度变化,跟一个幅值变化,就可以非常清晰地描述,我们这个整个三维图像的过程。

本身这个facer它自身的一个抖动,也就是我们这种深度误差的来源,我们就可以把这一个箭头换成,换成一个小小的这样一个包啊,但是我们这个包是可以通过提升频率,把这一个相位的误差来到了足够高的一个频率。

情况下,就变成一个global offset了,然后呢我们就讲到了一个generalize的一个continuous,wave的一个time flies,它会受到这种自身的一个多路径的一个影响啊。

或者是受到一个啊这种散射体的一个影响,就会产生这种非直接光的成像的,一些不好的干扰哈,当然我们讲到了这种不好的干扰,可以用这种micro display,也就是两种高频,但是频率相近的去解决这个问题。

最后来恢复我们这个direct的这种测量,也就是我们想要的一个理想的一个shape,当然我们也可以一些分析一些,这个光传播的一些效应哈,这些是大家这前面的这有问题吗,像没有问题的话,第二部分。

那我们像之前我们做这个就直接光的一个,间接光的一个调制成像啊,我通常可能模型比较简单,大家只是用一个单屏的一个这种方波啊,或者是一个呃正弦波来进行发射跟解调,但是这种我们真正的说我们这种。

大家可以想一下哈,这个方波跟这个正弦波哪个好一些,从大家的感觉上来说,就方波跟正弦波哪个好,就是咱在这个进入正式进入到呃,这个optimal encoding这个问题上,咱先说一下两种强常见的方式。

就同学们觉得哪一种会更好一些,放波好还是正弦波好,大家有没有这种可以先抛抛出来这个问题啊,到底是方波好呢还是正弦波好呢,哪一个我更鲁棒,我的深度精度更高,咱先不谈实现的问题。

因为我们最后这个激光管发射出去之后,他那个波形肯定是会变形的,它又不是方波,也不是正弦波,也就是遇到了,我们之前讲到了一个这种非线性的问题,但是他理想考虑理想一点哈,那就是方波,理想的方波和正弦波。

每一个对我的一个系统有更加积极的影响呢,同学们可以说一说,发表自己的观点,这我先不说哈,我先不说,然后给大家就是先回顾一下哈,我们通过这种相位的一个偏移,然后再做一个correlation。

来进行这个深度测量的时候,我们之前讲到过,我们需要三次测量来解决这三个未知量,我们有三次相关啊,r one拿到了一个相关值,也就是我们这个发射区的一个一个光波。

跟这个接收出来的光波做一个correlation,然后呢我们要通过这三次测量,这三次测量,一般我们可能会用四次冗余性来解决,这个解出来这个相位,那我们直接就把这个相位来解出来,这是我们想要的一个深度呃。

放这同学说方博哈,这个kph mt同学说方博呃,方波确实是比这个正弦波好一些哈,但是确实不是因为这个方波频谱宽,而带来的积极影响,这个咱先把问题留着,让大家继续看。

这个到底是怎么样带来这个积极的一个影响,本身呢我们也知道了,我们这个近极光成像,它会有一个比较高的一个信噪比,同时也可以实现一个实时的捕捉,但是呢我们从这个正弦波出发哈,我们这个调制方程跟这个解调方程。

理想的情况下,咱们也没有理想的两个正弦波,他们两个做相关的时候,我们实际上是拿到了一个,就是标准的正弦波对吧,但实际测量呢我们可能会有一些相位的偏移,这个时候我们还是比较理想啊。

只是只考虑有一个相位的移动,也是我们最后拿到了一个coration的一个方程,实际上也就是简简单单的一个相位移动啊,同理哈,再一次测量也是这么个情况,我们最后解散出来的这个相位的偏移。

就是我的一个深度上的一个变化,啊这个rpsi说方波新型信噪比高,嗯这个也不是因为这个为什么性价比高呢,这个同学可以解释一下吗,为啥这个方波的信噪比会高一些,确实会高一些。

我们做这个相位解调相位到深度的一个变化啊,实际上我们是建立了我们整个的一个测量到的,相位到一个深度的一个映射,我们现在比如说有三个颜色,也就是212223,这三个就是口音相关的一个值。

我们是通过这三个一个相关的值,来建立到我们对深度的一个映射表是吧,也就是说我们每一个深度的一上面的一个点,每一个深度哈,每一个深度都有它有三个相关的一个值,r1 r2 r3 。

也就是我们就是传感器上测量的值诶,不一样的深度,就会有不一样的一个对应的i123 的值,这就是一个三维到一个深度的,三维的一个值到一个深度的一个映射,这么一个关系,也是我们可以把这r1 r23 。

把它描述成一个三维空间,这三个值就直接决定了我最后深度值是多少,这个同学们是不是可以理解一下嗯,就我三个测量,然后每一个深度值对应的三个测量值,实际上我们就这个r1 r23 这个相关值。

就建立了一个嗯这种映射关系,这种映射关系,对这个比较好理解啊,然后换一个呢,比如说换一个深度值,我们又出现了一个三个点哈,我们就可以认为在这个三维空间里面,每一个点都有一个对应的一个深度值。

这样的话我们是可以建立一个啊,直接这么一个映射关系啊,哎再换一个深度值,我们发现这个点儿跑到这儿来了是吧,但最后呢我们这个相关的一个值,也就是这这三种颜色描述出来的值诶。

就会构建成一个哎我们通过扫描不同的深度,我们发现正弦波,从零到d这么一个远的一个距离,会出现一个这么环型的这么一个coding coach,也就是我们这个环上的这么一个,每个点都对应着一个深度。

这就建立了一个啊,从r1223 到深度的一个映射,当然我们可以看到哈,不一样的depth就是对应了不同的一个coding cover,上上的一个点,就基本上每个点就直接对应了一个深度的值。

当然同学们想一想,当我超过二派的时候,会出现什么情况呢,现在我们还是一个周期范围内,当我们这个深度,这个只是对应的相位超过二派之后会怎么办呢,会出现一个什么情况呢,其实啊也就是比如说从这个点诶。

超过二派绕一圈绕一圈,到了二派又回到这个点了,也就是出现了花屏,在我这个这种3d的这一个r1 ,r23 的一个space里面,超过二派之后,我都不知道这个只是前面的还是后边了,这就出现了wap。

实际上也就是这一个闭环的一个coding,科贝车里面,也可以很清晰地看到这个vip这个问题,当我们解码的时候,实际上就是从i1223 想解出来,真实的一个深度值,当我们看到我们还是我们。

当我们这个深度直射的噪声影响的时候,比如我们这个r1 r2 r3 ,我们测量的时候会有噪声,会有噪声的,我们这个测量点实际上就是围绕着这个噪声,我们可以画一个画一个球哈,比如说这个点对应了这个深度。

但我们会受到噪声的影响,实际上我们这个测量的一个不确定性啊,也就是在这个点周围诶,围绕这么一圈噪声的问题,那这个噪声我们映射到我们这个深度上,会有一个什么样的问题呢,也就我这个噪声。

实际上对应了这么大一段的一个不确定性,这么大的一段的一个副确定性,同学们想一想,我们如何减少这个不确定性,最简单的办法是什么,假设我这个测量的那个噪声是恒定的,就我传感器的测量噪声。

它就是就是一个固定的一个噪声,我怎么样去降低我这个深度测量的一个宽度呢,怎么样最简单的一种办法是什么,嗯同学们最简单的一种办法是什么,最简单的办法是不是我们可以把这个r1 r2 。

r3 这个box做大一点,最简单还不是这个科普是加长啊,这个可能科室加长还比较难,你要一就做边吧,你光强加强一点,你这个r1 r23 值变大一些,噪声是固定的,但是你这个靠近科学者变大了。

是不是这样的话,唉我们受到噪声的影响是不是就小一些,最简单的就是把这个整个就是照明的一个光墙,拉墙拉墙,我们最后这个整个值就变大了吗,我造成那个球还是这么小,对不对,这样的话。

我对应的这个就深度的一个不确定性就会变小,对不对,也就是我们这个小的一个深度的一个accidity,就对应了一个更高的一个深度的分辨率,也就是top的测量,它的噪声直接决定了他这个分辨率是深度的。

分辨率是多少,当然要考虑理想的情况下就是没有噪声啊,我们没有任何噪声,所以说我们没有任何噪声的时候,也不考虑多路径哈,这个时候我们top本身测量的一个精度,可以认为是无限高的。

来我们实际情况不可能一直的,就是我们实际情况里面,不大,可能,一直的这种增强这个激光的一个照明功率哈,因为我们最后有些像这种相机,它是要符合安全标准,他达到一定程度之后。

它就不让不再是class one了,这个时候就很麻烦,不大好,靠这个光强增强,我们怎么样解决这个这个说到这个coding cobt的,这个就是我们这个深度精度的问题呢,就我们现在光源固定了,光圈固定了。

这个咋办,所以说刚才有个同学一个思路很好,就是说我们这个coding confeature可以尽可能的变长,从而我这个噪声相对于我这个coding,curvature来说。

对我们最后深度的影响就会变得更小一些,当我们想一想,我们在这个r e,r i s3 构成的一个3d空间里面,怎么样去尽可能的延长我们这个coding confession,对不对。

然后聪明的人类就想一想,当我们比如说我们用一个这种方波哈,方波做调制的时候,刚才同学啊就问了一个问题,说就问了同学们一个问题,就是到底是方波好还是我们这个正弦拨号,当然我们可以看到这个方波。

方波的这个correlation matrix,然后最后对应的一个coding curvature,它是好是比这个这个圆稍微大一些哈,是大一些,这是它的一个呃encoding的一个曲线。

你们知道两个方波这个做相关,它就是一个三角波嘛,我给你发现诶,这个换成方波调制稍微强一点哈,比刚才会鲁棒一些,因为我们最后这个coding confeature变长了,但是我们这个3d的空间。

还是没有很有效的利用好,很有效的利用,我们还可以尽可能的设计一个更长的一个coding,curvature,来减少我们噪声对深度精度的影响,我们知道哈我们这个深度的一个分辨率哈。

我们记为这个这个这个这个数,然后我们coding curvature越长,我这个精度就越高啊,他直接跟这个深度的一个精度成正比,然后本身呢我图像的噪声越大,我这个精度也就越差。

当然这个还跟这个深度的一个范围有关,但我们只考虑这个coding courage,其他的地方都已经定死了哈,我现在只考虑这个coding curvature。

对我们最后这个det是resolution的影响,那我们要考虑到这种本身的这个呃,正弦波的一个编码哈,它是这种情况,正弦波呢它对应的在这个r1 r2 ,r3 构成的一个曲线,实际上就是一个圆。

我们这个圆的一个半径呢是啥呢,是1/4的根号下二分之k k呢,实际上就是我们的一个对应的一个呃,测量的一个量,在这里面我们这个k是三,就r t r r3 ,你也可以测量更多维。

比如r4 r5 构成一个四维到五维的空间,从而建建立到了一个高维的一个coding curvature,对一个depth的一个映射,这个都随你哈,那最少我们是三,我们这个就用三个。

我们可以算一算我们这个圆的一个周长是多少,是多少哈,周长实际上就是我们知道这个这个半径和半径,二派r2 派r就拿到了二分之派,然后跟下二分之k,这个k我们可以就认为3号,我们可以约等于的去算一下这个值。

当我们考虑到这个square encoding,也就是我们方波的情况下,方波的情况下,我们建立到这个表之后,实际上我们是拿到了一个嗯,这种三个面拼成的一个图哈,三个面拼成一个图。

它总共有这个就是2k的一个pology,每个边的边长他是啊,这整个都算好,也你可以这个整个都算好,这个是更换一下k分之一,四个边哈,四个边,我们然后再算上2k,实际上我们实际上也是对整个值啊。

乘以一个2k,就是也就是我们最后达到二倍的根号k,这么一个值,这个里面这个k还是等于3号,这是我们一个square encoding的一个情况,我们coin function实际上就是这么一个三角波。

三角波经过这个变化啊,就变成了一个这种很奇怪的这么一个coding cov,最后呢我们发现经过计算哈,大家可以口算一下这个根号k咱就不管了,然后k这两个值相等,我们就是比较这个二跟这个二倍的根号。

二除以派两个值哪个大,这个这个就是二嘛,这3。14除以个二乘一个1。4,一四就3。14除以个2。8,明显就是二比较大一些嘛,所以说也就是我们这种方波调制,它的一个coding length。

是比我们正弦波要长的要长的嗯,大概就是3。14÷1。414的倍数啊,也就是我们大概能提高一倍左右的一个精度,1。8啊,1。8增加这个值,我们怎么样来实现一个最优化的一种,编码方式呢,我们将方波正弦波的。

是我们比较常见的常见的一种调制波形,我们可不可以设计一种最优化的一种编码方式,来让我这个coding coach无限长的,也不可能无限长哈,它是在这个有限的空间里面尽可能的长。

有限的一个三维空间里尽可能的长,所以说呢我们这里有这么多未知的一些量哈,我们想到了一个通信里面常用的这个办法,通信里面编码,我们想要避免我们这个因为相邻的编码相似。

而产生了一个就是这种immigrate,就是因为相似的一个相近的一个编码来混淆,所以说呢,人类发明了一种非常有意思的一种编码方式,编码方式叫格雷马哈格里马,这个我后面会讲到这个格雷马是怎么样啊。

去应用到这个嗯,就是他们flight imaging的一个encoding上面,当然我们想要在这个有限的三维空间里面,那可能实现一个尽可能的一个coding curvature。

就是人们早期里面也是做了非常多的一,些想象哈,比如说我在这种梅花型的,它是很长哈,他是很长,但是他自己自个儿给自个儿相交了,也就是我最后深度我分辨不出来了,那就不好办不好办了。

而且我们同学们是不是想想我这个画一个环环,是不是也可以呢,但是画这个缓一缓再有啥问题呢,就是就是我们这个局部的一些细节保持不住,保持不住,比如我这个噪声哈,我搁这划了一下,这几个都包进去了。

这个细节保持不住啊,这个最后咋办呢,大家可以看到这个就很难办哈,诶这有点卡了,这ppt卡了,同学不好意思,这个有点卡了,所以说我们又不可能说随手画一个这种,很长的一个cvt来实现这个encoding。

所以后来人们就想到了格雷马这种方式,哈格雷马这种方式,这个这个是这种优化的方式,经过从从格伦玛借鉴过来了,叫哈密顿编码,我们可以想一想这个哈密顿这个cycle,假设我们一个高维还是三维吧。

就简单一点就是到三维用了,它可以是一个超超超超超立方体哈,我们有这么多个note,然后这么多个边缘,我们这个哈密顿这种编码,我画这个啊,在这个编的时候,这种哈密顿的编码是可以实现一个最长的一个。

coding path,他这个coding coverage length呢可以达到2k,减掉个二哈,剪掉个二,也就是我们这里一根两根,三根四根五根六根六倍的边长这么大,也就是在我们这一个超立方体里面。

能实现的一个最长的一个coding pad,是吧,那我们把这个回到这个问题啊,我们就就就三维,就r1 r23 这三个相位测量值,我们把这个这个,coding path,然后解成相位啊,解成相位。

反着推回成推成相位也好,我发现我们这个correlation function,它是一种梯形的一种口味方式,这个是不是很神奇哈,也就是说在这种畸形的一种条件下。

我们可以实现一个最长的一个coding co,最长一个coding coach,但实际上我们要想做到这种梯形的这种cod,这种调制波哈,实际上是比较困难的哈,这你想想这个理想的一个方波,你都整不出来。

他要345次斜坡,你比如说你这个100兆,你搞个五次斜坡,这都五六次,这五次解剖哈,一三这个34524446484,那这几次斜坡好家伙就就就大几百兆上g了,这个条例来说是非常困难的。

你要想搞个这种奇形怪状,这种梯形的这种波形调制出去,实际上是更困难的,它是一种高速斜坡,实际上是更难实现了,但是呢这个聪明的人类是有办法的,后面我会讲到。

怎么样实现这种哈密顿的一个coding coach,也就是我们调制波是方波,那我们要考虑到更高阶的一个哈密顿编码,就是我们要四次五次测量的时候,哎,我们就可以通过这种办法来实现一个这种呃,调制。

其实这个办法是从这种格雷法借鉴出来的,我们可以看到这个格雷码,我们让任意两个相邻的这个相邻的两个马,只有一位是不一样的,这一位是不一样的哈,我们看看第一个点000,它最后一位不一样。

然后这两个相邻的中间这位不一样,后两个就是最后一位不一样,然后在这两个第一位不一样,在后面最后一个不一样,它每两个相邻的编码之间只有一位,是不一样的是吧,这个就是呃1953年啊。

就是大家就可能通信里面会讲到这个格雷马,就是我们这个哈密距离在任意两个编码之间,它只有一位是不一样的,我们这个哈密顿编码呢,也是借鉴于这个格雷马里面这个思想,当然同样的这种思想也可以用到这种结构框的。

一种3d成像啊,这个这个用这种格雷码编码的一种python,已经是有了,它可以啊,比较有效的提高我这种结构光的,一个呃精度的分辨率,大家可以看看这个用格雷码,是不是跟我们这个对应的。

000~01这个位置对吧,到011,刚好跟我们的哈密顿编码是对应的哈,只是我们的这个哈密顿编码,它是一个连续的一个编码,这个格雷马是一个离散的一个编码,很神奇啊,很神奇这个各个领域之间。

所以说为什么就是喜欢推荐同学们去跨领域的,看一些东西啊,这可能拿过来就是一个非常经典的一种方法,来解决一些非常实际的一些问题,我们对比一下这个coding confeature的length,在比如说。

我简单点三次测量,三次测量,四次测量,五次测量,在这几种情况下,我们发现哈密顿编码,哈密顿编码是可以非常有效的提升,我这个coding coverage的l,也就是提升我对深度精度的一个鲁棒性好。

也就是在相同的一个照明强度情况下,噪声也比较固定了,我通过哈密顿编码,可以非常有效的提升我的深度测量的一个精度,这是一些比较仿真的一些结果啊,大家可以看到楼梯啊,楼梯这种多路径是非常恶心的。

我们可以看到这个,不同的场景哈,像正弦波,正弦波调制派一个平板,大家会发现诶,这个狂热兔子是一个这个深绿色的哈,正弦波和方波,我们发现方波可能会比正弦波这个误差小一点,小一点。

哈密顿编码呢是可以非常接近的,这个光非常接近这个光出色的,这是一个剖面图啊,这个剖面图,同样的我们测了这个圆的时候,ground truth是这个深绿色,那么哈密顿编码是黄色,它的误差可以做到很小哈。

24mm,但是我们这个正弦波正弦波这种这是红色的,就会误差非常大,误差非常大,它会受噪声的影响非常大哈,然后这个方波好一点,大概我们可以看到1。8倍哈,这个好像这个这个值还是挺准的。

我这个coding lt差不多1。8倍,这k等于五哈,这五大家可以算一算,这个误差的这个error跟这个coding lens,可以课后算一算到底是不是混合的,这是一个楼梯的一个情况。

我们发现这个这个正弦波,受楼梯影响已经非常严重了,看哈佛对编码可以非常有效的去降低,这个造成对深度精度的影响,那我们可以拿一些嗯在强太阳光下,比如说强太阳光是一个噪声噪声源。

一个global offset,一个噪声源,我发现这种正弦波编码五张图哈,就五四测量方波母子测量哈密顿编码,它的误差从14。5mm,8mm降到了用毫米的编码呢,这种k等于五的时候可以降到1。46mm哈。

差了接近一个数量级,我看到这个人脸这个细节也会变得清晰起来,对这是他的一个smooth后的一个结果,这是一个室外的一个测量啊,把这50米的一个top,你可以看到正弦波这个细节,已经基本上完全看不到了。

误差40多厘米,但是这个哈密顿编码是可以有效的去恢复出来,它表面上的一些细节,也就是我对噪声更加鲁棒了啊,更加鲁棒了,当然我们刚才讲到了,我这个好像这个梯形不大好不大,好实现,对不对。

我们要实现这么一个梯形的一个correlation function,对吧,我们可以比如说我们用一个就是dota function,跟一个这种梯形的一个这种图去做一个相关。

我们是可以拿到一个coration方式,当然我们想要发出非常窄的一个impulse function,是非常困难的,这个是不大可能哈,因为它频率太高了,我们怎么样通过我们通过合理的手段。

通过我们现有的一个这种电子的一些信号,来去实现这么一个梯形的一个correlation function呢,我们要怎么样去设计这个调制波跟这个解调波,从而发现我们这两个波形之间做一个卷积。

就可以出现一个梯形的这种模型,实际上这个问题在我们实际的应用里面,是比较简单的哈,比较简单的,大家稍微调一下这个战控笔就可以了,就我们正常情况下是一个50%,50%的一个方波哈,做一个相关。

我们拿到一个三角波,我们把这个调制这个方波占空比调窄一点,与之对应的呢,我们这个p modulation的这个参考信号,把它的占空比调大一些,我们这两个信号之间的相关就可以实现,比较轻松的实现。

我们这个理想的一个梯形的一个口人声方式,这个就是在实际应用里面,就会把这个问题变得非常简单,就是我最后调一下真空,比我这个理想的一个呃,codlss就可以做出来的啊,这个是啊实际电路里面是怎么样操作的。

当然我们最后要总结一下这个深度的测量,跟这个就是深度的精度,之间的一个矛盾的问题和矛盾的问题,就是对我们这个三角就是用这种结构,光用三角测量法来测量我们这个深度的时候,在比较近的距离。

因为这个三角我们知道是通过结构做参考,来去算计算这个深度的,也就是我们在比较近的距离,是可以实现一个比较高的精度的,就可以,甚至可以实现就几个微米量级的一个,深度的进度,但是呢它的这个精度。

会随着就是测量范围的变大,比如测量距离的变远,而很戏剧性的下降,本身呢我们这个tom fighting image,他就反正进的地方精度不是很高哈,进的精度地方精度不是很高。

我们目前可以做到的就是可能比这个更高一些,可能我们自个儿能做到1mm左右,1mm左右它不大,随着这个深度的变化,它的精度不大随深度变化而变化,但是啊绝对的测量精度不是特别高。

现在我们自个儿顶多也就做到1mm左右,那我们理想的情况下是啊又要远啊,这个精度要高啊,这是理想的,我们后面要实现一个努力的一个目标,今天呢讲这个课程可能呃比较比较难懂哈,比较难懂。

就我们最开始讲了这个micro image,也是来针对我们这个多路径啊,或者是这种scattering medium,这种产生的这种非直接测量的一个啊去除哈。

我们用micro imaging这个就这种方法,两种相近的高频,然后后面呢我就抛出来这个问题,怎么样实现一个更鲁棒的一个coding,也就是我们想尽可能的,去延长我们的一个coding path。

在有限的条件下去延长我们这个coding path,来提高我这个他们flight image的系统,对噪声的一个呃罗邦性啊,也就是提高啊在相同的造成情况下,提高我的深度的一个分辨率。

最后呢我们讲到了这个哈密顿编码啊,哈密顿编码,实际上是借鉴于格雷马的这种一种思想,把这个格雷马的思想运用到这个continuous wave,他们flat ming。

最后来实现了一个有效的一个精度的提高,甚至可以提高到一个数量级的一个,精度的提高啊,这是一个非常有意思的一个啊过程啊,啊今天的课程就到这里啊,同学们有什么问题吗。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这今天挺有意思啊,这个哈密顿编码是可能是19年还是20年,西瓜那时候还是18年,我忘了,当时wolf港问我,你觉得哪篇论文今年开会的时候最有意思,当时我就跟我说的是这个哈密顿编码哈。

他当时这听完觉得就是眼前一亮,耳目一新,这么简单的一个变动,就可以很戏剧性的提高,我这个深度的一个精度哈,同学们还有什么问题吗,可能今天讲的也比较清晰了,比较清晰的,那么有什么问题的话。

可以借着这个直播间的机会快速的问一下哈,当然这个我们现在也对这个刚开始,方波和正弦波的这个哪个好做了一个解答啊,当然有同学说方波信噪比高,有的同学说风波频谱宽。

其实呢本质上都是延续了我在这个coding space里面,他的一个coding curvature的一个长度哈,同学们还有问题吗,啊如果同学没有问题的话,今天的课程就到这里,下节课我们会讲到这个啊。

temporal encoding的最后一课也是cody啊,temporal photography啊,这也是一个非常有意思的课题,后面我们会进到这个special encoding的一个范畴。

好今天的课程就到这里,再次感谢同学们啊,耐心的聆听。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

22.GPU驱动的几何管线-nanite (Part 1) | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV1Et4y1P7ro

感谢大家一直跟我们在一起。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那今天作业最后一节课呢,我们给大家公布一些我们课程一些啊,我们做的最后的一些准备,比如说很多小伙伴已经完成了我们课程的作业,将近有100多个同学教了我们的作业,然后呢。

有40多个同学达到了我们的毕业的标准,还有十几个同学是全部答对,非常的厉害,然后呢,我们课程组就很用心地设计了一个,我们的毕业证书,那我们也极尽所能,我们想让我们的证书看上去更漂亮和专业一点。

那么也就是说所有的这些小伙伴的话,你们把你们的地址在群里面告诉我们的,课程的助理,我们会把这些那个证件证书发给你,我相信的话,也会帮助同学们未来在寻找自己的工作呀,在自己的求那个求职啊。

那个求学的道路上,也是大家的一个certificate,因为就是games104的课程,这些作业全部做完的话,实际上本身还是蛮挑战的,就是说昨天的话恭喜我们这些同学们,然后另外一件事情的话呢。

也就是说啊实际上随着课程的逐渐的接近尾声,那我们就课程组的话,终于有些时间,就是把前面这将近十几个十个月吧,没有有没有十个月哦,将近有六个多月我们做的这些课程,然后呢把这些资料准备好。

所以我们会把我们的课程整理成文字版,这样方便同学们去阅读,同时的话呢,大家可以关注我们课程的这样的一个公众号,这样在这里面的话呢,我们会持续性的把那个PICO小引擎持续更新,因为那个也是我们的爱。

然后前面一直在准备课程,大家都非常的忙,确实准备课程压力太大了,但现在随着课程那个准备,我们可以告一段落的时候,那我们可以有更多的时间,好好的跟大家一起维护我们的piccolo引擎,包括一直欠大家的。

我们的PICO的源码解读啊,包括我带着大家一起去给我们的皮卡罗,增加一些更多的feature对吧,说不定一年后会有很多同学用皮卡做出自己的,很酷的大作业,很酷的这个毕设很酷的游戏,那作业这一点的话。

非常的兴奋,那么最后呢其实课程组终于有时间做一些,这个就是说呃怎么说呢,回顾和总结的事情,那这里面的话呢,其实啊哇这里面有个tb,实际上我们课程组的话,前两天把我们POO引擎里面所有的知识点。

全部做了个图谱,大家看到这个图谱上是不是密密麻麻,对不对,不好意思啊,那只是整个图谱的1/10都不到,其实它是一张很巨大很巨大的图,到时候我们课程组会把这个图分享给大家,然后确实准备这个课程的话。

我们花了好多好多的时间啊,就是查了上万种材料啊,然后总结了大概1500多个知识点以上,然后呢,其实将近2000多个人天wow在这个那个工作里面,所以的话呢希望同学们会喜欢我这门课。

那么在今天的课程结束的时候,大家不要走,我们会有一个课程组精心准备的一个彩蛋视频,也是送给我们所有能坚持到最后一刻的小伙伴,然后呢,也就是也是表达一下,我们课程组这一这将近半年以来我们的情感。

我们特别想和大家一起say个hi,这也是第一次我们课程组让全员让大家看到,OK所以呢感谢的话先说先先说这些,我们还要回到我们今年课程的正文,那上一节课呢因为准备的特别仓促,所以欠了大家的QNA对吧。

那这节课我们先补上大家的QNA,那么第一个问题的话,大家就问我们说诶,这个在ECS这个架构里面的话,如何解解决一个NT被删掉这件事情,其实在ECS架构里面呢,它追求的这个就是硬件的性能。

所以说它它一般一个ANTITY或者被删掉的时候呢,他不会真的把内存释放掉,因为大家知道,每一次内内存的allocate和DEALLOCATE的话,都会牵扯到那个hip的这种操作就会很慢。

所以呢它其实只是把那个index把它制成空了,那下次再有一个新的allocation的话,那直接reduce那个index,那么怎么样的区别,就是新版的那个音ITY和老板的entity呢。

我们在之前跟大家讲过,就是加一个salt对吧,SD一般就是累加的,就是意味着就是说,所以我每个东西看到的时候啊,诶我看到你的index是一样的,但我的salt吃的不一样,我就知道哦。

这个之前指向那个nt handle是无效的,所以简单来讲的话,在这种高效的这种非常高频的这种啊,这个系统里面的话,我们会尽可能降低memory allocation的第一个allocation。

我们把内存直接有一个有一个链表,直接把所有free space全部串在这,然后直接就用起来了,那么第二第二个同学问我们说,哎我们怎么去测量这个catch beast,哎呀这个问题就非常的难了。

首先第一个呢啊在程序里面,我们自己去测KASHMISS其实是很难的一件事,但是我们可以估算对吧,但是的话呢实际上一般都要基于GPU厂商提供的,这样的一些工具,把我们的application跑起来。

挂上那个挂到那个那个那个那个就是工具里面,然后呢他会帮我们抓到说诶你的CPU cg啊,你的这个l to l three cash的这个miss啊对吧,会告诉我,那比如说在英特尔的CPU上。

我们有个工具叫wow tube,他会告诉你这样的东西,所以小伙伴们如果想写这种高性能的代码的话,一定要学会用这些工具,包括我们教rendering里面很多讲到的cash,miss这些东西的话。

其实在GPU上也有这样的一些就PROFING的工具,这一般都是硬件厂商给你开放出来的,因为你自己是没有办法知道那个硬件的spec,对吧,那最底层的那些接口函数,那么第三个问题呢。

就是说诶就是说我们如何给designer,一个面向数据编程的,这样的一个架构的工具集啊,这个要求实在是太高了,因为其实当我们在一个真实的游戏团队,你们工作的时候,你会发现就是说在游戏团队里面。

我们的艺术家artist,我们的设计师,designer和programmer程序员是完全三种不同的物种,真的大家的这个这个这个思维方式,差别是非常非常大的,这其实也是这个就是说我觉得做游戏也好。

游戏引擎一个乐趣,就是说因为你实际上游戏引擎的本质是什么呢,我们是做工具的对吧,我给大家一直在讲,就是我们是做工具的,那么你的工具的使用对象,他的思维方式和做工具的人是完全不一样的,对吧。

artist看见一个东西,他就喜欢边边边往上往上去那个贴对吧,他就是他不会去特别在意这个结构和逻辑,而designer呢更多的是希望AI will express myself。

就是说我希望表达我自己对吧,我希望创造出各种各样,如果你告诉我说一辆车必须有这五个部件构成,那我一定要做一辆车,是用加上一些额外的功能,跟你想象的那个车完全不一样,为什么,因为这样的车才会有耗。

才会有这个我们叫NOVT,就是说比较有趣,比较有创意,对不对,所以designer天然的就是要打破你设计的这个,Paradise,就你设计的范式,所以呢在DP里面的话呢。

我们是希望每一个component它的那个模组啊,就是这个功能都是明确的单一的,这和designer的需求是天然是有冲突的,但是呢怎么说呢,其实在我们在做这样的一个一个架构的时候,给自己的工具。

我们尽量的把每个component变成一个个的积木,然后呢哎让designer自己去组合,但是相信我,designer可能很快就会需要一些不一样的东西,那这里面的话呢其实我们需要做一个工具。

告诉第三点说,诶如果你希望做一个非常customize的功能的话,那么你就可能不能走那个DOP的pipeline,它的性能可能只有DOP的110,你愿不愿意,比如说我给他一个budget。

他就是说总的性能的bug,然后他就他就开始思考了,说嗯,我是以十倍的成本做一个非常酷的一辆车呢,还是以非常高效的这个成本,我做100辆车对吧,这就是让他去想的一个问题了,那么所以呢工具测的话呃。

首先他一定要允许这个设计师去组合,另外一个的话呢就是说呃我们不去替他做选择,但是呢我们要非常清晰的把他做的每一个选择,所产生的这个成本告诉他,所以呢其实在真正的实战性的游戏团队里面。

就巴基control就是预算的控制,包括呢这个预算的这个visualization,就是说这个预算指的不是钱啊,这你们讲的哎我的CPU的性能啊,GPU的性能,我这个预算控制,包括直接可视化。

其实是非常重要的一件事情,如果讲的更深一点的话,包括我们的QA流程,也就是说你做了设计师做了一版的改动,然后呢整个游戏不就变了吗,那游戏里面有那么多的关卡,我跑一遍,我要保证它的性能完全符合我的需求。

那这件事情的话呢其实也是非常复杂的,而且在真正的实战性游戏团队里面的话,这些流程全部都是自动化的,也就是说设计师改了一个玩法,那或者改了一个比如说小怪的AI啊,或者兵团这个这个这个。

或者说NPC作战的模型啊,那其实很多的测试全部会自动发生,告诉我们说对性能有没有大的变化对吧,包括他自己也要知道收到这个report,那么第四个问题呢,就是说哎这是跟我们上一节有关的。

就跟我们说诶the moon,你们能不能就是如何解处理这个自发光的材质,对吧,其实我记得我在那一刻我特别强调了这件事情,就是说其实四方光材质呢,它的lighting。

在这个就是说在传统的我们的rendering里面的话,其实是比较难以处理的,我们很多时候会给它加一个fake lighting,加一个假的光源,挂在那个自发光的材质上,看起来就像你身上有个led照亮了。

但是在lumen的这个结构里面的环境,其实对于这种低频的自发光,它解决的还真的是蛮不错的,就是大家大家如果急得我上一节课讲的,就是说这个四方框材质呢。

它这个radiance会写到一个单独的surface cash里面,那里面有个emission的那个channel的那个texture,然后呢,当我们在空间中采样了一个个的。

就是water metric lighting的时候,这些光这些radio全部会被踩进去的,踩进去之后呢,当我再去生成那个screen space的那个probe的时候。

这些光就会被踩到我的这个screen space里面去,而且呢它还有很神奇的设定,大家记得吗,就是左脚踩右脚踢云纵对吧,我这一帧的光到下一站又变成我的intro lighting。

这样的话我的那个就是自发光的multi bounce,实际上也可以在这个就是说一帧一帧,一帧的去这个传递中的话,形成multi bounce的这样的一个效果。

所以说我个人觉得lumen里面在解决自发光的,这个就是特别是自发光的这个这个就是GI,也就自发光形成在场景里多次反射的效果的话,这个方法其实还蛮漂亮的,但是呢我自己也很希望能够做一些实验。

看看它最终的效果怎么样,比如说这个自发光我能不能支持HDR呀对吧,它的效果是不是足够明显和准确啊,这个需要花一点时间我们再去验证一下,但是整体的它的结构做得还是蛮好的好。

OK那这就是我们今天的QN的内容,也算是回那个还了我们上一节课挖的一个坑好,那今天就到我们的课程的主题了对吧,NAT耶,这个哇,这个简直是一个神坑级的这样的一个topic,那么NT的话呢。

实际上也是大家很关注的,这一代游戏引擎的一个很很顶级的一个技术,那么我们也是花了很长一段时间去理解,NT这个技术去分析,也希望给小伙伴讲的清楚,但实际上这个准备课的过程是实话实说,是非常艰辛的。

我我我们课程组的小伙伴经常会争得面红耳赤,我记得我在课程备课中最常讲的一句话说,哎你们不要忽悠我对吧,因为其实呃从它的本身的PPT啊,到作者的讲解啊,其实这里面空白的地方盲区还是很多的。

所以呢我们课程组最后大家真的很多时候,被迫打开源代码,一行一行源代码去看,包括也做了很多小实验,确保我们对它的理解尽可能的去正确,那么基于类似于上一节课的我们的传统。

就是说我们不太会把原始的这个这个presentation,顺序的给大家讲一遍,因为原作者讲的肯定比我们好,我们尝试给予我们的理解,从这个技术的源头讲到这个技术里面,最关键的我们认为的一个大的结构点。

有些细节我们会跳过,但是呢我们要确保,把最核心的东西给大家点出来,好啊,废话不多说,到我们今天的正题,NT对吧,一个新一代的这个geometry pipeline,就是无限极和细节的叫pipeline。

那么首先的话呢在理解NANA的这个事情的话,哎我们要去开始复古的理解一下,就是我们在前面那么多节课讲的,rendering pipeline对吧。

其实我们在前面讲的很多rendering pipeline,实际上呢是一个传统的render,那么这个pine一个很大的特点是什么呢,就是所有的需求是在CPU那一端发起的,就是我们经常会发生一个桌扩。

那么大家如果学open g2,那学direct,你们会知道一个指令叫draw primitive对吧,画一画一个mesh,告诉他vertex啊,index啊对吧,一小篇match出来这个东西呢。

其实啊在GPU上,首先呢你还要准备一大堆的,这个你要用哪个texture呀,你的阿尔法布兰妮设成什么样子呀,你一大堆的我们叫做render state,这一大堆都设计好之后诶。

你进入那个漫长的pipeline,在CPU里面他还要通过swapping到GPU里面,然后GPU里面开始进行这个处理来跑vs p s,还有rust riser,那其实在这个过程中啊。

很多时候CPU实际上是第一个,它速度可能跟不上GPU,第二件事情呢,CPU本身会有大量的算力,会浪费在准备这些素材的本身,大家可能都不知道,就是说桌括其实是一个非常expensive的东西。

比如说我们以前大家还记得我们在讲SHADER,讲材质的时候,尽量讲材质,同一个材质的渲染,我们要merge在一起,为什么呢,因为我们这样可以把他的桌这个设置。

那个render set全部merge在一起,其实这一条长长的排不来,就是哪怕你就画一个一个三角形的话,整个pi你得走一遍,所以这是垂直上的render一个很头疼的问题,那么这样的一个问题之后呢。

其实啊对于现代游戏来讲,现代游戏的特点是什么,就是哇我的几何会,这个就是我们的场景中的这个几何,会非常的复杂对吧,而且有很丰富的材质,大家还记得我上次给大家讲那个就是啊,在那个迪斯尼那个那个那个报告中。

他讲,他说他一个屏幕上好像是有上千上千种材质吧,对吧,那这里的组合就会爆炸了,我有我有我的mesh,哪个mesh呢,我渲染的时候我有我的render state对吧,我mesh还有我的LOD怎么设置。

然后呢我还要设置我的材质,材质可不是一个参数,它有一大堆的参数,还包括各种各样的texture对吧,然后呢我还有skinny with animation哇,这就是一个combination。

就是什么组合爆炸了,对不对,那这个时候当我们去做客的时候,我们每一个组合我得扩一次桌括,你想我们要扣多少次桌扩,而且呢为了每次周末之前,我还要propel它的render state。

大家如果对现代GPU,包括在显卡的,这个是那个性能有所一些了解的话,大家都知道就是这个render state的这个这个设置啊,其实本身是非常expensive的,非常贵的。

所以的话这就会导致就是说诶按照传统PIPINE,如果绘制像现代,特别是3A级游戏这样复杂的场景的话,它基本上是跑不动的对吧,它就是会非常非常的费,但是呢好消息是什么呢。

就是说在这样的一个这样的一个情况下呢,我们就会发现,就是说GCPU实际上会被做了大量的,比如说计算,比如说我们做的wow russian colin对吧,就是这个在CPU里算完,对不对。

然后C哥算完结果我还得提交给GPU,而且GPU呢这个时候很多说他啥也干不了,他只能等着CPU把这数据准备好,而且呢就是说在java里面。

每一次去change exchange的render state的话,本身也会非常的费,所以呢这是traditional rendering pipeline,就是非常头疼的一件事。

这也是就是已经成为了一个瓶颈,那这个瓶颈呢实际上他的曙光是在哪里呢,就是第一个就是随着这个2010十年前,computer shader逐渐逐渐的成熟,到现在为止。

computer shader已经非常成熟了,那么他呢就可以做一件事情,什么意思,就是我们可以不用在CPU和GPU之间来回导数据,大家还记得我们在之前讲过,就是我从一个数据从CPU里考进GPU对吧。

这个事情是很废的,因为在CPU里面的话呢,我的这些render pipi,还得从这个memory里面load到cash,Cash,再到我的pick shader workshop去处理。

那能不能所有的计算就在GPU的内部,那就有个前提,比如说我要做一个唉世间锥裁剪,这里面一大堆的数学运算,对不对,那能不能在GPU里面写一个通用的计算器,把它处理掉,它的曙光是什么呢。

就是计算SHADER,Computer shader,那么它呢就是说可以完全的在GPU上做出大量的,以前只能在CPU上做的通用计算,所以呢就是说这样就使得我们的很多的这个。

CPU和GPU之间的通讯变得非常的简单,那么另外一个的话呢就是rendering API,以前的话呢,我们一个桌primitive只能画一个mesh,对不对,哎但是现在我们可以做indirect的时候。

我们可以把一个就是这个array of the parameters,或者叫一个parameter buffer,把它整个录得进去,我一个周末可以画很多的mesh,那这样的话也是使得我们能够尽量的减少。

就是在CPU到GPU的桌括这件事情上,就是成为了可能,所以的话呢其实在就是56年前,其实更早一点,就是说大家应该是我67年前了,更早了,就是说大家提出来了,就是说哎我们以前是一个一个对象的渲染。

我能不能把以前很多CPU的给rendering做的计算,比如像visibility啊,l o d selection啊对吧,全部把它移到这个GPU上去,而且呢我把整个场景数据全部放到显存。

大家看打开现在的显卡,你们发现一个特点,没有显存都很大对吧,动辄就是几个G的,所以我整个场景其实是可以基本放进去的,对不对,那我就不想让这个CPU再去做什么操作,CPU只是发一条指令。

说把场景给我绘制一遍,我设置一下相机参数对吧,剩下的事情最好你GPU全部搞定诶,那这样的话,这个我们就从以前的一个draw primitive,就变成了一个JC,这个呢其实就是我们讲的时候哎。

现代GPU上GPU driven的rendering pipeline,最理想的最终极的状态,那么这样的一个很大的好处是什么呢,就大家还记得,我以前在一开始给大家讲的,就是游戏引擎的架构里面。

游戏引擎它是一个对实时性要求非常高的一个,一个一个就是SDK,那么大家想想游戏里面除了渲染啊,是不是还有很多其他的东西啊,比如说我们的这个AI对吧,我们的游戏逻辑对吧,我们的各种各样的玩法。

把物理检测一大堆东西,对不对,那这些东西的话呢,我们啊包括网络通讯,那我们就可以把这些东西,全部放回到这个CPU来做,这CPU一下子就被释放出来了,那么GPU呢就等于说渲染的东西交给显卡,你来做了对吧。

我CPU就不要在这瞎忙活了,以前大家如果看的话,render thread是很满的,对不对,后来为了解决这个问题的话,我们还提供了就是这个多线程的这个state的提交,这个大家如果了解一下DX12的话。

这个架构包括我很架构是很核心的,就是个多性能的提交,那么哎但是的话呢,其实这个时候我CPU资源大量的被浪费,所以这些东西啊,其实是我们讲的这个就是后面要讲的cost,Brendering。

visb buffer啊,包括我们讲的NAT的话,它最原始的一个思想,就是说我希望整个这个世界的几何的裁剪,LOD的选择,甚至包括几何的这个就是选择哪些东西,可见不可见,全部在CPU内部完成。

然后呢我尽量不要让CPU特别的慢,所以这个是我们这节课的体验,就是什么时候我们能从一个draw,primitive到JC,这是我们要解决的问题,这里面最早的这个先先驱者呢。

就是我自己找到的是那个刺客信条,大革命那一作,对,这里面应该叫secret,这个这个这个那个unu unity对吧,那么其实呢就是GPU driven的这个pipeline的话。

最早是他在我印象中是2015年SEGA上,他们给了一个分享,这个确实做的非常的了不起,他们要解决什么一个问题,就是大家看大革命这一组啊,他所展现的那个场景,有大量的这个精细的。

这个这个这个巴黎的这种建筑啊,那些浮雕其实非常的让人震撼对吧,那么这么里面这么多的精细的几何,你去怎么去渲染它,怎么去绘制它,其实是个非常难的一个问题,在过去传统里面我们去表达这个几何的话,没有办法。

我只能把整个几何low的进去对吧,然后呢我就开始一个instance,一个inst的rendering,但是呢这里面就会出现很多问题,就比如说很多的instance其实是不可见的。

甚至是对于一个建筑来讲,一个建筑是对不对,但是你看到他的前面的柱子,它柱子后面的很多,虽然也属于这个建筑的mesh,它其实也是不可见的对吧,那我要为这些东西设置多少个状态。

那么我才能解决我的这个渲染高效率的问题呢,就是大家想象一下,如果我有上亿级的这个面片的话,我去渲染它的时候,实际上我里面可能有上万个物体,我怎么去渲染它,其实这就是当时大革命这一作的话。

它所面临的一个非常大的挑战,那他怎么解决呢,诶他们是最早提出来说,我们用cluster based rendering方法去解决它,这个方法呢讲起来很高大上,实际上是非常简单的一个淳朴的思想。

就是说对于一个每一个这个游戏世界里面的,一个instant的一个物体对吧,它可能是几万个面甚至十几个方面很大,但是呢我把它分成无数个,有128个三角形呃,应该是他选择当时选的是64个三角形对吧。

这不重要,大概就是一个小的固定尺寸的一个叫cluster,这样的一个一个一个一小片的mesh,那这样的话呢,其实我就可以把一个instance,分成无数个小的cluster。

而每一个小小的caster呢,它实际上都可以做自己的BINBOX,那这样就好了呀,当我去去渲染这个东西的时候,我以前只是检测说这个instance是不是可见对吧,但是现在我有了这cluster的时候。

其实我可以检测什么呢,每个class是不是可见,而且呢每个cluster他的是不是会被背面裁剪,会不会被那个depth去遮挡掉,这样的话,我对整个这个世界的表达的颗粒度就会细,非常非常多。

哎这个东西听上去有点反直觉啊,但是其实这个是非常重要的一个observation,就是说因为我们在computer shader里面的话,我们是可以就是批量的处理,这种uniform的结合的。

但是的话呢我们整体的去对于每个instance,LOD切换啊,包括就是这个我的卡林对吧,我大家知道我们画一个instance,无论这个东西可不可见,但是你如果有10万个三角形,只要这个instance。

我只要一个角可见的话,那10万3角形我得整个再炫一遍,这个其实是很废很废的,但是你想一下,如果我们在大革命这样的一个场景里面的话,很多时候这些建筑这些东西,它本身就是一个很精细的模型。

但是你站在一个里面的话,你看到的就是它一小块,所以呢哎我把这些mash分成很多cluster的话,实际上理论上来讲,它可以实现对船购的这个最大化的利用,就是对于所有不可能看见的三角形。

我是尽可能少地绘制它对吧,所以这个看上去很复杂,但其实大家如果仔细推演一下,你会发现他对几何的利用率是最高的,那么他这个拍拍案想起来呢其实也非常的简单,这是他画的整个这个流程图,它首先在蓝色的。

在CPU的部分呢,它其实就是对这个instant做了一个最简单的,比如说view russian coming对吧,然后呢在GPU阶段的话,它会进行一个比较精细的这个view fcm。

它就是会把很多的看不见的instance给卡掉,这里面其实还包括depth,然后呢每个instance的话,就是每一个物体它又会分成很多的cluster对吧,他把这个cluster再做斯卡林。

这样我把这个可见的这个物体的,不可见的那些小的部分全部也扔掉,然后呢我把这些锁,然后呢每个cluster它不是164个面嘛,对不对,我甚至把一些不可见的三角形我都扔掉,最后呢我把所有的可见的啊。

这个讲起来比较拗口了,叫可见的instance的可见的clustered,可见的船go,把他们全部packing成一个超大的index buffer,它这个过程叫什么呢,叫index buffer。

compact compaction对吧,然后哎我最后一个桌扩或者一个indirect jk,可以是这个这个这个INTELJA,也可能MULTINTELJAL诶,我就把你整个场景画出来了对吧。

这其实就是当时刺客信条他这一做的时候,它的一个核心的思想,你可以理解成,就是说他在前面用这么多的GPU的运算,包括这么复杂的class base的结构,诶他做了一件事是什么呢。

就是啊做了一个超级的这个啊visibility carly,就是把所有不可见的triangle,尽可能给你全部干掉了,而且呢把所有可见的这些几何,全部group成了一个大把粉。

然后呢我一个周后我把你全部搞定,所以它就达到了性能的最优,同时的话呢也尽可能降低了屏幕上呢,我们叫做什么呢,叫这个这个这个overdraw,就是说同一个pixel我很多三角形画的话。

他们就彼此之间产生了浪费嘛,这个其实是它最核心的思想,那么这个思想为什么我要先讲它呢,因为其实大家去理解NT的话,他的思想的源头实际上是来自于这个思路,就是clasps rendering。

那么包括就是我们看到那个非常有意思,就是啊,发明这个就是COSPARENDERING的这个这些老歌的话,那会写很多的,这个twitter就是在讨论说诶,你NT哪些技术是你更厉害的。

哪些技术是我发明的对吧,彼此之间还在讨论说谁才是这个技术的发明者,但是没关系,我们不卷入他们的争论,但是呢确实这个就是大革命的这一作的话,确实引发了一个class based。

rendering的这样的一个革命,那么其实在GPU赛呢,CPU赛就是在那个就是非常的简单的,他只是做了一个非常简单的,就是对instant cotree的一个coming in对吧。

他就是把这个就是说那些各种各样的桌括呢,他还做了一件事,就是说根据你的材质不同,他做了一个哈希表,把你相同的材质,相同的render state的东西,尽可能顾不到一起往里面去去去去提交。

那么接下来的话呢我就把每一个instant data,无论是你的transform l o d啊,你应该用哪一层的LOD啊,注意啊,这里面在大革命里面的话,每个instance l o d是自己算的。

就是这个其实还有一个古典做法,就是说啊比如说这边有个柱子,它讲的是一个是一个instance的话呢,它的LOD是整体说我切的LOD0,还是12345depends,我靠近相机的距离。

这个其实后面我会讲了,这其实是和那个NT有个本质的不同呢,我们先不讲开,那这些信息呢诶我把它packing成一个buffer,然后一股脑就交给我们的GPU来开始处理了,那GPU干什么事情呢。

其实GPU非常的简单,哎这个虽然这个图画看上去非常的复杂,但是我尝试用最简单的方法去解给大家讲清楚,就是说呢,哎我这个时候我就有一个,我现在要绘制的instance的列表,对不对。

那么我一个每个instance的假设,大家知道有几万个三角形,对不对,我呢把这个几万个三角形分成很多的cluster,但是呢很多的cluster呢其实太碎了,他还做了一个叫chunk对吧,就chunk。

就是你可以认为就是把一群cluster grp到一起,比如说啊16个啊,或者32个对吧,这个depends on他的选择可能一般是32个,为什么呢,就是这个里面有个小的trick。

就是说我们在这个就是说显卡里面,我们的那个那个,就是大家还记得我们的每一个computer shader对吧,他有一个叫wave或者叫wave from,或者叫那个那个叫安安VIDIA,叫WP。

就是说我一次次性发出一批工作对吧,把我所有的working thread全部吃满,一般来讲的话NVIDIA是32个工作同时发,然后呢那个AMD的话以前是64个对吧,但是呢其实就是说。

你如果能够把所有的thread全部用完的话,效率最高,所以这个CHK的意思也就是说哎我一个cluster,一个我这一批就扔出去了,所以呢他其实在这个cluster和这个那个instance。

之间又建了一层唱K的架构,但是大家不用特别担心这个东西,这个东西其实只是个加速架构,对吧好,那我的这个有这个唱歌的时候,当然这里面多说一句,就是在后面我们讲nut的时候,有个东西特别难理解。

叫cluster group,就是我们把cluster变成一个group,其实跟这个呢有那么一丢丢的异曲同工之妙,包括我后面会讲的就是说那个class group的话。

使得大家去理解NT产生了非常多的困难,我们尝试今天把这件事情讲清楚,OK那么其实呢每个instance的话呢,它中间分成一个个chunk,每个CHK里面包含了若干个cluster,没关系。

我先去看唱歌的可见性好,接下来我去干什么呢,诶我看每一个cluster的可见性,那cluster的可见性,每个class有自己的绑定嘛对吧,包括我可以做自己的这个那个depth testing。

我什么都可以做,诶这个时候呢我还能做什么事情呢,就是在cluster呢,它实际上是一个曲面,对不对,但有些三角形呢是在我的正面,有的三角形是在我的背面,对吧,我还可以把背面的三角形给干掉。

那么我能进一步降低我的三角形数量,然后呢,我的computer shader里面就会把所有的instance的,所有的乘客,所有的cluster,所有的三角形全部跑一遍。

最后呢我会输出一个最后可见的所有三角形的,一个超级大的index buffer,那他怎么办呢,他一上来会先分配一个大概八兆的这样的一个,伊森的buffer的这样的一个一个一个一个空间。

然后呢你们所有的这个walking street,就是你们去便利所有的这个instance啊,所有的这个这个class唱歌啊,所有cluster所有船口,你们只要这个船口最后可降了。

我就把你这个instance part,这个这个这个TRIGLE的信息index buffer p写进去,然后呢依次的往后去ding这个东西,为什么可以做呢,其实是因为就现在的这个GPU的话。

它实际上能支持,就是说在这个computer shader里面,我可以并行的处理很多的工作,但是呢我能保证它的血的运算,具有一定的原子性对吧,但是这个你要做的不好的话,他互相就会你等我,我等你。

但如果你写的他这个几乎是比较那个稳,就是比较工作量比较均匀的话,他们写的话真的是能够非常高效率的,往那个最终那个buffer里面去写写写写写,当然这里面有个细节。

就是说因为我的所有的这个instance的便利,所有的cluster的便利,实际上都是并行的,所以那个instrument buffer那个英特尔谁先写谁后写,其实可能是乱序的。

这种外序呢本身没有什么太大问题,但是如果这些几何的密度特别特别的高,那么你会出现什么情况呢,就是比如说啊啊在第一针的时候,诶,我同样是这些可见的物体,我的渲染顺序可能是啊instant1。

然后呢instant5,instant8对吧,但是呢我到第二针的时候,我可能变成了insert5INCENT8int一,那么这个渲染呢,因为z buffer它本身的精度啊,它还是有限的。

可能会产生一个z fighting,所以呢作者在他的那个presentation的后期会讲到,就是说诶因为硬件厂商提供了叫multiple multi director,扩对吧。

它可以锁死这个inn的绘制的顺序,那么a cluster绘制的顺序,因此CROSSC绘制的顺序,这样的话呢它能避免这种the fighting的现象出现。

但这个是一个非常小的这样的一个hack trick,不过同学们在做这个render的时候,其实特别注意一件事情,就是说我们希望就是在针与针之间的话。

我们一些渲染它的顺序最好是deterministic的,否则的话呢当这个几何的密度特别高,而且贴的非常近的时候,比如说啊我举个例子大家就知道了,比如说啊我们在墙上再加一层贴花的几何对吧。

他两个几何之间就非常的近,那么当你的这个相机离得稍微有点远的时候,那个z buffer的精度就不够了,那么你是先画那个贴画,就是那个想细节几何再画墙面,还是先画墙面再画细节几何呢。

那个Z会产生fighting的,所以他两个的顺序确实要保证起来,否则的话你画出来的东西它就是不对的,但这里面的这是一个非常细节的一个东西,但是大家如果在做真正做游戏的时候,大家需要注意这些细节。

所以呢这一步核心的就是说,我把所有的物体全部变了一遍,把它里面所有的COSER全部变了一遍,然后我把所有可见的传统customer,可见传口全变,我把所有的在这一帧相机下的可见的传统。

build成了一个超级大的一个index buffer,我111个pass把它渲染完,诶,这个是不是就实现了,我们在之前GPU driven里面讲的那句话叫做哎。

我们从JOEPRIVITI变成了JING对吧,而且这个calling是非常彻底和充分的,哎这就是这个刺客信条大革命,它最核心的一个一个渲染上的一个想法,这个想法说实话,在那个时候我们刚刚看到的时候。

确实是惊为天人,就是觉得哇塞这个老哥还是挺猛的,居然敢这么搞,甚至是会觉得哇这个这个会不会,这个导致这个CPU上的运算过过于负载,但是你后来发现就是说确实这样做,对于那种非常细密的这种高精度几何的话。

确实是效率最高的一种做法,而且呢这个也毫无疑问就是逐渐成为了,我们下一代这个rendering pipeline的一个,可以说是个标准解法之一吧,OK那么这里面其实有很多的细节了。

比如说像baha calling作者提出了一个想法,就是说哎我可以在一个cube上面去CODEC,就是说我有128个面,对不对,那你每个面对于我一个cube的六个面来讲,你到底是可见和不可见好。

那我有了这个cube之后呢,当我一个相机的视角过来之后,其实我就可以知道说,因为你这三个面对于我可见,所以你那个三角形的话,假设这三个面中只要有一个人的B特,是是是是亮的话,那这个东西我就是亮的。

因为你总共就是64个三角形嘛,所以说我六个6×64个,这个这个vector就能表达我三角形的这个可见性,这一点其实非常的重要,因为其实back is calling的话呢,用这个方法速速度是很快的。

当然了,就是说其实在NANA里面的话,好像没有用到这个技术,但这个技术我觉得是一个非常好的一个trick,所以其实呢这个就是我们这个最原始的就是。

cost based mesh rendering的一个思想,其实非常的简单对吧,大家想想哎,理解了就不难了,但这里面又引入了另外一个细节,就是说哎这么多的cluster。

我如果只是用wow fashion对吧,那我实际上那么多的几何层层叠叠的话,那后面那些几何画了不是全都浪费嘛,对不对,而且你虽然说我们说一个周末对吧,一个JING就可以把所有的现在可见的这个。

传染狗的可见,但是其实你背后藏着很多实际上是被遮挡掉的,这些cluster我也绘制了,这一点,其实对于rendering来讲的话是非常重要的,为什么呢,因为其实大家知道。

就是说如果没有做clusion culling,基本上所有现在游戏它的性能都差得一塌糊涂,真的就是啊当大家做游戏的时候,经常会遇到一个性能的bug,就是如果库存卡里没做,对对吧,那你会发现同样一个场景。

直接就帧率下降个级别是很正常的,所以说其实接下来一个很重要的一件事情,就是说唉对于那种彼此遮挡的这些几何的话,虽然你都在我的相机的视野内对吧,虽然你所有的三角形面都嘲笑我。

我能不能把你这个cluster整个给干掉,这其实是这个就是说啊,对于这种class based machinering的话,很重要的一个议题,同样的就是对这么细密的几何。

那我就做你的shadow map的时候,我的天呐对吧,shadow map大家理解吗,就是说哎他要从光的角度再去渲染一帧,那它的复杂度呢很多时候不是由材质决定的,因为那个时候材质不重要,对不对。

哎几何是直接决定了我渲染一个SHUTMAP的成本,那我怎么样在渲染它这个这么复杂场景的,shadow的时候,尽可能变得廉价,所以这也是就是说a cluster based rendering。

很核心的一个技术点,就是ACLUSION怎么去calling,这一点的话,其实一直到我们本节课要讲的重点,拿net技术的时候,这也是一个非常核心的一个技术好,那作者怎么做呢,哎其实在大革命那个时代。

他其实有一个非常聪明的一个想法,就是说我当前这个物体,我要去算他的这个这个这个东西可不可信,怎么办,我呢把上一帧他的depth,重新投影到我当前的相机位置啊,重新算一遍。

因为大家知道在那个depth buffer里面,其实我们知道一个深度,其实我们还知道它的XY,就是实际上我们就知道了,在这个物世界坐标系里面,我们形成了一个怎么说呢,这个图很难表达出来。

但是其实是一个像一个模样的,就每个模带深度对吧,这样的一个个的pixel呢,当我把它当我的相机位置换掉之后呢,这每个pixel其实可以重新,投影到我的新的相机位的,那么假设这个世界你的相机移动不要。

那么就是跳它是一个光滑的移动,第二件事情呢,场景里大部分物体都是静止的话,那大家有没有发现,实际上这个ACCA的话呢,实际上是可以重用的,这是他一个很核心的一个观察。

另外一个这个DEBUFFER可以重用,上一段代码可以重用,另外一个的话呢,作者呢他还想了一个trick,就是说我写了一个HEISTIC启发性的算法,就是因为我的场景里面有上万个,甚至是更多的这些物体。

因此对象对不对,我有一套启发式算法,就告诉我说哪些物体就是很大,而且它离我相机很近对吧,我就把它作为优先的酷睿,我先找到300个,就是最有这个可能性的这些aqua。

我先把它z buffer就是在我渲染出来,这样形成我的指导,然后呢桶把它呢就是当sample的,到我的512×256,然后呢我们再把上一帧的z buffer诶,把它REPROJECTION出来。

那上一轮这样的话呢,因为你只选了300多个那个物体啊,实际上你会是那个Z8手上面有很多洞的,对不对,诶他把上一段东西representation过来呢,把这个洞填一填,对不对。

然后这个时候我就用这个z buffer,我build一个HZHZ,大家还记得吗,就是说我的z buffer1层层的往上密铺,但是这个mp是很特别的,就是说我选择那个他的是应该是最近的那个Z。

也是最小的那个Z,也就意味着说你跟我的hey test,如果过了就说明你肯定是没有被遮挡,如果没有过的话,你可能被遮挡对吧,它其实是一个啊保守5G诶,那我就可以去做这个GPU上的直接卡里面。

因为我每个COSER不都是有绑定吗,对不对,或者我每个唱歌其实也有帮你,对每个音色也有帮你,实际上我很早就可以快速的判断出来,音色到底可不可见,如果伊森森的可见,那我的这个唱K是不可见。

唱歌是不可见之后,那如果可见,我在问我的classroom能不能可见,这个想象想象起来其实是有点抽象的,但是大家去理解它的时候,就知道就是他有个很巧妙的想法,其实他想法分成两派。

第一趴呢就是说我选就是我有一套启发式算法,选取三个最有可能去遮挡住别人的ACCORDA,把它先渲染出来,然后呢,我把上一帧的z buffer那个重新的REPROJECT一下,然后呢我就形成hey。

这样我在GPU上能快速的做他的哭声,但这个方法会有什么问题呢,哎作者自己也讲了,我相信聪明的同学们可能很快就发现了,就是说如果上一帧Z里面的有些物体,它在这其实它是高速移动的物体对吧。

那你在这一帧是不是就会产生问题啊对吧,那么这个问题确实是存在,但是据作者自己讲啊,说哎呀我这个虽然是in theory,理论上会有artifact,但是呢他说这个结果基本可以接受,但是呢我个人是觉得嗯。

反正你游戏已经发布了对吧,我就相信你了,那么当然到后面的话呢,其实大家也提出了一个诶更有意思的方法,叫two face accursion calling对吧,这个呢其实是啊。

当时和他们一起做研发的另外一个老哥,那个老哥他以前是个独立的公司,但是呢因为他后来被育碧收购了,他们两个两个团队会经常在一起协作哈,这个老哥的话呢。

他提出的就是说两次的accushion calling对吧,那怎么去做呢,他首先的话呢把所有的物体对吧,用上一帧的这个Z去给它这个测试一遍,那这样的话呢,就是说我对于所有的。

就是说那个通过上一帧的Z测试的物体呢,我把它快速的画一遍,其实那个时候已经就相当于,比如说我有1万个物体啊,我用上一帧再测试一下,我可能通过了,只有比如说啊100个,很多时候这个这个通过率其实是很低的。

大家想这个真实的游戏场景里面去,通过率非常低,大家想象一下,就是说在一个复杂的巴黎的整个场景里面,你你站在一个街道里面,其实你满眼看到的也就是几十个建筑,但整个巴黎城可能有很大很大的,这个上万的建筑。

对不对,所以呢唉我先用上一代Z,我去测试一下这个哪些物体可能可见好,我把这些所有可能可见的物体呢,我去按照当前的这个相机啊,就在当前的相机下,我跑一下干嘛呢,我形成我这一帧的新的Z。

那但是呢你上一周通过的物体呢,他的那个Z可能会产生很多的动,这个大家要知道第二个呢,他对这个Z的这个表达很可能是错误的,那怎么办呢,哎他这个时候用这个生成的Z啊,把所有钢材。

你认为不可见的物体也快速的测试一遍,注意啊,这个时候是用当前针下去测试的,他跟刚才那个用上一帧,那个强行的那个投影过来是不一样的,它是用当前的相机,用当前可能可见的物体的Z全部画了一遍,然后呢。

这个时候用这个形成的新的,这个这个depth的话,去测刚才被过滤掉了所有的物体诶,这个时候他就会发现一些新的物体又可见了,哎这个这个方法其实是非常巧妙的,实际上你可以认为就是说他用上一帧的那个Z。

做了一次提前过滤,但是这个过滤呢大家不用担心,它是一个保守过滤,也就是说你所有被过滤掉的物体在后面,当我在这个depth空间又填了一些东西之后,再被测一遍,这样的话呢。

其实我就可以省掉大量物体的可见性的测试,这个讲起来有点抽象,但这个方法的话呢,实际上是啊我们在做现代渲染的时候,很多时候大家会用的方法,这个方法的好处就是说啊它是准确的,就比如说在我的近处。

有一辆马车高速通过的时候,你不用担心说这个Z是有错误的对吧,你大不了就是少a rude的几个物体,你在你在你后面的测试中一定能把它画出来,诶这个其实是啊,当时呃另外一个作者提出来对这个方法来改进。

同学们需要花点时间去理解这个算法,那么但是呢就跟大家讲一下,就是对于这种所有的cluster base这种rendering的话,ACCUTION是一个非常复杂,但是呢又是非常重要的一个计算。

它的基本思想就是什么呢,我尽可能快速的低成本的基于当前的相机,相机位置构建一个depth buffer,这个DEBUFFER呢我一旦有了之后。

哎我就基于他beautiful beautiful high c,你可以认为就是我形成了一层层的幕布,当我拿到任何一个物体啊,任何一个cluster呀,无论你是用那个就是你是用什么东西表达了。

你最后肯定有个绑定对吧,我用那个bounding和那HZ,能够快速的在GPU里面进行测试,这样的话,我就能迅速的把那些大量看不见的东西给踢掉,所以呢这个Z的那个挡板其实非常的重要。

所以其实你可以发现他所有的这些算法,都是用尽可能低的成本,形成那个你想需要的挡板O所以这个地方的话,大家如果有兴趣真的去实现这个算法的话,我会建议大家两个算法都去实现一下,比较一下好。

那么其实呢对于这个two faces的OQUENT,COLIN的话呢,它的效果还是非常好的,就是这个老哥,他自己这是一个非游戏的一个案例,他就做了一个在这个行星边界,漂漂漂漂浮的一片,那个叫做那个啊。

我们叫做云小行星带,这里面有大概是啊,我记得是25万个这个小行星,或者是那个陨石,他这个呢这个他这个案例给的非常挑战,就是说陨石也是随时随地在动的,嘿他这个时候能够用这一套two pass的这个。

accution coming in的算法的话,能够实现一个非常好的一个效果,所以这也是呢,我觉得这个算法它其实在那个时代吧,已经被提出且被很有力的验证过了,因为真实的游戏场景的话。

我们动的东西的话呢应该到不了25万个,但是的话呢我的场景里的物体数量,可能还真的到这个数量,所以的话呢,这也是就是说LUCI算法的一个很大的优化,那同时呢在大革命时代的话,就是那个那个算法中的话呢。

有一个很重要的技术是什么呢,就是shadow,因为shadow这件事情其实非常的难,就是说刚才我这样,我刚才讲的就是shadow,当我们如果大家对真实的写过一个游戏引擎啊。

特别是你真的生成一个游戏级的场景的时候,你会发现就是casket shadow generation,在整个渲染pine中的话会占据非常显著的时间,它可能占据占据你前绘制时间呢。

比如说到1/10到1/5都不止,想想看这是很大的一个成本啊,那么而且他的很可怕的一件事情是什么呢,它只和你的几何复杂度有关对吧,也就是你材质上做任何简化,它不受影响。

而且呢我的shadow caster它的几何的进步,实际上要和我的这个camera space,看过去的精度是一致的,否则的话,你假设用一个低精度的几何去cast the shadow。

你投到那个高精度的几何上的话呢,那两个的他的这个depth信息是不能匹配的,你会产生很多很脏的东西对吧,这一点也会让他这个过程变得非常的expensive,其实我们后面讲到nine的时候。

shadow也会重点的去讲一下他的挑战,其实也就是在这个地方,那这个作者怎么去做呢,他其实思想跟刚才我们讲的cushion,calling的想法是一样的,就是说我要想方设法的在我渲染下的map的时候。

尽可能少的渲染物体,而不要渲染太多的物体,那怎么办,他呢,首先一个就是说他把上一帧的shadow map,里面的那个depth buffer重新投影成我们这一帧,但是它精度采样的非常低。

只有6464个pixel对吧,然后呢,我们把这一帧的这个这个就是说这个shadow的话,我会用它去快速的去进行一次卡里,把很多物体就用上一帧的那个depth,把它给裁掉了,你看这个老哥是不是很粗暴对吧。

但这件事情其实非常的重要,因为否则的话你想想看,我要把整个巴黎城,在光的方向再给你绘制一遍啊,大家想想这是casket shadow,大家记得他的最后一层,可能是方圆几平方公里的物体啊。

大家想想看这个是不是很要命的一件事情,所以呢这个时候我们要尽可能用这个,就是z buffer这个depth buffer,把它很多东西能挡掉,就尽可能挡掉,这样的话就是节约我的时间。

那么这一点够不够确实不够,这里面我还想提一下,就是他在那个大革命这一组里面,提了一个很有意思的一个想法,就是说哎当我相机去平视,我在我的camera space生成一个depth buffer的时候。

我对它进行采样,我把他的每1616个spring tel的话,我其实可以拿到一个他的,就是说最近的这样的一个一个一个depths对吧,我可以生成一个cube,那这个时候呢。

其实我就可以知道说对于每一个物体的话,你对于我这个就是这个这个其实它不是个cube,是一个四棱柱的这个东西,你到底跟我有没有焦点诶,为什么这件事要这么做呢,其实你会发现啊,就这个地方我要讲一个细节。

就是说之所以他这个方法,可以用一个很大的假设,就是说在这个游戏中的话,很多时候我们的建筑物是平的放在这,而人呢很多时候是走在街道上面,所以我的人一眼看过去的话,如果前面有一个比较近的物体挡住我的话。

那这个近的物体啊,他大概率不会受到后面那个shadow的影响,为什么呢,因为他shadow形成那个VOLUO,和我的这个camera形成的涡轮,它两个之间是没有交集,所以在数学上你可以知道。

就说那些shadow caster,实际上并不能有效的在我当前的这个相机位,投影到我的shadow诶,这个加上讲起来也有点抽象了,但实际上这个算法,我个人觉得对于这种向城市集的场景,渲染的时候。

它能够帮助你非常高效的剔除掉很多的物体,那这样的话就像刚才我讲的,就是如果我要渲染一个casket对吧,我站在一个街道的中间,这个街道在拐角,其实我前面的几栋房子。

它所形成的这样的一个一个一个切割面的话,它可以把大部分的后面的这个shadow caster,全部给过滤掉,那这样的话我的shadow才会比较高效,那大家看一下这个场景,对不对,大家回想一下。

在游戏里面,是不是很多时候我们是站在这个视角,所以你前面几个房子它所形成的depth,然后呢,在空间上会有一个无线投影的,这样的一个,一个,一个一个就形成这样的一个,就是一个一个四棱锥的一个区域。

那么我刚过来的时候,其实很多的就是instance的话,它的投影实际上是不可能出现在我的可见性的,这些追里面的那这些物体,当我去渲染shadow map的时候,我是不是可以完全跳掉。

比如说我在这个里面的话,那栋房子就是那个远处接的那头,那个房子背后的整个巴黎城,其实在算shadow的时候,我也不需要投影,当然了,如果你这个东西特别特别的高对吧,我的算法也能告诉我说,诶不好意思。

他还是会跟你有交集,但是呢能够达到那种高度的物体的话,在整个场景里应该没有几个,所以说那个这也是,我觉得,就是说他们在这个点上做了一个很深的优化,其实这里为什么要讲的这么细呢。

我在想就是同学们如果想去理解NT,他很多技术的设计对吧,包括他们和我们提出了非常那个复杂的,叫virtual map对吧,其实都是在解决,就是说这个在这个camera space。

在光的space如何高效的去渲染,能够把这么复杂的几何能够快速的做裁剪,只画我最有必要的一些东西,而且用我想必要的精度来绘制,这也是下一代的这个rendering pipeline。

必须要思考和理解的东西,所以我个人认为就是说ACCUTION的话,是这个下一代渲染pipeline,非常核心的一个算法模块,这个地方如果做不好的话,那就算你把几何做的再高效,它实际上也是很难渲染的。

非常好的对吧好了,我这句话是不是立了个flag,没关系,反正是我个人一家之言,大家可以不理我好,Ok,那这其实呢我今天讲的这个大革命的这个算法,实际上是啊。

我们所有的这个cost base的这个geometry,rendering的一个老鼻祖吧,鼻祖之一,至少我至少我找的是最早的一篇文章了,那么好,另外一个呢跟NANA的很相关的一个工作是什么呢。

叫做a visibility buffer,大家还记得我们前面讲rendering的时候,哎,最早的讲folder rendering对吧,那个然后呢后面讲的er rendering。

大家different shading,大家都觉得大名鼎鼎,对不对,那么visibility buffer呢,实际上是一种现在越来越,这个就是那个引起大家关注的一个新的渲染。

PAPI这件东西为什么这么重要呢,给大家解释一下,首先的话呢大家回顾一下,在我们前面课程中讲到低分的设定里面,讲到G8分,它实际上在解决什么问题呢,就是说哎我们一个场景放的是。

如果我们用最简单的古老的这个shading对吧,那么我们叫forward rendering,那其实很多的几何是彼此被遮挡的,但是呢我在forward shading的时候呢。

唉我的这些像素他都要进行这个什么呢,都要进行一次完整的texture采样啊,什么的采样全部做一遍,然后呢还做一次光啊,就变得非常的复杂,所以大家就发现,这里面其实是有很多的计算的浪费。

其实另外一点也是我们的defending,最著名的一个点,就是说诶我假设有很多屏幕,screen space动态的光源对吧,那我每个光源所有影响到的几颗,我得再给它绘制一遍,还得叠加上去。

这个过程变得非常的复杂,那differ shing说,哎我来解决这个问题,他把渲染分成了两步,第一步呢把所有可见的几何,他的诺他的那个法向啊,他的这个这个这个这个texture呀,他的diffuse啊。

那个sparkler roughix啊,包括TG的这些数据,全部打到了一个screen with buffer里面,但注意这个buffer里面的话呢,它只会指你可见的这个pixel。

然后呢我这时候根据你的光,我去shading这些pixel对吧,那这个的话就避免了很多不必要的pixel CD,这就是而且呢刚才如果你有很多动态光源的话,它可以在上面无限的去叠加对吧。

如果你是talist rendering的话,你可以在每个屏幕的这个小的tale里面缩,我会受到比如说两个光源的影响,三光源的影响,我可以实现,这个就是最近很火的一个叫什么。

thousand lies对吧,上千个光源在那里动来动去也没有什么问题,那这就是differ shading,之所以before the rending大家觉得比较好的地方。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是呢differ shading呢,它其实这个pine大概是这个样子,但是它会产生一个比较大的问题是什么呢,它在中间过程中啊,就是它会产生很多的,就是跟屏幕的分辨率一样的中间数据。

比如说你要存normal,你要存阿B,你要存roughness对吧,就是形成了一个叫G8er,g buffer本身是很肥的,很大的,我们叫做feat g8er。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么这个发七八分呢,就是每个pixel我要存这个多少,可能是将近几十个,甚至是接近100个这种BT的数据,那其实大家知道就是在显卡中的话,我们的cash miss是很重要的嘛。

那如果你的buffer过大过肥,比如说我们是4K4K屏的话对吧,那么多的像素,然后每个像素我要存这么多数据的话,那这个buffer光写一下,光去fetching一下,它就很废。

所以呢这其实是这个differ shading的话,它在现代的绘制中,有的时候大家很诟病的东西,特别是大家如果做那个就是手游的时候,会经常讨论的一个问题,就是说因为积分确定用了G8分对吧。

他的那个FB是非常厉害的,所以呢我们不能够直接上different shading,我们要用td base方法,再加上1hack,能hack出来一个类似different shading的方法。

这其实也是这个原因导致的,就是因为手机上的那个就memory的那个带宽,是很紧张很紧张的好,那different shading的话呢,其实他真正最吃亏的地方在哪里呢,是在类似这样的一个场景。

大家看到这个场景里面,它有很多很多的三角形,这个三角形有个特点是什么呢,就是说你在屏幕上找一个点射过去,因为这些植物的叶子它会层层叠叠,层层叠叠在一起,因为呢我没有办法保证,这些植物的叶子。

是一定是从优先从靠近我的相机开始绘制对吧,如果他优先从我的靠近相机绘制的话,那其他的pixel都会被那个就是说哎,early z把它干掉,所以下面的那些挡在下面的那些叶子会看不见。

那我不会产生性能的问题,但实际的绘制渲染的话呢,我并不知道我的这些几何提交到显卡中的顺序,对不对,就不受我控制,那好了呀,那就可能会出现,就是说对于屏幕上一个像素,我可能会绘制十几次,哎。

这个设计是什么概念呢,就是对每一次这个pixel的话,我都要去把他的texture sample出来,把他的什么abele roughness normal,包括把它转成local space对吧。

然后呢这个而且呢还要把它写到哪呢,这这一大堆这个texture sample运算本身就很废了,对不对,大家还记得我们前面讲过,每次take some something是什么呢。

是一次TRAINOR差值,就是说首先要做个呃,你要找到对应的map对吧,在mp上下两层mp之间的差值,每个mp内部是什么呢,是一个binary差值是1trainer差值,对不对。

我要做若干次trainer差值,算出他的这个这个color呀,他的那个那个那个ABEL啊,RAGHNESS这些数值,同时呢哎我这些乱七八糟的数据算好了之后,将近100个BT的啊。

将近100个beat的这个数据我要往哪跑呢,我还得写到那个G8份里面去,那个G8份每次打开来往里面写一下框,一创数据好,下一次在绘制的时候,那个周会来了,我再来一遍啪,那其实大家知道就是说也许AU计算。

对于这个现在的这个GPU来讲还OK,但是呢你大量的这种texture sampling,再加上往基本方面读写这个啊,这个写这个数据实际上性能就会变得非常的慢,所以对于像foliage对吧。

像你比如说看到很多植被的情况下,那你的这个这个这个偶尔做是非常严重的,这个时候传统的differ shading的方法,它就会产生巨大的问题,哎这个就是很有意思的一个点啊,那这个时候怎么办。

就有猛男横空出世了,他说来我们提出一种新的方法,叫visibility buffer对吧,他这个自称是一个cash friendly的一个方法,去这个这个去优化这个differ shining。

这个最早这篇paper是我们查到的是2013年,他的方法是什么样子的呢,唉其实非常的粗暴,真的这个超乎大家想象的粗暴,他说呢我在这个我第一张渲染几何的时候啊,我不要像different trading。

我把你所有什么什么材质啊,这么normal啊,这些全部采样,我觉得太费了,你呢就把几何给我汇上去,对于每个pixel呢,我在你的这个buffer里面只存几件事。

那个比如说你的primitive id对吧,你的incident id放在这,当然它有很多有很多细节的,比如说这篇文章是原作者,他说我把哪些东西是有alpha mask的,哪些没有阿sa mask的。

我也把它区分开了,他其实就表示两种不同的材质,就是有的是带阿尔法master的材质,我要走单独的设置通道,如果其实其他这个类似于,我们后面真正的就是说啊。

就是叫我们叫产品级的这个微visibility buffer,based rendering的话,你们用的这个mature id,但这里面就可以理解成就是一种mature id吧,然后呢。

他把它packing成一个32个比特的UINT对吧,然后呢,我就把它直接打到这个screen speed buffer里面去了,大家看到就是这样的一个,比如说我的这个球这样的一个简单的场景诶。

我最后打出来的全是一堆,这个叫instant index啊,全国index啊,还有这个material index,Material id,诶,你就形成了这样一个色彩斑斓,毫无这个可读性的这么一个东西。

好这个pass渲染完之后,哎我接下来要做的事情怎么样呢,我要做shading了,这个设定就非常粗暴了,他呢首先拿到这个这个这个这些insert id,拿到全国id之后,他干什么呢。

诶我可以把这个船给的四个vertex全部拿到,对不对,然后呢我知道camera所有的参数,其实我可以把这三个三个传狗啊,三个顶点投影到屏幕的空间,然后呢因为这个点呢我也知道它的深度。

而且我也知道他的那个就在屏幕空间的,XUV对吧,所以我也知道他在那个我可以反算出来,他在那个三角形中间的重心坐标,然后呢好那我把三个顶点的UV,我也知道我三个顶点text3朋友都能拿到对吧。

那我去通过重心坐标插值,可以查出我这个像素点,它应该有的这个比如说那个ABEL才出来,texture应该是什么样子的,RAGH才出来,应该是什么样子的对吧,spec才出来应该是什么样子的,然后这样的话。

我接下来就可以开始对它进行设定了,因为我知道光在哪里嘛,对不对,那其实这个地方大家觉得就是哎呀,我的天呐,这个太粗暴了,因为以前这些工作啊,全部都是由rust rizer和vertex shader。

做掉的对吧,所以vertex shader把每个顶点的数据算好之后,哎,我在rust riser的时候,把这些数据插值到每个screech pixel,他老人家说你们都不要做了。

你只要在屏幕上打出了所有的这个这个,几何的id信息,我自己手动的去取顶点的数据,对它进行插值,然后呢我再进行设定,这个听上去好像非常非常的费对吧,但事实上呢他的速度比大家想象的快,那为什么呢。

因为其实很简单,就是where is buffer里面取每个顶点数据的时候,其实它的CCHHOENDS是很高的,他很多时候就在那一小块子和你去取,那么第二点呢,就是因为你可以发现屏幕上。

你看到一小块几何对吧,它实际上很多时候都是同一个三角形,所以说你是反复的取那个三个顶点的数据,那这样意味着什么,它的KASHMISS率是很低的,但我在前面跟大家讲过,对性能影响最大的是什么。

是CASHMISS,对不对,所以的话呢但这一点它带来的好处是什么呢,就是说对于屏幕上,无论你多少层overdraw的这个节目水,你在前面真正付出的代价,就是打赢这个花里胡哨的ID。

但那个计算量是极低极低的,等你把这个ID打印完之后,其实我在这个shading pass的时候呢,我绘制的永远是你屏幕上有多少个像素,我做多少次采样,所以我几乎是没有over做的这个cost。

唉这个其实就是with buffer一个很核心的想法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么这里面的话呢,就是这是那个另外一篇paper里,他讲了这个整个的PAPI对吧,我的这个几何放在这,他这边为什么没有网格,就告诉你说这种情况下,我只要关注几个,你的材质是什么呢。

我其实不太特别不是特别在意,然后呢我把你的这个就是PROPD传go的id,包括你的material id全部打印上去,然后呢在那个就是后面shading pass的时候。

我会做一个geometry reconstruction对吧,我把你的这个三角形的信息全部拿到,然后呢,我超值出来,我这个像素点的所有所需要的这个shading information。

然后需要ly lighting,那么这个维斯比巴尔这个方法呢。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

哎大家去理解它呢,实际上它是一个非常有意思的东西,就是说它可以和传统的低分的设定结合在一起,这一点其实非常的重要,就是说在NANA中的话,我们也利用了这个特性,因为比如说就是说在我们的渲染中。

如果有些几何,我还是用了传统的different trading对吧,它几何的over作并不是很多,但是呢有一些几何他真的就是这个密度太大了,我们就需要用维CB的buffer的方法。

那我怎么把两种完全不同的绘制的东西,混合到一起呢,哎他这里面就提出了一个解法,就是说我首先呢在这个with a bility buffer,这个pass的话,我还是输出了vivid buffer,诶。

我我有一个叫G8分,这个pass这个或者叫material pass,我把根据你的这里面存储的这个instance id,传个id,我把你的这个你要的那些什么啊,bile啊,SPECER啊。

那个roughness,这些数据全部还是打在这个FRAMEBUFFER,打到你的g buffer里面去,然后呢,你那些走传统管线的同学,是不是也去写了G8份呢对吧,反正我有我们的,我们有Z8分嘛。

所以不用担心他们的数据会产生这种唉,不必要的这样的一个一个冲突,最后我一上光过就是lighting pass的话,我完全不care。

你这个g buffer的数据是来自于这个via via via buffer,这个pass还是来自于传统的pass诶,我给你直接上光,整个场景就渲染出来了,其实这一套架构的话呢。

在早期的就是visibility buffer based,render里面是挺常用的,比如说在有的游戏情里面,我去渲染这个植被,就是我们叫做foliage对吧,那种灌木丛啊,小树林啊。

树林上那么多树叶啊,哎我用的就是visibility buffer的这个方法,因为大家可能想象不到,比如说我要绘制一个丛林,forest的这样这样的一个一个场景的时候,其实啊你对它进行这种啊。

就像素卡里是很难看的,因为你说那棵树挡在前面,他到底是透明还是不透明的呢,你觉得嗯他可能是不透明的,但是那个树上树叶上有很多洞对吧,那后面一眼看过去,那几十棵树,其实都你并不知道哪棵树叶被挡住对吧。

这个时候就很很很麻烦,那怎么办,像这种密密麻麻的这种复利计的,这种情况的话呢,我们一般会倾向于用VIVITY发布的方法,去节约这种overdraw的这种cast,但是呢当我画那个主角对吧,主角很帅。

我们画主角,我们画那个一些近出的一些物体的时候,其实你没有必要用无zz buffer这么复杂的方法,你怎么办呢,哎你就可以用传统的different shading。

然后呢最后在g buffer那边汇合,我最后给他来一个final的lighting,这个呢其实也是一个非常重要的pipeline,那这个呢也是我们去理解nmt rendering的话。

一个很重要的基础对吧,所以我们今天在讲这一课的时候呢,我们不会就着那就讲,我们先把大家把这些基础知识全部建立好,所以呢这是一个就是vcb buffer,这个方法的一个很核心的一个思想,那么这个思想呢。

其实他当然有很多的细节需要处理,其实其实你用wily buffer去做rendering,还有蛮多的细节需要处理,我这边只举一个简单的例子,就是说哎我们以前做texture的时候,我们要算他明白对吧。

以前是在那个就是啊vertex shader里面做完之后,rus rise它就自动给你生成了DDXDDY,那么就是说当我们做texture sampling的时候,我调硬件的API的话。

它自动会帮我选择正确的密码,但是当你只是把这个船狗的id,打印到那个像素的时候,我怎么知道他DDXDY呢,其实在那个就是说reb buffer render的时候,我还得做一部额外的处理。

说哎我知道这个点在这对吧,我得根据我那个小三角形的三个顶点UV,我把它投影到screen space,这样的话其实我就可以算反算出来这个UV的话,就是这个点的这个这个pixel。

他的那个UV的在screen space啊,注意啊,是不是在几几何空间,是在screen上的梯度到底怎么样,这样就能够告诉我说,我到底该采mini map的哪一层的运算,这里面的细节我就不展开了。

但是的话呢大家注意,就是说,如果我们自己去写这个via visibility buffer based,rendering的话,那么就大家一定要注意这些细节。

否则的话你生成的结果会有很多的artifact,就像这个图上给出来的说,诶你在这个凳子的拐角有看到很多的小白边,但实际上是因为它两边的密度不匹配,导致的这样的一个问题。

所以呢其实这个visibility buffer rendering,他其实对于这种非常密集的这种,overdraw的这种情况,比如说几何特别的细碎很多小几何,而且彼此之间层峦叠嶂的这种状态的话。

他是一个最好的解,其实原作者当时给了一个sample,就是对于一个有800万个三角形的这样的,一个场景的话,他会发现,就是说当你的屏幕的精度越来越大的时候,诶你走这个visibility buffer。

它的性能就会遥遥领先于deer shing,但是这个他这个测试做的其实有点早了,距离现在已经有78年了,其实我很好奇啊,其实对于现代的显卡来讲的话,我猜这个差距不但没有变小,可能会变大,为什么呢。

大家还记得我们在那个课程中讲过,就是说哎我们的就是那个显卡的算力,很多时候是这样上去的对吧,但是呢我们的memory的这个速度很多时候是这样的,他两个是不匹配的。

就是对于visb buffer这个方法来讲的话,你的算力越强,它实际上它的优势就会越大,哎,这也是为什么在我们后面要讲到,NAS的绘制的时候,它就会直接采用了这个机制。

就用vivisibility buffer的方法去shading,最后我渲染出来的这个NANA的这个几何,也是这个基础,所以呢这也是我们讲NNT非常重要的一个基础,那基本上讲到这儿呢。

我们算是把这个就是NANA的两个前导的知识点,给大家讲清楚了,接下来呢就进入到我们今天的神坑了,就给大家讲讲NANA到底是怎么做的对吧,包括他自己提了一个非常大气的名字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

叫virtual geometry,待会我跟他讲一下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

22.GPU驱动的几何管线-nanite (Part 2) | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV17G4y1x7VX

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

欢迎大家回来,这个我们就开始讲我们的virtual geometry,none night对吧,这是他自己官方给自己贴的标题,其实从这个标题我们就可以看出。

none night这个团队的话确实是野心勃勃,那首先讲它要解决的问题是什么,实际上的话呢,这个是我从他的那个官方的那个塔,叫做journey to the nut中截的这张图。

我个人还是蛮喜欢这张图的,因为其实从我开始做这个就rendering开始啊,其实我们是每一个做渲染的人,脑中都有一个梦想,就是说我们希望在计算机的世界里面,还原真实的世界。

但如果大家真的观察一下真实的世界,你会发现哇这个大自然实在是太美了,我我以前经常举了一个例子,就是说你在海边看那个浪花,去拍拍击那个那个海岸,特别像这种岩时代,你看到那种无穷无尽的那种细节的时候。

你就能知道说哎呀,我们的渲染,其实离这种realistic真的还是非常的遥远,这其实是所有的做渲染的同同学的话,心中的一个梦想,就是我们也希望达到这种,就是我们叫cinematic。

就是电影级的这样的一个精度,这其实也是所有实时渲染的人,他无论是做硬件的还是做算法的,大家心中的这样的一个梦想,所以其实none night,它就是这个作者他一直在思考的问题,就是说我们怎么样子。

在这个游戏引擎的pipeline中,实现这种无限的几何细节,那这件事情的话呢其实啊非常的复杂,所以今天呢我再去讲nana的这个技术的时候,其实我遇到一个非常大的挑战是什么呢。

就是说啊这个技术我读了他的所有的这个,原始的这个文档,我发现就是说其实他比较晦涩,就是他讲的这个东西的话,其实有很多的细节,很多关键性的东西,其实你要花很长时间去猜,所以呢这是我自己尝试整理了一下。

就是今天我讲的第一部分,我想讲就是none night,他最开始的思考就是all of you,就是他为什么选择了这个solution,第二个呢,第二part也是今天的重点,就是说也是nt最核心的。

就是说它的几何到底是怎么去表达的,而且这个几何你没有两个东西,特别容易混淆,一个就是诶,我去cluster构建了它的l o d体系对吧,哎后面他还做了一个叫b v h这个东西,这个bbs他讲的。

我个人觉得是最没有讲清楚的部分,但是后来逼得我们看了很多的代码,才能能猜出他大概是怎么做的,然后呢接下来就讲,如果我们有这样的一个表达之后,诶,我们去怎么去做它的渲染。

这里面其实有很多的很关键性的一些实施,比如说基于软光上化,在这里面起的作用对吧,他是怎么去用这个vivisibility buffer的技术,做shading,因为nat是一个实战型的。

这个游戏引擎技术,所以它的材质会非常的复杂,那么多的材质它怎么处理,还有呢就是说诶,我的材质就有那么多的材质,那么你有了这么详细的几何,接下来另外一个挑战,刚才我在反复强调的是什么。

就是如果你的几何做了足够的细,那你在做shadow的时候,你也就更头疼,因为你的几何的complexity在急剧的增加,所以其实这个时候在虚幻五里面。

提出了一个很重要的技术叫virtual shadow map,我个人觉得这个技术也是非常了不起的,一个技术,那最后呢,其实我个人觉得在原作中讲了大量的什么,我怎么去做streaming啊。

怎么去做压缩啊,我个人觉得那可能是更多的是一些,implementation detail,所以呢当然我会点一下,但是我希望今天的重点是,能够把几何的representation跟大家讲清楚。

这个也是啊倾尽了我们课程组的权力吧,希望小伙伴们不要跟我们砖头,如果讲错了的话,也欢迎大家给我们更正好,那我们先讲nana它到底是怎么个源头,其实呢我个人去理解这件事情。

我首先想到的一个词就是virtual texture,因为virtual texture的其实是啊,如果我没记错啊,是这个游戏引擎的发明者对吧,那个哎叫什么来着,突然想不起来了,对。

反正就是写quick的那个老哥哇,我的我的我心中的神,我居然忘了他叫什么名字了,这个实在是太过分了对吧,那么那个就是他呢提出来的这样的,一个一个一个核心思想,就是说他说呢,我们在一个真实的游戏场景里面。

有很多的物体,每个物体都有自己的tt,这个text数量是非常非常大的,我没有办法这么多texture全部装入内存,存也不可能哦,也谢谢大家在弹幕里提醒我啊,对john k对,然后哎呀。

这个罪过罪过大神的名字我都忘记了,对这个确实是最近脑子里填的东西太多了,ok john camer确实非常了不起,就是他在我如果没记错的话,好像是在quick 3的时代,还是那个他提出了。

就是说应该是q3 之后一点,他其实是virtual text思想,每个物体有大量的tt,这text如果全部加载的内存,显存其实都会炸的,但是呢我能不能给一个budget。

就是说在当前的我的这个相机的位置,我能看到的世界,其实根据近处texture的精度高,远处texture精度低,我实际上可以形成一个texture的这样的一个,a clip map。

那么我可以在一个限定的八gt里面,把我当前view下的所有需要的材质的texture,全部给他cash起来,那这样的话,实际上他就提供了一个unify的表达,去表达所有的材质。

那这样还有更大更大的好处是什么呢,就是说大家还记得我前面讲的传统的render,pipeline里面对吧,我要不停的,我每次换一次材质,我都要切一次他的这个render dd,对不对,我要换一下哎。

我设置我的ab to text是什么,这个这个这个这个这个diffuse texture是什么,对吧,我的那个spectre text,什么那个roughetexture是什么。

那这个东西其实叫起来就很麻烦了,对不对,那如果我把它全拍到了一个巨大的versity,texture里面的话,诶我至少在材质切换这一趴,我一次性就搞定了,这其实是个非常了不起的一个想法。

那个turn rendering的时候,其实tern rendering,实际上用的也是这个virtual texture这个思想,所以这个这个方法呢,实际上对于啊游戏引擎来讲的话。

是一个非常elegant的一个一个一个solution,真的非常的美,非常的美,就是啊大家如果搞系统架构的人的话,就会感受到这种就是这种系统架构之美吧,或者是算法之美,确实他是非常了不起的一件事情。

所以呢我not net的作者,他就在这是我盗用他的p p t啊,这里面我用了一部分他的原始的p p t,就是说他的梦想是什么诶,我能不能够把几何也virtualize变成一个virtualize。

geetry对吧,也就是说我因为我知道在screen space,在我的屏幕上有多少个像素,我的几何数量不可能超过我的像素数量,所以我每一刻,我只要渲染了几百万个三角形就可以了,对吧。

而且我的周末要尽可能简单,但是呢这就要求什么呢,我要对这个几何,这个就是他有个方法能够进行filtering,能够进行进行处理,而且我一旦我达到了每个像素,一个三角形的话,其实我也达到了fmc。

就是说电影级别的这种画质,这就是他的一个梦想,但是真正的挑战是什么呢,就是说其实几何的数据,就像我前面在讲到那个lumen的时候,反复强调一件事情,就是什么。

哎呀几何的数据是一个irregular data,对不对,它是一个就是不是uniform data,那这个时候你对他进行各种处理,比如说这个ping啊,loading啊对吧。

你比如说你的一个index buffer,他可能说我在画一个mesh,他可能在verse,八经跳到了一个非常远的地方对吧,你只能把整个vb搂进来,你不能把它一段段的load进来。

大家想想是不是还有什么呢,还有那个就是说诶我的几何,我的l o d0 和d一的那个match,其实彼此之间可能没有关联性对吧,它是两个完全不同的mesh,当然了。

你可以说有些vertex 5可以reuse,那我可以就同一到vb,但是两道不同的index,但是那个它的filter其实是不连续的,所以jg ree其实是非常难以进行filter,为什么filter呢。

所以大家想要texture对吧,近处你看到非常的细,到远处哎,越来越熟越来越熟越来越熟,对于这种有风的data的话,你是比较好去过滤的,那这里面可以好filter的数据有没有呢,有啊对吧。

大家还记得我在讲入门的时候,为什么我大吹特吹,sdf这个东西确实很很酷啊,就是因为sdf它可以过滤啊对吧,你可以对他信形成各种各样的密码,但是呢sdf实在是太粗了,我没有办法在它直接进行绘制。

那么我还有别的什么方法呢,可以用voxel的方法对吧,用像素的就用那个vocal,就是vocal,不要叫体术,对体术的方法去对它进行表达,我还可以用什么呢,point cloud floud是什么呢。

就是说啊大家有没有用过那个scanner,就是那个呃3d scanner对吧,其实3d的scanner,它扫出来的其实原始数据就是点云,我们为什么看到那么漂亮的几何,它其实是基于点云重建的。

那么这些数据呢诶好像是可以filtering,所以作者呢他就在他思考他自己呢,他把这些东西都全部过了一遍,其实啊我我个人还是蛮欣赏他的工作的,就是说他在决定做nana的这个方案之前。

其实是便利了几乎所有的可能性,比如他讲的worko对吧,那worko呢,这个东西呢确实是一个非常uniform的表达,当然works so有两个很大的问题是什么呢,第一个就是说它的本身的数据量。

其实还是很难压下去的,特别是如果你想表达那种非常高频的in的,这种边界的话,那works slide表达,其实他就要求那个works的精度很高,实际上啊它的数量还是惊人。

诶他的这个数据你对它进行filtering啊,进行处理啊,就变得非常的费,大家还记得我们上一节课讲,len讲全局光照的时候,有一个基于sparse orchestre的方法,去做gi的那个方法。

你有没有发现我讲的那一趴的时候,我讲的就非常的简单,非常的跳,为什么呢,那个算法好像我们没有找到他的source code,我们一直很担心,那个算法自己实现起来会有很多的坑,为什么。

因为他对这个世界的表达太复杂了,那么其实另外一个呢,我个人觉得这是作者非常重要的一个观察,就是说其实现在我们的整个,比如说艺术家的pipeline,比如说你用max maya对吧。

zbrush生成的所有的资产,他都不是基于worker的去表达的,那么如果我今天为了我实时渲染的目的,我要逼着你把所有的asset资产,变成worker li的表达的话,那这个成本是不是很惊人的。

大家想想看对吧,所以说其实也是基于这个原因,虽然worko的表达,有非常好的这种filtering的个性,你甚至它的密铺啊非常的方便,但是的话呢作者到最后还是把它by pass style。

我个人觉得就是存储是一回事,但是这个就是说不你对传统pipeline呢,就传统艺术家的管线的工作的,实际上是啊致命的对,因为我们自己在做一个心情嘛,我们非常清楚的知道一件事情,就是说你必须要尊重。

那么第二种方法呢,其实也是,现在这个就是说gpu猛推的一个东西,就是说比如说我们在看在这个10年之前,我们就提出了这个jb shader对吧,我们提出了这种mesh shader这些概念。

就意味着我们可以on the flight,增加很多几何的这个这个这个就是精细度,以前那个叫什么whole whole shader对吧,还有dman shader这些很奇怪的词。

说实话我到现在都很痛恨这些名词的命名,我觉得明明一个我能懂的东西,结果他名字一命我就不懂了,那他其实核心要解决的问题是什么呢,就是诶我有一个粗的集合,我可以在软碳。

要用类似于这种subdivision的方法,就是把这个几何呢给他再继续细分,subdivision的意思就是细分曲面嘛对吧,我可以用各种各样的样条啊,各种各样的控制点的方法。

可以把它几何面变得无比的光滑,其实这种subdivision faces啊,就是这种几何,实际上呢它有几个特点,第一个就是真正在啊,如果没记错的话,在电影工业里面用的是特别特别多的。

那么那时候你看到的很多几何,它都是a4 边形面,大家想象我们渲染的基本上是三角形对吧,但是哎如果你想用subtivation的话,他说你得要用四边形面,那么这个四边形面呢,实际上在我们的艺术家。

在做这个一些精细的模型的时候,他一上来全部用的都是四边形面,帮助他们造型,对这个跟大家理解可能不太一样,那么好了,我有这样一个四边形面,作为一个control points的话。

那我其实可以形成一个cage,然后呢我可以形成很多很细的几何,那么这个时候呢哎我对它进行细分的话,我就会形成很多我们想要的那种,光溜溜的几何细节,但是呢作者这里面。

他讲了他这个subtification的很多的问题嘛,我个人觉得,其实如果我要去实现一个,像nat这样的技术的话,最卡住我的东西是什么呢,你的subdivision呢,他只能不断的去refine。

比如说美术做一匹小马对吧,他做了一个5000个面的,这个马的这个这个原始版本,我可以把它all the way of sampling到100万个面,没有问题,但是如果这个小马离我非常非常远。

我希望就是几百个面就表达的时候,诶他subdivision不能够往下进行,当三,那这个你会发现就是在not net实现中的话,它每一个对象它其实可以all the way,减到100多个面。

甚至可以减减到一个imposter,这一点上,其实当我在大规模的应用这个技术的时候,肯定就会有问题对吧,所以这也是作者,他自己就是pass掉这个方案的一个,很核心的原因,那么另外一个呢,这也是啊。

我们在这个图形渲染领域里面,讲了很多年了,就是a displaced map啊对吧,这些这个这些这些技术,我可以在一个一个cross的cost的三角形面上,增加很多的几何,这个方法好不好。

当然非常好了对吧,但是作者他就说,如果你要用这个方法去做一些硬表面的时,候,你那个design map是很难去设置的,他说你做出来做这种organic的,这个方面的效果是非常的好。

而且呢它确实可以做ft,但是呢,如果你要表达一些非常硬的一些东西的时,候,它很难,另外一个就是,假设我拿到一个很精细的几何,我怎么去生成一个比较好的design map,这本身呢还是需要一些运算的。

但是这一趴我个人觉得是啊nana的这个技术,大家现在debate最多的东西,如果大家关注最新的这个,nvidia的发布会的时候,你会发现他四零减显卡专门提出一个东西,叫做啊叫叫叫啊。

应该叫michael mash吧对吧,其实也就是说mv的同学还是在猛推,就是说诶基于这种这个gpu的方法,我自动的把你的几何加密,然后呢我还可以在上面做retracing。

这套方法就是不要再用你那么复杂的,哪来的那套技术对吧,所以我觉得其实在未来的10年的话,就是到底是nt这套方法是会成为王者,还是基于硬件的对吧,我还是用这个几何,用硬件去加密几何对吧。

这里面我当然可能用的是map,可能用的其他的技术,然后呢同手环的兼容retracing啊对吧,更复杂的一些光照啊,这个地方是大家,我个人认为现在还没有决出这个生死的,这样一个战斗。

我感觉是我看得非常清楚,就是两派都在这个快速的往前走吧,所以这个呢当然作者会认为,这个方法其实不是特别通用,那么最后一个作者就是这个a提了,提到了就是说诶point in the base的方法。

我渲染结果怎么样,首先pinbase方法做filtering是非常方便的,但是呢,如果你要达到这种我屏幕绘制进度的话,其实他其实那个point of running是在屏幕上叫spring。

就是我打一个个的小小小disco上去对吧,那实际上对于每个像素的话,很可能有很多的overjo,而且你要达到一个比较高的精度的话呢,那个效果其实并不是特别好,其实也是比较大的问题,所以的话呢。

作者分析了这些的表达方法之后,作者说,所以呢我的选择是很明确的,我要选择三角形,因为三角形呢是大家最熟悉,最成熟的一种几何表达形式,整个的这个content pipeline。

就是所谓的比如3d max maya zbrush,这些工具全面支持对吧,另外一个硬件上对他的支持,也是最最成熟的,所以呢它的整个那个无限几何的解决方案,都是基于三角形构建的,所以作者做出这个选择。

这也是none night的一个foundation,那既然我们选择用三角形,那这个几何到底是怎么构建的呢,哎这个真正难的问题就来了,就是在nt里面几何到底怎么去表达好,那其实呢他这他这里面。

作者提出了一个一个一个思想,它的原作讲的是说诶我这个几何数量,int数量可以持续增加,但是呢我希望我绘制的三角形数量,不要跟着它持续的增加,因为为什么呢,其实我个人的理解是这样的。

就是说你无论增加多大的场景复杂度,在屏幕上你的像素数是一定的,对不对,那么好,你有多少个像素,原则上一个像素对吧,一个三角形或者两个三元就够了,那我其实就可以算出来说,在任何一个view下。

你应该绘制多少个三角形,所以说我们有没有可能像virtual text一样,就是根据我屏幕的这个精度,决定了我的这个geometry,诶这个cing的精度,这两个时间能不能建立一个对应关系。

这其实也就是拿来一个,最最核心的一个思想好,那我们有假设有这么多这么细密的几何,我们怎么去表达它呢,诶他首先第一个思想就是说,其实跟刚才我讲的那个就是啊,class based rendering。

我对这种细密的几何,我把它分成一个个的cluster对吧,这是我们的课程组的小伙伴自己做的啊,这个原作没有,我们自己搞了一条dragon,然后呢我们把它分成了无数个cluster。

用的是nana一样的算法,你可以看到这样的很多的cluster,好,这个方法很简单,对不对,好,我有了这样class的表达,make a cluster,比如说是128个三角形组成的,对不对啊。

接下来我就可以做一件很淳朴的事情了,我们这个这也是nat,我个人认为是非常强的一件事情,就是说他的技术可以实现一个叫view,dependent,lo d transition。

就是说对于这样一条dragon,它是有240万个面构成的,对不对,但是呢哦是对2400万的船购构成的,那么当我的相机去看它的时候,我可以让它实现,在近处的这个显示的密度非常的高,但是呢稍微远一点点。

它这个每个coser的精度就会逐渐的降低,这样我能极大的节约我的面数,这一点其实啊也是它和刺客信条那一做的,那个技术一个本质的区别,在刺客信条那个技术里面的话。

它每个instance l o d level是锁死的对吧,你不可能在一个instance里面,每个caster用不同的l o d,但是呢在nt里面他真的是实现了。

就是will dependent这个l o d的transition,这也是他最引以为傲的一件事情,同时也是他整个算法中,我个人认为最复杂的一部分,因为待会我会介绍几个好几个概念。

这个这个概念在原始的这个报告中的话,那绝对是神坑级的这样的存在对吧,但是大家记住一个概念,就是说not that它能实现就对一个物体,一个inst,它的每一个它的cluster会切到不同的。

这样的话能够实现对这个屏幕空间的,这个船口最大化的利用,那么大家可以看到这只龙的话,就是说诶,他几乎用只用了1/30的船狗,就能够实现了,就是每一个pixel,就是每个屏幕几乎有一个三角形的,这个精度。

那他是怎么做到的,诶我们先讲一个最简单的算法,这个算法其实啊,这是我去他原作全部整理了一遍,因为他那个方法以前讲的就是,确实让大家混淆,我们先讲一个最简单的东西,就是说,假设我已经对这个mash。

变成了很多的cluster,对吧好,我假设把每个cluster 22的去合,合了之后呢,我把cluster的团购的数量都减少一半,那我就形成了一个l o d e的,上面的cluster,对不对。

然后呢我假设我下面有四个cluster,我上合一层,我就变成两个cluster,对不对,然后我再往上一层只有一个cluster,那这样的话我就可以构建一个非常简单的,这个就是这个cluster的。

l o t的这个hearchy对吧,那有了这个hy呢,我每一次简化的时候,其实我会知道他的error的对吧,有几何每次简化我的error就会增加,那好在当前的这个view的情况下,我可以算出来说诶。

你这个caster离我的绑定是多少对吧,我觉得能够算出来说,你的误差不高于一个pixel的,这个error tolerance是多少,如果你的class是做几何简化的时候,和你的这个原始的几何。

这个误差小于一个subpixel的话,那我就觉得你可以绘制了,但如果我发现你大于的话,那怎么办,我继续往下走,所以呢我其实就可以decide一个cluster base的。

l o d的这个实时的卡里的这个li,这个是不是很简单对吧,这是个非常难义务的一个solution啊,好诶如果我有这样的一个line的话,大家想象一下,我假设场景有很多很多的几何对吧。

那我是不是我的streaming,也可以用这种方法去做对吧,对于那种下面很细的,但是其数量很大的那些那些翻译脚本,就是精细的几何,我其实一上来可以不加载,我先加载它的扩展的锤。

当我的相机推进那个小雕像的时候,诶我发现那个l o d2 不好使了,怎么办,我就加载l o d一嘛对吧,当我发现我相机太近了,我d一都不好使了,我加载l o d0 ,你发现没有,诶。

这个方法是就又可以实现了,那个拿来最引游也好的,就是这个这个这个几何数据,可以streaming的去加载,你想这个难用的方法,是不是,就基本把他所有的核心的需求全部解决了,对吧。

这就是nana的最最基础的我们去class base的方法,但这个方法有没有问题呢,哎这个方法其实问题还是挺严重的,但问题出在哪里呢,就是说当我对这些cluster进行合并,进行简化的时候。

我只要简化完之后啊,我的三角形数量少了一半,但是呢我不能保证我减耗完的那个几何,它的边和那个没有简化的几何,就比如说我这边的这几个claer,是用l o d0 绘制的对吧,我回到这张图里面。

这几个cos蓝深蓝色的caster,他用的是l o d0 绘制的那个浅蓝色的,l o d e的那个caster呢,就是我被那个姓掐中的那个那个,那个那个就是那个那个coser呢。

他可能是用l o d e绘制的好,那么它两个之间呢本来是watertight,水密性在一起的,但是呢他们就会形成一个我们的叫cx对吧,大家还记得我们在讲turing的时候,会有这样的cx,对不对,好。

那怎么办呢,其实这个问题呢也是一个很好,很好解决的问题,怎么办,我把它的边锁住嘛对吧,就是说我每次简化的时候,我把我的class的边全部锁住对吧,这样所述之后呢。

我这个cluster虽然已经切到l o d一了,但是呢我实际上这就是我跟旁边,你无论是用d0 还是d2 ,我们那边都能够watertight在一起对吧,但实际上你会发现它一直锁的是那个。

l o d0 的那个边,那个边的话呢,三角形随着你的l o d,从012345678上去之后,你会发现,那个地方的采购的密度是永远都是很高的,那很高,那意味着什么呢,意味着两件事情。

第一个你肯定你的面片简化的利用率不高,你想想看啊,比如说我在l o t0 的时候,我我最后占据的就是比如说我的l d 10,那个时候我的一个cluster,虽然只有128个,128个面。

那它所表达的区域,在原来的那个几何中的区域是很大很大的,对不对,但是你要锁边,光你那边的那个是那个船口数量,可能128就远远装不下去了对吧,这个这个实际上你就没法搞了,这是第一点很头疼的事。

第二点是什么呢,就是说这些边假设你不care说我就歪了了,我对高高级的l o d4567 的话,我就不加那个,128个三角形的约束了,对吧好,我这边就放在这儿,其实你会发现这个几何啊。

当你去拉开来的时候,你会发现有些区域,它的几何的密度和它整体的这个密度啊,其实是就是就是nine uniform的,这个在信号采样上,你会看到一些artifacts,就是你会看到一些非常明显的那种地方。

就是看起来也是连续的,但是你会notify那个地方好像很密,举个例子,这种感觉像什么呢,就像是两件衣服对吧,两块布你缝在衣服的缝合处,你可以看到那个地方,好像有秘密的缝合线的感觉一样。

因为那个地方加了很多几何细节,但是他其他面上的细节全部都没有了,你会notify,就人眼是这样的,人也是一个很神奇的设备,就是我们人的大脑和眼睛,其实对高频信号非常的敏感。

特别是对于franky change,就是频率发生变化的时候,我们人眼的detect的能力是非常非常高的,这个大家如果做render,你就知道就是说其实你从数值上看,它的artifact已经非常小了。

但是呢人眼总是能注意到这些artifact,所以这个地方的话呢,也会产生一个很严重的问题,所以大家会发现没有哪一种方法它work对吧,如果这个方法work了,我们就很省事了,那今天的课程讲到这。

我就可以回去睡觉了,就可以休息了对吧,但实际上的话呢这个方法是不work的,那怎么办,哎,not nice就提出了一个非常神奇的一个想法,这个想法,其实我个人觉得还是非常的惊讶似的。

就是说他把这些cluster 10几个cluster,我变成一个叫cluster group,这个数字我有点忘了,是八个还是还是16还是32个,但是反正不重要,他自己选了一个数据。

那么我的l watch锁整个classer group的边,我里面的这个in inner的这个age啊,就是这个coser之间的boundary啊,全部打打打碎掉,你们就一起去简化,这样的话呢,就是说。

我实际上能够最大化地利用这个,简化所带来的好处,比如说我一个cos 128个三角形对吧,那我假设那个我把16个cluster,聚成一起的话,那我将近有2万多个三角形,对不对,好。

我把这23000集合到一起,我还是锁它的边,这个边可能就1000多个三角形,但是呢,我把2万个三角形减到1万个三角形,这时候你就会发现,它的边其实没有那么痛苦了,而这个时候诶。

我的简化就会变得更加的有效,那么这样做的一个这样做,这样做下去的话,你会发现,他接下来对于那个简化过的那个,1万个三角形的再做一次cover class,他把那个class的数量一下子就减了一半。

这里面就是他原作给的这样的一个案例,就是说诶大家看这四个不同的颜色,就代表了四种不同的caster对吧,那个就是黄色,红色,绿色和蓝色诶,这是代表四个相应的点,就表示caster。

然后呢我把它们合成一起,变成一个class group,然后我整体做出简化,但是它的整个class的外边我还是保持住啊,因为我要保持它在l o d transition的时候。

是what tight的好,这个时候我就会得到就是三角形,数量减一半的三角形,然后呢我再去run co,我就会得到大概少一半的cluster,比如说你们这两个coser,你会发现。

这个时候他就一个很有意思的事情,来这个这个地方也是哪里来,大家特别容易弄混的地方,就是你后面的class数量上面只有两个,但是它和下面的那个class之间的,父子关系的话,不是我们传统理解的树状的。

就是一对一的关系,它是一个一对多的关系,也就是说有可能简化过的cluster,每个cluster实际上是和下面的四个的,l o d0 的cluster都有关联关系对吧。

简化的l o d e的两个cluster,他两个是兄弟关系,这个关系其实是非常非常重要的好,那么它的整个这个算法的核心,就是说,我每一次把这个现在当前的这个l d0 的,比如说l0 。

所有的cluster把它先变成若干个group,然后呢我在group内部做简化,然后简化完之后呢,我去做简化,把它再分成cluster,这里面一个很重要的一点是说,我分成l o d e的。

比如说我假设在l o d0 ,我有2000个cluster对吧,l l o d e的话,2000个cluster,比如说我们十个cluster,一个group,我有200个group,对不对,诶。

我在l o d一的时候,我有1000个cos,对不对,那我这个时候呢,还是用一比十的比例把它变成了,比如说啊100个group,但注意这里面100个group和那个两,以前那个200个group。

它的边界是不保证是一致的,这也是它最核心的一个思想,为什么呢,这样就保证了什么呢,保证了就是当它在l o d切换的时候,你看不到一个持续存在的一个boundary,那个boundary。

否则的话就会一直出问题,好那这个东西是不是很复杂对吧,来我们的课程组的小伙伴,也发挥了我们的这个土法炼钢的神功,我们就开始用not a的算法,来去做了一个实验,我们拿可爱的班尼做了个实验对吧。

这是一个bunny,那用nt的算法,你会发现诶他生成了这么多的claer对吧,这个看上去,这些每个coser大概是100多个三角形,128个三角形诶,下一步干什么事情呢。

我们把caster把它聚类成一个gp,大家注意到这个课件上,那个红色的那个区域,那就是呃大概是十几个哦,16个cluster给18coser是吧,我们变成了一个coser group。

然后呢我们对这个coser group进行一次简化,那么按照课程中的那个按照那个原文的话,你可以发现,就是一开始是那个秘密的cluster对吧,然后呢我们把class cop融合在一起去。

对于整个功夫进行了一次简化,简化完之后呢,我们再run一次classroom,你会发现得到了一些新的cluster对吧,而这些新的cluster呢,和老的cluster之间的话,实际上是不再是一一对应。

而是是说在这个l o d e里面的,这个class group的所有的cluster,可能和d0 里面这个class都是有关系的,因为这些三角形被reuse了,唉这个结构就会非常复杂了。

这其实也是nana的,大家特别容易弄混的一件事情,就class group到底是什么东西好,你有了这个group之后呢,你会发现就是他为什么要这么做呢,其实啊。

他希望每一个每一次这个group的boundary,在不同的l o d里面,因为group boundary是什么,在做l d的是什么,需要它的边的精度是要锁住的,大家还记得吗,他一定要锁住那个边。

那么他希望这个被锁住的边啊,在每一层lo d的时候,它都会变换掉,这个很像什么东西呢,哎我自己一个土法炼钢,就是说很像你在做这个,比如说做这个三破零的时候。

你比如说你做那个呃screen space ao的时候,你的采样那个r的分布,你每个pixel你希望他做一次接触,如果你不做杰train的话,你会发现你这个noise是很有pattern的对吧。

你会注意到那个pattern,但其实他在这个几何采样的时候,他对他每一层的l o d的时候,他是强迫的把这个boundary做了一次gl three,所以使得你当这个几何在进行l o d调。

就是随着你的相机的移动,它的l o d在不停的popping popping切换的时候,你没办法定死住,一个,就是说诶,一个你能注意到的一个高频的数据,因为那个高频的区域,在每一层l t变化的时候。

它都会发生变化,这样你人眼就注意不到这样的一个,清晰的这样一个锁边的boundary,它实际上我我用最土的方法去理解,就是他就接触,但这个方法说句实话,我认为是非常非常巧妙的,真的很巧妙。

那么这里面的话呢,所以这里面的话,这个图是很多人会弄混的一件事情,就是这张图实际上不是classer boundary,它是classer group的boundary。

比如说红色的表达的是他的l o d0 的,所有的class group boundary,哎当我这些group里面做简化,然后呢我再去做classroom,然后呢我再去跑一次grp的时候。

我可能得到的是这些绿色的这一层,你会发现绿色的这个边界,好像和那个红色的那一层就没有关系了,对不对,那我们再往上走一层,诶,那我到l o d r的时候,我这个class group就越来越大,那么它呢。

实际上和这个就形成了这样一个套接关系,这个图的话呢,实际上是理解nana的几何的基础的一个,非常核心的一张图,也就是你会发现它这个用一个,非常巧妙的方法,把这个我们以前在做l o d。

这个transition的时候,要左边的这个挑战给它彻底的给它解决掉,那么在这里面特别容易混淆的是说,他这里面展示的不是cluster,而是cluster group,好。

那我们有了这样的一个表达的时候呢,原作给了这样的一张图,就是说你看我们基于这个,我们构建了这样一个漂亮的deck,deck是什么,deck就是一个有向无环图对吧,但是你们看这个deg。

是不是不像一个复杂的这个有向无环图,更像是一棵树对吧,所有人看到这个都觉得哦,这个这个就是我基于这个class group,我去merge的时候,那这里面每个节点它到底是这个啊。

到底是cluster呢还是cluster gp呢,对吧,其实这里面画的每个东西它是一个cluster,但是class之间的关系,它这个图画的实际上是有问题的,因为你到了l o d一到d2 的话。

它的连接不应该是那么干净,实际上它的连接是非常非常复杂的,所以呢我们课程组呢,基于我们翻看了源代码,我们画出了我们的版本的这个图,它为什么是个deg,而不是tree,实际上这个图应该长的是这个样子。

就是说首先大家看l d0 ,它下面的是同一个颜色,它其实表达的是在l o d0 里面,一个class group里面所有的cluster对吧,比如说红色的那些class group。

蓝色组的class group,那个绿色组的class group,然后呢当你对它class group进行简化,你就可以得到了l o d e的那些cluster。

然后呢在l o d e的那个coser呢,你会发现,当你再去run一次这个古品算法的时候,它实际上会和以前的l o d0 的那个,cluster功夫的关系是打乱的。

你会发现我们用每个框表达一个class group的话,那实际上你会发现比如说在l d e的时候,左边这个classroom里面,它有一些cluster。

指向的是这个红色区的cluster 0 level 0对吧,有些是指向,有一个是指向蓝色,就是那个蓝色的class那个group 0,那么在另外一个侧的class group里面的话呢。

它也是这样去指的,所以这一张图的话实际上是none night,最重要的这张dg这个图,其实如果大家对这个图不理解的话,你后面他几乎所有的算法都很难理解,这个图我可以讲我们课程组吵了三天三夜。

昨天夜里两点钟我还在电话,那个我们在视频会议里面,大家还在吵架,说中文到底是怎么回事,今天早上一时兴起打开源代码,一通看完,终于把他看明白对吧,这简直是个神坑,因为这张图说实话。

画的绝对让大家很confuse,这他妈到底是为啊,这为什么一定是个dg,这很明显看上去是个数吗,但实际上的话呢,这一层层的cluster之间的连接的话,其实是这样的关系,这里面的话呢你可以看到乱中有序。

首先是乱,就是说他l不同层的l o d之间的这个,caster之间链接啊,是多对多的链接,对不对,它就是每一个底层的cluster,他可能有multiple parents对吧,就是他上一集有多个。

那么同时的话呢它有趣的地方在哪里呢,你会发现他虽然说它的parents可能是多个,但是他不会和上一集的所有的这个,同一级的coser都会建立,这种就是parent的关系,它只和由我自己做简化。

就是simple带上去的那几个cluster有关系,所以他的这个影响是一个在localized的对吧,那么这个的话呢,就是说是一个很重要的一个系统,很重要的一个结构,你有了这个数据结构之后。

你就能理解他后面的l o d是怎么做的,哎这张图大家一定要记得,我们后面还会再出现一次呢,大家不用着急,好好,那这个时候呢,我们还是拿我们可爱的班尼做案例,你会发现这就是我们课程所拿到的算法。

去跑了一遍,你看l o d0 的时候,class我就切成这样了,那我们到l o d e的时候,按l d2 来,我们跳了几局啊,你看见这个classr已经变成这个样子了对吧。

那他l d4 的时候一class这么大,到最后那个l d的时候,它大概是128个,就是那个班里就变成这个样了,所以呢,其实这就说明了他的那个原来的这张图,的解释啊,是对的。

就这张图也就是说它每一集的classer,这个boundary确实一直在变,class group boundary,所以你不会就是当我们在这些cluster,来回切换的时候。

你不会注意到一个consistent的那个bdi,让你注意得到哎,这就是拿来它是一个很巧妙的一个东西,但是呢这个漂亮的架构呢,实际上你要去维护它,是这个非常复杂的这个deck对吧。

这个deck我去做l d怎么做,是不是很复杂,所以呢接下来就进入none night,第二个我认为比较难懂,大家特别容易computer的一个地方好,那这里面有个细节,就是这也是我对原作者。

非常震惊的一个地方,就是他花了很多笔墨,讲了他怎么做这个simplification,对吧,当然我我觉得他讲这个也是有道理的,其实我个人一直认为就是mesh supplification。

但是呢确实他讲了一件事情,我认为是对的,就是说如果你想实现not net的算法的话,你对他这个error的计算一定要准确,因为你的l r计算一旦不准确的话,当你的相机推来推去的时候。

你可以注意到就是noticeable的这个poppy,当然他他要保证,就是每一次我的error都是subpixel,而且呢其实他后面还提了一个要求,就是我需要它每一层error往上去传递的时候。

必须是单向累加的,这个累加其实是非常就这个单向增加的,这个单调性取值也是非常重要的一个设定,我们待会儿再去讲,ok但这个地方的话,我觉得这是我们课程组做的一个案例。

就是说他是你是首先生成的classer,它把这个class之间通过链接关系呢,生成了一个graph,然后呢用mice这个中间件把它聚类成了group,然后呢一个grp里面的话呢。

我用这个就是simplification方法,基于这个q e们呢,就是那个这个这个codrick的,那个error metric的这个方法诶,我对它进行了一个简化,简化之后呢。

我又对它进行classroom对吧,我又可以形成我新的部分,它大概是这么一个pipeline,好,那有意思的问题就来了,我既然已经构建了这一个看起来有点像树,它又不像数的这么一个。

deck的这么一个结构对吧,所有的classer从l d0 ,l d e l d r l的adn全部构建起来了,我的软碳,我给了你一个相机位,我怎么去选择它的这个l o d level。

这个问题其实还是蛮挑战的,那么如果我们现在用view dependent的方法,我们去去做它的这个level的话,就是说我们最简单的做法,就是我在这个deck里面去从它的根节点。

因为它这个代表到最后的根节点,是一个cluster,你去看看源代码,你就知道就是他最后发现诶,我的cho只是只能生成一个,只有一个cluster的这样的一个case,说我的这个合并就停止了。

好那我知道他的error对吧,我就根据我的view,我就不停的问我的error够不够不够,我就往下走,就是说我实际上呢,他把这些同一个cluster group的东西,做成了一个大的虚拟节点。

整个这个节点有一个error,有个绑定,那实际上我是不是就可以知道说哎,我对这个group我是不是可见啊,是不是需要被cut掉,如果不要不需要被cut掉的话,我继续绘制它,但是这样的一个dg啊。

你去traverse,他的话是不是还是比较费的,比较复杂的对吧,就是大家想想,这个算法写起来有一点头疼了,对不对,那么好,作者在这边的话呢,提出了一个很重要的思想。

就是说首先他认为你的这些cluster,如果都属于一个group的话,如果我这个caster group如果要往下去绘制的话,那所有人如果选了l o d0 。

那我所有的cluster in the same grou,都要被画成l o d0 对吧,如果我不是l o d0 ,那我就不画,这个想法其实很淳朴,我认为也是可以理解的,这个问题不大。

这样的好处是什么呢,就是它的l o d的选择是比较快的,但是真正最难理解的是什么呢,就是说实际上所有的l o d问题,你在这样的一个类树状的结构里面,你其实找的还是那一条的cut line对吧。

那么这个cut line的话,你想啊我们真实的一个几何,比如像我们做的那个dragon那个例子里面啊,那个例子里面大概将近有1万多个吧,1万多个这个caster,那我把这1万多coser。

以及它构建的那一层层的lled结构,我把它整个traverse一遍的话,大家觉得这个速度是不是会非常的慢,那大家想个办法说,我能不能让我的这个l o d的selection,全部的并行化。

也就是每一个单位,每一个啊指数或者每一个节点,他自己决定我在当前的l o d下,我到底是绘制还是不绘制对吧,比如像这个图像里面,就是说那条被黄线勾中的那些顶点,就是我要绘制的,没有被各种。

我就不绘制对吧,那这样的一条cut line的话,他最好是deterministic的诶,这个就是对于这种dg的这个结构啊,大家会发现,如果你真的假设,你对他的不做一个单调性的约束的话。

你这个数从左向右便利对吧,从上向下深度遍历对吧,或者从右向左边离,你,在数学上,你会发现它有可能这个cut是不稳定的,那么如果这个cut是不稳定的话,你知道会出现什么情况吗,大家还记得我在我在前面讲了。

那个那个算法的时候,就是说他可能会出现the fighting啊,popping啊,就是说诶你的camera没动对吧,这一帧和那一帧算法上,只是因为那个就是b型化的这个计算,它提交的这个先后顺序有。

那么这个,这个这个就是亿万分之1ms的区别,导致了他们的数据就fight了,fight之后这个结果就不一样了对吧,那所以他就希望说唉我的这个决策的话。

同时的话呢它的结果必须是deterministic的,那怎么去做这件事情呢,这也是none night,我觉得很重要的一个点,就所以我这个标题我自己优化过的,就是我觉得如何paralyzation。

第一个呢他要求这个deg树上的这个error,它是单调性的往上涨,因为如果你的单调性的往上涨的话呢,你给我任何一个error sours hold,他的这条cut线一定是唯一的。

哎这个在数学上大家可以去证明一下对吧,第二件事情是什么呢,就是说到底每一个节点,它到底是怎么样的决定,我是否可见的话,它实际上呢你从树的根节点往下去,便利自然是一个解法,但是呢你这个数的便利的话。

其实你很难把它做的并行化,但是他后面其实有个方法并行化,待会儿再讲啊,但是这个并行化的话很麻烦,那他想了一个方法,就是说其实你要的东西是什么呢,对于任何一个节点,他要被渲染,其实要满足两个条件对吧。

第一个条件呢,就是说我的我的父亲的那个节点,他的error要大于你给定的这个threshold,对吧,同时呢我自己的这个coser,我的error要小于和等于的,那意味着我这个caster是可见的。

所以说其实我并不需要把这个树上的,所有的节点,按照你的那个顺序就是遍历一遍,就一定我并不一定要按照从root往下便利,其实我把这所有的节点全部拍平,看成一个列表,我就用这个方程去验证一遍了。

假设我每个节点会存一下,我父亲的arrow的话,实际上我就可以把一个数的traverse,变成一个raid traverse,这个这个地方是有点抽象了,但大家一定要理解,因为你不理解这个的话。

它这个地方其实核心的想法是什么呢,就是说这样就使得每一个节点的l o d的,decision能够并行化的进行,否则的话,我就必须要按照数的结构去访问它,那按照数字结构访问它,随着你的树的深度的话。

我的访问的效率就会下降对吧,如果我并行的话,我一次可以32 30个往里面扔的话,我的效率是不是更高,对不对,这就是它的一个核心的想法,而且呢在这里面还有一个细节是说,在这一颗带给里面。

他去做这个l o d selection的单位到底是什么,是每个卡cluster自己做这个我的检测呢,还是以cluster grp为单位,那我接下来会讲这个细节,这个细节也是特别容易混淆的,实际上呢。

我们看到它的代码是以claser group为单位,但是呢又精准到每一个cluster,但是它核心的想法就是每一个检测,它都是isolated的,其实在这个它的这个数里面,它存储的呢。

就是他其实这个时候已经不需要输了对吧,他其实把每一层l o d0 ,l o d e这里面的cast group变成一个节点,这个节点它可以拍平,但是每一个节点呢它存两组数据。

第一组数据呢是我的parents对吧,比如说我假设我的l o d里面,这个group是有四个caster组成的,我把它四个简化成两个的话,那我这个简化过程中产生的最大的erro。

就是我的parent error,我存在这假如parent error是1。2放在这,然后呢我自己本身的话,比如说l o d0 的话,它实际上是没有l的,对不对,但是呢你哪来的,实践中。

它有一个小trick,它会把这个强制制成-1对吧,很有意思,他就好mark一下,就是说你看我这个是绝对正确的一个几何,但是这不重要,反正是他的细节,他就往上这样做,但是核心反正-1比零小嘛。

所以没有问题对吧,那么好对于那个在l o d一里面,大家可以看到有两个cluster,一个是红色的,一个是那个绿色的,那其实呢它也会存一个我的paraerror,和我们这个cluster。

因为我行过来的话,我各自的error你会发现,就是说它们源自于同一个,就是低级的l o d group of class group的话,他两个简化过了caster。

虽然它们分属于不同的l o d一级的,classroot了,它的error两个class error是一模一样的,诶这个是很重要的一点,就是他们在做网上合并进行简化,即使简化完之后。

即使分成两个不同的coser,它的error都是取得这次简化过程中,产生的最大的error,好那这样的话我这就意味着什么呢,就这里面在这张图里面,假设我的输入是threshold的一点。

这个ao你不能超过我对吧,诶我对于这三个cluster group对吧,有两个是属于l o d1 ,有一个是属于l0 ,我怎么去计算呢,哎很简单,首先我检测第一个条件就是我的parent error。

要大于我的这个ths hold,你会发现这三个cluster都满足你的需求,对吧,我的在lv 0的时候,parent是1。1没有问题,你大于一了,第二个呢led的那个就是那个蓝红色。

那个l d一里面的那个红色的class group呢,他的partnl是1。2更大了对吧,因为往上以及它会变得更大了,好,你也满足了,那个绿色的那个l o d e的cluster,他也满足了,他是1。

4,好都没问题,好我们再看下一个问题,诶,这个地方的话其实是原来pp,就我觉得这块写的不算严谨,应该叫for each cluster in the class group。

你的cast error如果小于等于ths hold的时候,哎,我这个时候,我认为这个cluster就可以被渲染,但是对于我们这里面给的这个案例里面,比如说在红色里面,那个1。1的那个黄色的那个。

就是那个红色那个l l o d y,l o d e的那个class group里面的话,那个1。1等于l的group,他还是不满足这个条件,所以它的下面的那个class group。

那个它这个东西就不会被绘制对吧,那么对于那个绿色的l o d e的,那个class group来讲呢,在l d里面它也一样不满足,所以那个紫色的class group也不会给大家,这个大家就会去想了。

说因为我不会被绘绘制,所以呢我要激活我的children的这个class,对不对,但其实这个地方如果你这么想的话,就意味着你没有理解这个并行化的这个,l o d selection。

实际上每个class group里面的每个classer,他只是做自己的检测,就是相当于是说我那个红色的框class group面,假设有四个class的话。

他每个cluster只是自己决定说我是否会制,但是因为我不会制,所以我需要我的child这个哦,我的下一集的那个l o d0 的那个东西,绘制的话,这个决策跟我没有关系,但是呢因为我的这个error。

他严格的网上传递的话,当你做到那个l o d0 里面,那个绿色的卡斯库的时候,它的数据上一定会满足,说他的paraerror是1。1大于一点的,这个sal的,但是呢他自己的error的话。

应该是-1小于那个一点,所以他这些就是d0 里面的四个小classer,全部会被绘制一点,唉这一点是特别特别容易混淆的,就是大家会天然的认为是说诶,我的上一级的l o d发现没通过,我就看我的下一集。

其实它不是的,他把整个这个树的结构全部拍平了,哪个class不是我自己处理,当然你会发现,就是只要你保证这个error的话,是严格的单调的网上传递,而且我下一集的那个parent error。

一定是跟上一集那个对应的cluster的,那个自己的error是严格一致的话,你会发现这个测试出来的结果,是严格一致的,不会出问题,而且几何不会去渲染两次,这其实是作者一个非常核心的一个,一个想法。

这个想法非常的巧妙,实话实说非常的巧妙,也就是说,因为以前当我们在做一些l o d的时候,我们会天然的会做一个树状结构嘛对吧,那我们对这个l o d树的这个处理的话,天然的就会树状的一次一次下去。

但是的话not net这里面的话,他因为意识到,就现在gpu的b型化处理能力非常强,他就希望把这个o d的selection,变成彻底的b型化的处理,所以很遗憾在这个原原始的这个ppt中的话。

这个作者把这个事情就是,几乎是一一笔带过,nana的技术的时候,会发现这一part是非常非常难以理解的,而且它的源代码中写的是叫club,这个叫class error,小于s的对吧。

但其实他是class功夫里面存的是paraerror,但是呢它这个功夫里面的话有一组cluster,所以每个coser自己会称自己的error,他要所以说这个比较的话是在鼓舞里面,每个l自己去比较的。

然后呢各个class group的l o d的selection,就是我到底是绘制还是不会知道,但是你会发现它最终的结果一定是对的,这也是not net非常巧妙的一个地方,好这个给给他那个点赞的时间。

差不多到此结束了,就不点他的赞了,好那么实际上的话呢,这就是它的整个基于class group的构建了,这样的一个hy的这样一个结构,我可以b进化的决定他的similar那个d。

但是呢诶作者的第二排就来了,我觉得这样虽然我还是可以并行化的做,但是毕竟class的数量太多了,而且呢我的cluster的这个这个,这个数量还是很大,这时候作者就提出了一个很很牛逼的一,个想法。

在这个他的自己的报告中的话,整个这个东西是在一个页面下的,很小的一块,说我构建了一个b v h4 对吧,把所有的children的这个l r全部maximum在一起,然后呢。

所有的l o d ection了,我的天哪,这么复杂的一个算法,老人家用三句话就讲完了,当时哈我自己读到这一趴的时候,我就觉得啊这真的是太难理解了,对吧,然后又是被逼着我们课程组的小伙伴。

又开始钻进代码里面一通狂搞狂研究,然后就就去仔细理解这个我们的原作者,他这个b vh到底是怎么构建呢对吧,这个地方我确实要小小的吐槽一下,就是这个presentation确实是没讲清楚。

但是我猜可能是有意的吧,这么高深的算法,怎么可能让我们这种凡人学会呢,那没办法,凡人也是要修仙呢,所以凡人也是很努力的去理解先人的想法,其实这个想法的核心是什么呢,唉这是我们课程组自己画的图啊。

这个也有,我真的要给我们课程组点赞,就是说其实啊这个bbs是非常的抽象,但是呢他它的实际的情况是这样的,就是说对于这条龙而言,那其实你如果你的l o d0 所形成的,所有的class group。

对不对,那么你可以把所有l o d0 的class group,用一个bbs的方法形成一颗tree诶,那同样呢对于你的l o d一所有的cast group,你是不是也可以形成一个bh tree对吧。

那么l o d一直到l o d n它都能形成bh,然后呢他把这些所有的tree的节点诶,把它连到一个共同的根节点,它就构建了一个超级的b vh tree,他为什么要做这样一件事情呢。

这个事情其实是有很深的道理的,就是前面我一直在讲这个,这也是作者,我觉得一方面大谈这个诶,我的l o d selection,我要paralyzation,但是他又意识到,就是说。

但其实你只要处理的class grp,数量实在太大了对吧,那举一个例子,比如像这条龙,它有700万个三角形,那我会生成11万个cluster对吧,group的,那么group的数量也是几万个。

那我每一次在一个camera的情况下,我要把这个啊其实比11万还要,比那个就是1万多还要多,因为你是1万多个,假设一比十的换算,一比11000个。

cluster group在four l o d0 的话,那你再往上l d一是多少,是5000多个对吧,l d2 是2000多个,把你这个二的密大概是2万多个,这个class group对吧。

你把这个数据就是即使你用并行的方法,把它paralyzation一下,这个效率其实也是很低的呀,啊作者这时候突然意识到原来不香啊,就是这个这个traverse,一个array的数据是很不香的。

那怎么办呢,哎传统艺能来了,我们给他把这些所有因为每个class group,你可以想象成一小片几何吗,它有那个绑定嘛对吧,那这个在空间上的物体块,而且大小都差不多,那我最优的组织方式是什么呢。

我把它升成b vh嘛对吧,而且b vs里面的它这个error的话,我可以取他的这个绑定,我可以取他们的和诶error,我取它们的最大,这样的话,当我的相机看到一个就是一个cluster。

一个一个一个一个物体的时候,比如说对r o d0 ,他跟这个物体如果距离我很远,他这个那个绑定的话,离我最近的地方可能距离我可能10米对吧,然后呢,l o d0 上它最大的l也是-1对吧。

那整个这棵树就这1万多个class grp,我是不是完全不用traverse了,对不对,作者真的是大聪明啊,这个地方它突然又意识到树的好处了,那好我这个这个地方这1万多个class gp 9。

我就不用看看了,那同理l o d1 ,如果10米之外,你可以把整个这个l o d e的这个,这个class groups全部cut掉对吧,那你可能到l o d7 的时候。

你发现这个error我需要notifine,然后呢你平时在里面去traverse了,所以说其实啊怎么说呢,他这个时候这个思想就比vh的话,实际上又引入了。

就是我们以前在做这种with bility的时候,经常用的这个方法,但这个方法有没有道理呢,我个人觉得,虽然我这个觉得他讲得实在是太过分了,对吧,就这几句话,但是呢我个人认为。

这个方法其实对于nt来讲非常的关键,因为确实对于这么高精度的几何的话,如果你即使把所有的coser group traverse一遍,这件事情,它的负载也是惊人的,想想你场景有那么多的物体怎么办对吧。

所以的话呢它构建这个b vs b vs tree的话,对性能的影响非常大,但是这里面为什么它可以就是不用l o d,01234构建了一个tree,它反而把零的节点认成一个税一的节点,一个成一个睡。

实际上这个考虑是很聪明的,为什么呢,对于很多时候,这个物体啊离我的距离可能有点远,比距离我5米,距离我10米,有的时候距离我20米,对不对,这个距离在游戏场景里面不算很远对吧。

但是很可能你的cluster group,数量最多的那个case,那么多,卡斯可以全部不用traverse直接给剃掉,所以那一棵树整个就被踢掉了,所以说这个呢,实际上是作者一个非常聪明的方法。

但是呢确实实话实说,就是在它的原作中没有讲清楚对吧,所以我们课程组绞尽脑汁的时候,把这张图画出来了,同学们就明白了,那这里面特别容易confuse的东西是什么呢,这是啊,其实我们把它那个。

整个那个树都给倒出来了对吧,你会发现他把这些所有的这些l o d的,这些group全部构建成一棵树,它还有一个小trick,就是说诶我我尽可能build一个,就是说这个这个张度为四的这样的一棵树。

它其实做这个大家如果以前学过数据结构,就学学过叫树的那个平衡嘛,我把树原来不平衡的数,把它变成平衡数对吧,否则的话这样让我的这个这个数的便利,尽可能的效率高一点,但这里面有一个有一个细节。

就是说在他这个b vs树,树的这个叶节点里面,挂的是一个个的classer group,不是一个个的cluster,这也是一个大家很注意的一点,但这个点呢大家如果讲错了,大家也可以去查一下。

反正我们是花了很多力气,去研究它的源代码,去看待这件事怎么做的好,那其实呢你有了这样的一个结构的话,实话实说,这里面也是他的自己的一个demo对吧,这是600万个三角形的一个一个case。

那么它会合成多少呢,大概会合成这个就11万cluster,那么如果我们当我们构建了b y h的话,实际上我们大概只check了107个,比vh nose,你看从11万变成107。

然后呢我们只需要去check 4000多个class,这比11万几乎少了,将近有大概有20多倍吧,将近二三十倍左右,然后呢你最后可见的大概是2000多个,所以这回让这个算法变得真正的可以实战。

所以之前我刚才讲的,就是说b y h这个东西的话呢,对于nt来讲,其实是个很关键性的一步,如果他不做这个的话,只用我们上一节就上一章讲了,这个算法的话,其实他实战中的效率是很低的。

所以我认为这个事情也是很关键的一步,那么接下来呢就是原作者是大谈特谈的,就特别得意的说,哎呀我有了个b bh对吧,我怎么去traverse,他呢,他说哎呀传统的方法对吧,我就在这棵树。

我就一层层的去traverse,第一层把根节点扫一遍,产生很多新的子节点子节点,然后呢我扔到新的任务thread里面,我再去跑,然后呢再形成第二层,第三层它是这个方法特别的慢,那怎么办呢。

哎它实现了一个小小的类似于这种,那个就是job system,大家记得我们在前面那个d o p job sister,讲的,就是说诶我把很多的walking thread固定下来。

然后呢我是用一个pmc的方法,就是multiproducer muli consumer的结构,然后呢,就是说我在我产生了任何一个子节点,我就直接扔到一个我的task q里面。

那现在这个walking read里面只要有个thread空呢,他就把这个q把这个任务捡起来,他就处理掉了,就是一堆人往后面opending任务,一堆人的用前面的指针去取任务对吧。

就是这个这其实是一个很简单的一个结构,当然了,因为它要依赖于现在的这个显卡,就是这个computer shor,它其实可以实现,就是叫多很多个working read,之间可以共享一个p对吧。

它可以实现这种原子化的这个锁定,所以能做这件事,实话实说呢,作者在这个这个报告中,大谈特谈的这个这个这个设计,但是我个人觉得,这就是一个实现了一个小trick,然后呢大概大概实现了10%到。

他说10%到30左右的acceleration对吧,但实际上其实我觉得他比bh,是它最核心的一个思想,但是的话呢,就是我们的traverse,速度会变得稍微快那么一丢丢,而且这个方法呢。

我个人觉得大家如果理解了,什么是job system的话,你可以理解成,就是说我在这个就是computer shor上,利用那个compusher,他一次性发出32个walking read的。

这个设计的话,把它32个threat,我可以re全部固定住,然后呢做一个公共的task buffer啊,那个就是to be handle task buffer,然后呢我这头往里面扔入啊。

这头往后面ending任务,那一头呢取任务就好了,两个指针就完事儿对吧,所以的话呢,这个啊是一个作者的一个小的trick,我个人觉得应该比较好理解,那么这样的话讲到这一part。

我觉得none night最复杂的几何的表达,终于就讲完了,我不知道同学们有没有听懂啊,如果大家听不懂的话,我们会再想办法对吧,我们还有二零系列的课程,对不对,虽然我每次跟我的团队讲,二零系的。

可能大家都会说,求不要再做二零系列的课程,实在太累了对吧,ok那我们先把这个坑留在这儿吧,那么好,那有了这样的几何的时候,接下来我们讲讲nmt到底怎么渲染,它想渲染之前呢。

先讲一个他自己特别引以为傲的东西,就是nmt,我们去做rts ation,那为什么要去这个russell zation呢,其实nana,如果达到这么精细的一个几何密度啊,它其实很多三角形。

已经和屏幕上的像素差不多大了,那么如果跟屏幕上像素差不多了,那我三角形的绘制到屏幕上,我们用的方法是什么,诶我们用的是这个硬件的ross rozation,对吧。

大家传统我觉得硬件的ross应该是最快的,肯定比我自己写设计点快了啊,确实是这样,但是呢其实硬件的reservation的话呢,实际上它有一个假设,首先在硬件中为了处理。

我们在做这个texture sampling,你们的dx d d y,他每一次rose rozation的话呢,它一般至少会rose rise,就是2x2的pixel。

这样我才能算出它d d x d y,第二个呢就是run的算法呢,它是一个高度优化过的算法,就是在古典时代啊,我们的三角形都很大,那么我们去对这个三角形进行,扫描的时候呢。

我们用的一般用的是skyline算法,那其实呢如果我是一个像素,就一行像素,一行像素skline的话呢,这个计算其实非常的费,大家如果想想就知道了,那怎么办呢,我们就想到了一个聪明的方法。

我们说把屏幕按4x4,分成一个个的套对吧,我首先检测说这个skyline,是不是在这个town里面,那如果这个skyline不在这个town里面的话,整个topixel我不用检测,这其实也是古典时代呢。

大家意识到,就是说诶,三角形的数量是远远低于屏幕的pixel的数量,就可以快速的,这是cut掉很多,我不需要去进行计算的这些pixel对吧,但是呢这个大聪明的这个,到了我们的这个。

当这个船狗已经小到跟皮克斯差不多的时,候,问题就来了,因为在这个nt里面,我很多三角形其实已经是接近于一个pixel了,我的天呐,我为了去渲染你这一个pixel大小的三角形,我要去这个访问。

我要generate 16倍的pixel去做他的realization,这上有大量的计算是被浪费掉了,那这个时候怎么办呢,哎我们就想到了一个方法,就是拿来的方法就是说诶我们用software方法。

rose rise,只是说他用了computer shader,他就直接把这个小三角形的rust rization,它自己全部接管对吧,这样的话呢。

他自己就就是now night的这个software sation,它自身是比硬件的要快三倍,那怎么去rts其实也是比较简单的,就是说首先的话,如果这个三角形本身小于一个pixel的话,他啥也没干。

他就啪打一个pixel上去就完事了,这个显然比那个skyline要好,这个快很多对吧,否则的话那个是sky,先在16x4x4的,16个pixel里面先算一遍,然后最后抓到说哦。

原来是这个黄色的pix又被点亮,那单身的话呢,nana因为你知道每个三角形的边长和面积嘛,所以你就知道它投影上面它就是一个pixel,啪就丢上去了,对不对,所以它会非常的快,然后呢,因为你知道。

每一个就是这个三角形的vertex,所以你其实可以根据vertex上存的这个uv,可以算出它的dd x d y,你不用去做一个2x2的pixel,对吧好,那么它的原则是什么呢。

其实是个很high的一个数据,但是我觉得这个数据,其实可能是他的经验数据,就是说对于每一个首先的话,对于每个cluster,如果这里面三角形的所有的边长,就是他在投影情况下,它都少。

rust rization都小于16个spring pixel的话,他就把整个这个cluster切换到software ross,zation的这样的一个这个pipeline里面去,那么反之。

如果这个cluster离我比较近,这里面的有三角形,它超过了18个pixel的边长的话,那我怎么办呢,哎我还是交给传统的这个hardware pipeline,但这个我后面再讲。

那这里面有一个很大的一个一个挑战,就是说我去写computer shader,写一个software rather rise pipeline,其实是比较简单的一件事对吧,我就把这个像素的点填好就行了。

这个sky算法其实也比较简单,就是算两头,对于每一行的pixel算两头,我就知道中间这一排点我全部要填,但是大家知道就是在我们做哪来的,这么复杂的几何的时候,它其实很多几何会做的,那么在传统的管线中呢。

我们有个机制叫early z,就是说如果z bar里面这个东西它已经有了,那我就不用再做了,对不对,那么我其实就算没有,lz我总要做z testing吧,software rose riser的话。

他怎么去能够,early的把这个东西给干掉呢,这里面它就有一个有一个trick了,他怎么办呢,他利用了一个扩展的sdk,就是他直接写了一个64位的,这样的一个原子形的操作,然后呢。

他在这里面用了一个interlock max的这个算子,就是说他把深度写到这个,64位数字的高位,那意味着什么,就你后面所有的这个buffer的这些信息,比如说你是哪个cluster呀。

你是哪个triangle啊,这数据随便你写,没关系的,但是只要你的depth比他大,那其他的depth肯定就会被干掉了,对不对,所以说其实呢他用了这个,就是这个其实是一个trick了。

但是我觉得这个trick的话呢,实际上在未来的意见中肯定要支持的,就是说当我去写sofa rose rise的时候,诶,我自己手动的模拟了一下,模拟了一下the testing的这样一个过程。

所以这个是它的一个trick,但是呢这样的一个trick的话呢,实际上我就能够把那些就是说被挡住的,那些几何全部给它过滤掉对吧,那么这个时候你可以看到它,它在这三个维度。

你可以看到它的生成的depth对吧,生成的这个class的i d,然后呢它生产的全过id,这都是用伪彩色把那个id表达出来了,大家可以看到就是非常的有意思对吧,claer其实就算是clar也是非常的密。

那三角形几乎就已经达到,像素级别的东西了,那么这里面就隐含了给大家讲了一件事情,就是nne他的shading啊,它在几何的这一趴深沉的东西,它其实是用visited。

visibility buffer的方法去rendering的,他并不是上来直接生成了g8 分,而是说先把每个class的id,和这个传播的案例打出来,所以谁定的事情放在后面,他先把几何答对好。

那么接下来的话呢,它lighting pass就跟我们刚才讲的visibi barender,一样的对吧,就是我拿到了阴森的id了,拿到传一个id了,我就把你三个vertex index找到。

把vertx的数据position什么全部拿到,我就拿到你的这个什么,根据你的那个每个vertex的uv啊,我进行插值,然后我就算出你的这个啊,你的那个ab do啊,你的这个spacer这些东西。

大家可以发现我们前面为什么要跟大家讲,vc b g visibility buffer based rendering,其实这就是大家去理解nlight,它核心上面一个关键的block对吧好。

那这个时候就是拿来的这个方法好,那你有了这样一个东西的话,其实大家就像经常讲的,就是我们觉得这个算法是不是会非常的费,啊对吧,因为你你想这里面要写这么多东西,其实会非常的对,但实际上的话呢你会发现。

就是说作者说在现代的gpu情况下,其实是在这个那个console主机上,也都实现了,他说其实不像大家想的那么废,我就我个人还是很愿意相信这个结论,那么这里面有个很重要的一点,就是刚才我们在前面讲了。

visibility buffer based rendering,讲的就是说,其实对于一个真正的现代游戏引擎,来讲的话,那我们还是会建议,就是说你要把维斯的buff和deer的renderer。

设定结合在一起,为什么呢,因为你有很多的物体走的还是default,rendering对吧,那你这个时候的话呢,你增加一个mature pass,同样去写他的g8 分的话。

这样的话你后面的lighting pass的,整个papi全部是统一的,否则的话你要除以两遍,如果大家去看那个就是说啊,比如说像aya那个就是曼哈顿那个demo里面。

就是matrix那个那个demo的话,实际上它不是所有的几何都走nt,只有部分几何走的是nt,很多绝大部分几何走的还是传统的低分的,这个就是differ的papi,但这两种东西的渲染的话。

本身毫无压力地混合在一起了,这也是本身我觉得他很聪明的一个地方,因为其实not net只能解决那些静态的结合啊,那对于这种动态的,比如说character角色呀,奔跑的汽车呀对吧。

就是他是让nana的目前的技术是解决不了的,好,那么这样的话呢,其实这里面大家注意到一点,就是not ne他去做这个rozation的话呢,它是以每一个cluster为单位,记住啊。

不是class grp,是每个class为单位,就是根据刚才我讲的那个原则,就是他的如果所有的边都小于18个pixel,那怎么办,我就把整个class扔到这个sofrurider里面去。

那如果是大于的话,那我这classroom没办法,我就扔给hardw,这张图中就是原作者给出来的,就是说诶那个红色的那些区域,就表示走的是hardw,你会发现绝大部分的区域走的全是software。

resation,这也是非常了不起的一件事情,但这件事情呢我自己是很想多说一句,就是我觉得首先他想到用computer shader,做sofarrier是个很聪明的一个想法对吧。

确实比现在传统硬件的实现效率高很多,但是我个人特别好奇的一件事情,就是说比如像nvidia amd对吧,他们看到了这个算法,如果是我的话,我肯定会在硬件上实现一套跟他比,他效率更高。

而且不用你再去写写诗的方法,也就是你三角形,你告诉我说就是tiny triangle对吧,我走的就是一个非常高效的硬件的这个single,pixel的这种管线,那么所以的话呢我个人很好奇。

就是说nvidia最新的,他提出的那个micromash的那个那个,那个那个那个功能的话,是不是就是把这个他的software rose riser,硬件化了一下,反正我如果我是mvd的话。

我肯定会干这件事情对吧,所以有可能这些代码在未来,由硬件直接支撑了,可能不需要我们自己再去写,这么复杂的caitter shor来解决这个问题,好,那么作者也提到一件事情,就是很多的instance呢。

他可能离你非常的远,因为大家意识到就是在真实的游戏场景中,比如说一个小雕像,它这么大,当我的相机凑近的时候对吧,我需要绘制它很多很多三角形,但是它如果我在我20米之外的话,其实它可能只占几个像素。

那这个时候,即使我把它简化到最小的,128个船口,它也是本身也是不好那个精度过度的,而且呢你就像刚才我那个班尼的例子嘛,那个班尼我把它捡到了128个,那个就是那个那个chango的时候。

你觉得那个还像是那个兔子吗,对不对,作者可能也意识到这件事情了,他怎么办呢,他又用到了我们的传统的神器叫做imposter,这个imposter是我们在做l o d的时候,一个很经典的算法。

就是说我对于这些instance的话,诶我去进行12x12个,144,144个view进行采样,然后呢每个view下,我踩踩一个12x12个pixel的一张图,这个图里面的话呢。

我会存什么东西存在的这个abel啊,存在的normal啊,甚至存在的深度啊,那这样的东西的话呢,实际上就是当我这个因此离我足够远的时,候,我的整个nana的管线都不启动,我直接把in post往上一扒。

我的defs也是对的,我的d8 翻你的数据也是对的对吧,你后面的设定该怎么做就怎么做,其实我觉得这个方法其实说明啊,就是传统的这些lled的方法,其实在这么高级的现代管线里面,它还是有用的。

还是实战的东西,所以这是nana他做rendering的这一part好,那么其实呢大家可以看到,就是说用了这样的一套体系啊,这个overdraw,但是实际上一个真实的拿到的场景。

你可以看到就是那个红色高亮的区域,就是偶尔做比较费的,其实这里面他会讲的就是偶尔做啊,实际上还是非常的昂贵的,但是呢它对于整个这个nana的管线来讲,你不同的trango的尺寸。

它的偶尔做的这个瓶颈是不一样的,比如说如果你是small triangle的话呢,其实你会发现因为你go再小,我都要去采集你三个顶点的数据对吧,要进进进进行这种差值啊,百30个codation的计算。

然后还要去插值,要去采样,每个pixel我都得折腾这么一边,而且很多时候这个三角形如果过小的话,在一个pixel里面,可能好几个三角形叠到一起去了。

那实际上我的vertext transformation,那个transform还triangle set up,其实是变得非常的慢,就是说我们在这个visibility buffer。

后面的那一部叫jim concert,那个buff那一把是很废的,那么如果你三角形是个中不溜秋的话呢,其实你会发现就是pixel它在这个coverage的时候,他的肺是比较费,但是如果你全是很大的时候。

他最废的是什么呢,大家还记得刚才我们讲的那个,我们自己hike了一个64个比特的,那个就是depth对吧,那个天杀就很高级,但是呢它其实是有一个叫原子性计算的,这个要求,那原子性计算有什么特点。

就是我去写的时候,我去读读或者写的时候你就不要操,你就不要做操作了,那这样的话呢它会形成一个atomic bd对吧,所以这个呢实际上是就是那个啊,我们讲的就是说这一套他的rose rose方法的话。

会产生的一些性能的问题,我相信在未来随着硬件的优化的话,很可能我们不需要像我刚才讲的那样的,我可能不需要自己去hike那个software arrier,我甚至可能不需要我自己去high一个自己的。

z buffer的testing方法,因为换着我是n v d n n n m d的话,如果我相信这是未来的话,我肯定在硬件上给你解决了,对吧好吧,希望业界的发展,能够追上我们的引擎发展的步伐好。

那最后一个呢呃也不是最后一个,接着讲,就是哎当我们有了这么多的几何,我们有了这样的buffer,接下来来了一个大家特别容易忽视的问题,就是说我到底怎么去给它贴上材质,那为什么这件事情很复杂呢。

就是因为啊其实我们看到一个场景啊,就是在游戏里面看到一个场景,其实它是有很多很多的材质合成的对吧,每一种材质的话,它的texture它的数据都不一样,这里面这个例子,就是说你这样的一个nt的场景。

这个是不同材质用伪彩色表达出来,你就意识到这个材质是不一样的对吧,那这么多的材质你怎么去绘制它呢,诶那none night,他想了一个方法,是这样的,他说呢,我把每个材质i d。

把它变成一个depth的一个指值,这个就相当于说每个i d,它在这个在这个depth里的值是不一样的,然后呢他做一件什么事情呢,他就是我知道我屏幕上有多少种材质对吧,我每个材质绘制的时候。

我把那个材质i d做个z testing,就是这里面this test呢它用的不是小鱼,也不是大于用的是什么,是等于就是说你的深度等于我的时候,你这些pixel我才去绘制。

你就相当于是说每一个材质我扫过去,全屏的话,只有那些你的depth里面的那个呃mature,depth,等于我当前的材质id的这些pixel才会被绘制,哎你想想看这个事情的话呢,它既费有不废。

说先费的地方,比如说我这个屏幕上有50种材质的话,意味着我for screen要扫50次,对不对,但是呢它不废的地方是什么呢,因为这50次里面它对于每个pixel来讲,它只能是指50种材质的一种。

所以呢实际上我去那个非常复杂的做这个,这个做那个pixel shading的,就是大家知道在用的buff去渲染那个pixel,其实是很麻烦的,对不对,诶,我只会对于屏幕上的pixel的数量做一遍。

所以呢早期的not night用的就是这个方法,但这个方法大家意识到有没有问题了,就是说假设我的镜头里面有上百种材质,那我就要渲染上百个full screen pass对吧。

这件事情就算把这个屏幕上几百万个像素,做这个z testing,做这个50次,100次的话,这件事情的overhead,实际上并不像大家想的那么小,我记得以前跟今天跟大家讲。

就是大家我们做particle的时候,最容易犯的错误是什么,就是我画了很多透明的cod,然后呢在相机的镜头叠他个几十个上百个,而且每一个都是全屏那么大,其实基本上都绘制没什么贡献。

但是你会发现这个性能会下降的非常厉害,所以呢作者在最新的作品中,他就发现了这个问题,那现在的这个nana他是怎么做的呢,哎我这是我们最近在看的一个东西,就是说我为什么要把four screen qu。

来进行处理呢,哎我们为什么不用tod base方法呢,这个方法是不是很淳朴对吧,大家还记得我们在讲tairender,其实也提到过类似的思路,它很简单,就是把屏幕分成很多个,64x64的这样的一套。

那其实在每个top里面,它真正有的这个材质的数量不会那么多,对吧,那我怎么办呢,哎我假设用computer shader,把所有的ta我全部扫一遍,我先看讲这个啊,那我就可以得到一张表,这张表是什么呢。

就是说首先我虽然理论上我有1000种,1万种material,但是对于我当前的这个screen来讲,可能只用了100种对吧,我每一个每一个材质呢,我们叫做一个material slot好。

那每个match slot呢,我就在这个tale里面去检测,就是说这个tale里面只要有一个pixel,他是有这个材质的话,那我就把这个tab标记成啊,是yes,是一对吧,那我我用32个比特。

就是我一个数字是不是可以表达32个,太阳里面,我这个材质是否可信,那我把屏幕上的这个,因为屏幕分辨率无非也就是1080对吧,或者是那个就是那个22k或者4k对吧,那你的太阳的数量是有限的嘛。

那好那很简单,那我就就形成了一个array,就是对于每一种可见的材质,实际上我就生成了一个array,我就知道哪些tag里面,我这个材质需要处理的好,当我有了这样一张表之后。

我接下来可以做一件什么事情呢,其实也就非常简单了,对于每一个材质,我用了一次indirect桌括,你看着我也是画了无数个tale,但是呢我可以在computer shader里面。

把那些没有我这个材质的,这些tale全部给跳掉,唉你想这个事情是不是很聪明对吧,因为对于一种材质来讲,我只可能在部分的泰坦尼克见,那这样的话我一个桌括他,其实他每次呢是一批,一次性处理32个太阳对吧。

然后呢他一个屏幕这样快速的扫一扫,扫一扫,虽然你看着这个桌廓比较复杂,但实际上它非常的快,因为最费的是一个一个的像素,他这样的话一次性64x60是多少,3000多个像素点就直接过去了对吧。

所以而且他很多的tap可以直接跳掉,所以在最新一代里面的话呢,它其实是用tiled base的这种方法,对materia进行了极大的简化,这个具体的算法的话,大家去研究一下就可以搞得清楚,非常简单。

但是呢这也反映了,就是说我们用现在的computer shader,实际上我们可以把一个复杂的full screen运算,把它切成tell分而制止,其实在我们的很多渲染里面。

为什么tao base是有道理的,就是有个原因,就是比如说你这里面讲的是材质多样性,对不对,假设我场景里有上百个光源对吧,你也可以用类似的思想,就是说我每我虽然在整个屏幕上,我能看到100光源。

但是的话呢在每个套里面,我可能只能看到两三光源,所以每个套里面的,我的这个光的处理数量也就两三个,那你整体上的数量就会降下来,其实跟这个是一个道理,所以这个的话呢很显然能够极大地降低。

就是在材质比较复杂的情况下,它的绘制的复杂度,ok但其实这里面我再多讲一句,就是其实啊如果他的所有的texture和材质,采取的用的是virtual texture,这个思路。

就是说我整个材质全拍到一个,verttt里面的话,诶,我的材质的数量,是不是也可以进一步的下降对吧,其实这也是作者在他future讲的一点,就是我未来能不能给virtual texture结合在一起。

我个人觉得这个东西是verse consider,就是说很值得去思考一下好,那所以这就是它的这个材质的绘制方法,这个方法其实非常的重要,因为如果这个东西不解决的话,那你虽然做出了那么漂亮的几何啊。

但是呢它和一个就是真正的,我们叫做商业级的引擎,所达到的画面还是有比较大的区别的,因为我们一个商业级引擎所达到画面的话,它的材质是要非常非常丰富的对吧,artist是绝对不允许你说你限制。

我只是用一种材质的,那artist绝对要给你拼命的,那接下来这一part讲完之后呢,基本上就到后面了,后面的话呢我觉得这也是今天nut,我认为最后一个相对比较硬核的东西,就怎么做shadow。

大家想象一下这么复杂的几何,你做shuttle的话是不是非常的挑战,比如说对于gi就globa nation,对低频的间接光照来讲,反正你是低频嘛,所以呢我也无所谓对吧,所以大家可以发现,就是。

为什么none night可以跟lumen在一起做朋友,是因为lumen还是算了低频的间接光照,所以呢他也不一定要把几何做到这么细,这里面这是他们的内部的黑暗料理,我们就不展开。

但是对于高频的就是a光的直接的shadow的话,那你对于nana来讲的话,这就很痛苦了,因为那么高密度几何我怎么去渲染他的,达到我的要要的精度对吧,所以呢其实当我们要做shadow的时候。

shadow在很多时候他是个高频信号,所以呢他做shadow casting的几何的精度,要和渲染的精度是一致的,否则的话它就会出现我们不想要的,各种各样的很脏的artifacts。

那这个问题怎么解决呢对吧,那你用retracing好不好,但是的话呢就是说其实not net,它的这个几何的表达是非常定制化的,也就是对现代的retracing的硬件来讲的话。

他没有办法在他的那个bvh的架构里面,去表达我们nana的集合诶,这个地方的话,其实也是这一代显卡在打架的地方,就是比如说像nv的最新一个显卡,它很强调的就是。

你用我自己的micro mesh的这个结构对吧,你加很多细节没关系,我给你构建,我给你构建了他的b,然后呢你对于这种机器的集合,你也能做出trc对吧,但奈的说啊,你就是做不了。

我的几何是很很special的,大家如果仔细观察一下,哪来的几何的表达的话,确实是非常非常复杂,所以至少目前为止,我不知道怎么用real time,retracing的这个技术。

去把这个几何在这个显卡你表达出来,所以你既然不能去把这个几何在这个显卡,你这个表达出来,让他做retracing的话,我基本上是没有办法用retracing去算他的shadow,那接下来怎么办呢。

那我们先看这个最经典的shadow算法,哎我们这一趴讲的跟那个原作不太一样,就是说其实我认为他很多思想啊,实际上是源自于一些古典的图形学算法,就是其实shadow最大的问题是个采样问题。

就是说随着我的相机的远近近处,我希望这个信号采样的密度要高一点对吧,因为你可能光那边的一个一个,一个小小的一个,就是一个就是shmap里面的一个txt,其实对于我屏幕上的一个pixel来讲的话。

可能就是几乎是一对一的关系,但是远处的话,比如说我屏幕上的一个pixel,其实对相对外部来讲的话,可能是很大的一片区域,对不对,那这个时候呢,其实我可以用更低精度的东西,生成它的shmap。

所以呢我们会有一个,就是用多层次的l o d,根据你的view dependent,我生成这样的一个shut up的精度,那这个方法就是著名的什么,其实casket shadow。

就像我们前面在课程中给大家讲的,这几乎是现代游戏一个最经典的一个,shadow的这个方法,这个方法它的数学本质是什么呢,叫new dependent sembling,就是基于你的相机的位置。

采取不同的这个采样精度,去深圳shadow好,那你用这个方法之后呢,哎我们假设能不能做得更精致一点呢,比如说有个方法叫sample discp的map对吧,他意识到一件事情。

就是说你在在传统的这个coser shadow时候,是围绕着我的相机无脑的,一层层的变得越来越大,但是你其实真正眼睛看见的区域呢,就那么一点点对吧,所以你其实shua map。

你cask shadow生成了很多的区域,其实是无效的,大家如果真的实现过一次,这个casket shmap的话,你就会发现你的,比如说最后方圆2km的那个shadow map里面,你真正用到的区域。

真的就是那个一条的refresh,那个地方其实很多的选择tion,你全部是浪费掉的,所以有人就提出来说,我能不能根据your fan,真的在shut map空间里面的那条切线。

我有效的生成它的shmap对吧,这样的话也能够有效的去利用它的东西,其实当我们去这样去想这个问题的时候,就让我们意识到shadomp本质,shut mc本质是什么呢,是根据我的相机的视空间的这个精度。

去采样光空间诶,这个听上去非常的抽象啊,就是但是这其实是沙特曼不算法的一个,本质问题,就是说叫做为什么沙特曼有利,是因为相机空间对几何的采样和,这个几何在光空间对光的可见性。

采样是两个采样的频率是不一样的,所以会产生了像我们各种各样的artifact,我一直在讲说为什么我们要加个boss呢对吧,就是因为这个产业很不准确,所以我们要加上一点容错对吧。

大家还提出一种叫perspective shadow map,试图,在这两个这个这个这个这个这个两个角度,之间找到一个平衡,但这个这个算法8000年已经没有用了,是很古老的一个算法,大家不用管它好。

但这个时候呢,我觉得这里面就龙这个就是说,其实这个方法的话呢,它的分布就很明显会比硬性的casket,shut up会稍微的这个更合理一点,它会把更多的精度,放在我相机相对近的地方。

而在远处的话没有必要浪费那么多的精度,对吧好,这个方法是非常好的,那我们再接着讲,其实这里面的话我们必须要讲的就是,在在area 5里面,这个virtual map是这个方法,再往前一个很大的进步。

我不得不承认,就是说这个方法其实非常的了不起,就是说它是对于这个采样问题的一个,本质解决,就是说那如果我把我相机看到的这个世界,根据我的resolution对吧,我近处我的采样密度要高一点。

远处采样密度低一点,这是什么,这是个cp map,对不对,好,每个climap的这个区域,他在这个light space里面,我给他分一小块的这个shut map,一小块shut map。

但是呢这个时map的金部,不是以我的这个世界空间的大小来定的,而是以什么呢,你在我的视空间里面的大小来定的,这样的话远处一大片区域,它在那个沙滩漫步里,只需要一小片的这个几何去表达啊。

一小片的那个那个那个他要去表达,金属的话呢,哎他这个tell就很小的一块区域,在里面都有一个表达,那这样的话是不是我们完成了对shadow map,这个空间的采样的最大化的利用,对不对,而且这个东西呢。

还有一个更大的好处是什么呢,就是假设我对这个空间的clip map生成啊,大家还记得我们在前面讲lumen的时候,一直在讲一件事情,就是说诶我们的value magic quemap对吧。

它并不是连续生成的,它是一格一格生成的,这样的话呢我对空间的这个划分的话呢,它是在worth space为角度进行划分,那这样的好处是什么呢,当光不动的时候,我相机不动,那这个沙雕map是不是不用更新。

全部在这对吧,当我在往前动的时候呢,哎我只有部分的东西需要更新,而很多东西其实我不用更新的,你想这个这个方法是不是特别的漂亮,所以virtual map它的最核心的思想就是说。

我啊充分的把shadow map切成一小块一样,确保每一小块,它的这个采样率,是和我的视空间是高度对应的,那么而且呢当你的光不动的时候呢,它其实是可以储存下来的,cash下来的这一点的话其实非常重要。

大家想象一下,我们在游戏的世界里面,很多时候主光源是基本不动的对吧,太阳就是那个角度,所以的话哎,我这个地方的数据的成功率就非常的高,那么实际上的话呢nat它这里面的shadow。

因为它的几何密度实在太高了对吧,那他怎么办,他其实也用的是这个virtual shadow map方法,它就是对于每一个光源对吧,我就给死了一个16k升,16k的一个大的这个沙袋buff buff。

那么这样的话呢,就是说我就会去算,我的每一个在试空间里面,你看到这里面不同的颜色,就表示你相机看过去,这里面对应的是那个不是版本的一个top,所需要的集合,那么这个时候呢,我就可以使我算这个。

这个这个这个每一小块的这个shadow的时候,我就在那个不是沙滩外面找到那个tell,去判断它的光源的可见性,但这里面有个有意思的这个细节,就是说如果你不小心你放了一个点光源。

我们的rs特别喜欢在里面放点光源,放一盏灯对吧,顶高原呢它对世界的投影是六个q,反正我们看了一下那个arl的源代码,就是你放了一个点光源,它会生成六个16k乘16k的,不是ture的mp,我个人一想。

我说哇我的天呐,这个实在太废了,但没关系吧,反正就是说他确实是能够解决这个问题,那么其实你对不同的light light type的话,你会发现他对这个时空间的几何,这个这个这个tell的划分。

它是不一样的对吧,如果你是这个spotlight,你是这个就是这个点光源,你是方向光,它的划分就是不一样啊,你可以发现就是比如最它的左上的那个啊,就右上那个点的话,就是一个方向光源形成的这样一个跑分。

那么这个方法呢看上去是非常的复杂,但实际上这些配置啊,他的allocation每一次只要分配部分的东西,如果你的相机和光源都不变的时候,它不用重新allocation对吧,当你的相机动的时候呢。

它实际上只需要更新这里面部分的tad的,上来map就可以了,就相当于我们以前做cascade的话,我们要画一个很大的一个一大片集合,但今天的话我只画一小片那个几何,我跟光相关的那个。

它其实那个锥很小很小,所以大量的物体都会被cut掉,所以它的更新效率是非常高的,那么这个shadow map的配置,这个在washutmvm里面的话。

它invalidation的case其实是非常简单的,第一个你相机移动对吧,但是呢你相机移动如果是smooth的话,它实际上只有部分的配置需要更新,当你的光一旦动了之后,那没办法。

所有的沙雕map都要变,所以说当你用vtusha map的时候呢,那尽量选择这个主光是不动的场景,所以大家去看那个u v5 的那个demo的时候,很多时候那个光都是固定在那儿对吧。

那个那个最酷的那个山谷的那种,那个光就直直的就射下来了,那么还有就是说这个节目水本身动的时候,这个筛掉也会变,但是呢你也可以把这个变化更local一点,那么还有很多一些一些一些一些原理,就会产生变化了。

那么我们这里面自己是我们课程组,自己做了一个实验,就是说我们搭了一个场景,然后呢,当我们的光就是当我们去推进相机的时候,主观不变的,你会发现那个那些绿色的那些切片,那些那些山,我去山版的那个套。

它基本上是不用更新的,只有少量的那个红色的那些套,需要更新一下,大家发现没有,他其实需要更新的地方是非常的少,这也是这个方法的巧妙之处,但是呢它这个方法有一个很大的好处,是什么呢。

它所生成的shadow的质量是非常非常高的,这比传统的cascade的shadow质量要高,而且呢以前casket shadow map有个问题,就是说当我相机移动的时候。

因为我不同的层级之间的shadow,它是有个transition的嘛,你可以很明显的感受到,那个shadow是有一个popping的,就是说诶我从l d0 的shadow map到d一的时候。

到l d2 的时候,你可以看到邦德瑞那个几何是一个popping的,那个那个shadow是个popping的,但是用vr sem的时候,你可以发现它的shadow基本是很稳定。

而且这套pipeline的话也可以非常柔和的,非常naturally的跟那个nt结合在一起,所以呢这个我也是认为,就是说这是由于我非常了不起的一个发明,我个人认为是啊。

有可能应该是大概率可能会取代掉casket,sha map的下一代的shadow的技术,因为从他的数学原理上来讲的话,我觉得还是用那个词叫做非常的elegant,非常的优美,非常优雅对。

所以说呢其实就是说这个virtual smap的话呢,也是一个大家如果想去理解nas,整个的rendering pipeline的话,一定要去理解的一个基础算法,ok好,那最后呢其实是作者讲了很多了。

就是说啊我们这个nana的技术对吧,当我们去处理这样的开放世界的时候,我们就可以进行streaming了,多么的了不起啊,但其实我个人觉得这里面的,有些很大部分的实现的话,还是比较自然而然的。

因为你既然已经构建了这样的一个b vh,啊,这样的一个tree的结ree的结构的话,你可以很自然地根据you dependent对吧,我可以只露的一些hello,我的降水。

然后呢我再去下面构建它的这个lol的降水,他会把这个降水的话呢,构建成一个一个的page对吧,这样的话一块一块的往里面加载,这个其实在我们的很多的系统里面,是一个很常用的一个技术对吧。

那么另外一个当然了,这个技术对他来讲的话,就是说诶我终于把几何像virtual text一样,可以叫用到即下载,不用急不下载,这个如果我想做一个基于这么nt的技术,这可能是我有必须要用的一个技术。

这个我认为还是有道理的,那么另外一个的话呢就是拿他的一个痛点,就是说哎呀,我的这个数据量实在太大了对吧,那他就要对数据进行压缩,其实它的压缩呢我个人看了一下嗯,还是比较好理解的。

就是说对于内存中的数据呢,它一般用的是quanzation,什么叫quanzation的话,我记得我在之前讲到那个,好多地方都讲到这个概念对吧,表现动画就是说原来你是浮点型的,我把你把把你变成定点型。

比如说你的vertex的位置对吧,我如果知道一个cluster的这个,这个这个bbox的话,实际上我这里面的这个很多的位置,我实际上是可以把它,就是这个那个把它给定点化了,比如说像罗al对吧。

我不需要精度那么高,我也可以定点化uv,也可以定电话对吧,这样的话我可以节约出来我的存储空间,那么这个的话好处就是说你访问他,对它进行反向的低矿的效率都非常的高,那么对于这个存储在磁盘上的东西的话呢。

他就用了hardware lz decompression对吧,lz compression这件事情本身啊,应该说是最效率最高的,而且很多硬件可以支持的一个压缩和解,压缩算法。

应该是microsoft的和啊,md还nvidia的dk里面有一个叫做direct storage,就是说你从磁盘中读一个数据,不用过cpu,不用过主内存,直接可以读到。

那个就是我的显存中间去读的数据过程中,我还可以自动地对数据进行解压缩,这个解压缩算法如果没记错的话,就是la的算法,这样的话实际上我就可以实现,就是比如说像在我记得如果没记错,在cs上就有这个东西。

那我就可以实现那个哎非常多的数据,在磁盘中,快速的,这个磁盘,本身,也是那个就是那个那个那个,就是那个这个那个叫什么h d d对吧,不是hdd,说错了,是那个就是s s d,是我的那个就是固态硬盘。

我的数据可以直接到显存里面去,而且到显存的过程中,它自动就被解压缩了,那这样的话呢就可以被解压缩,所以我觉得他提到的这个数据的streaming啊,无限可以扩展的世界的话。

这也是一个大家很自然的一个想法,当然了其实也讲到了很多的时间细节,比如说为了提高lz压缩的这个效率,他就想到了说诶,我要在里面加一些padding的data对吧,然后让他那个lz的字典的命中率更高。

这样获得一个更高的这样压缩效率,其实原作者其实还是分享了很多小的,trick的,也就是说整个nana在我的看法来讲的话呢,就是说,首先是个非常了不起的一个工程思想,那么另外一点的话,就是说。

作者确实他们这个整个团队在工程上,把这一代硬件的性能基本是压榨到极致了,所以这里面大家如果想学这个,就是一些高性能的编程啊,这在他的实践中可以学到很多,有意思的东西好,那么其实的话拿来的话呢。

它本身它的主要算法就是这些东西对吧,这个很巨大的数据量,我在这边整个跑通了对吧,那今天这节课基本上全部讲完了,我今天还是老问题,就是当我把所有的ppt写完之后,我发现我的时间已经out了。

我其实很想写几句很感性的话,就是说哎呀这个这么复杂的技术,到底在讲什么东西,但是呢我后来觉得用这句话,可能能代表我对这个这个未来的理解,就是说其实下一代的游戏,那你必须要有一套全新的几何管线,能够处理。

能够憨豆这些复杂的事件,那这里面的话呢,我们也给大家分享一个,我们课程组制作的一个小视频,这个视频是什么呢,就是这是nas demo里面,当我们用相机钻下去看你看到的那个山谷。

它下面有多少层的这个几何的细节,层叠而成,所以大家可以想象,就是现代的计算机的这个处理能力之强,就是这么多层,就是达到像素级精度的三角形,一层一层一层叠在一起,形成了我们所看到的这个,丰富的几何的世界。

所以的话呢,这也是我觉得我们的这个就是未来,顶级游戏作品的一个未来吧,就是我们必须在一步步的逼近,这个电影级的影视级的画面,这也是我们一代代游戏人,游戏引擎人的一个梦想,好,这也是作为我这个104课程。

最后一趴的这个感想,好的谢谢大家,那接下来呢我们就是q n a的环节,q n环节之后,大家不要跑,我们会有我们课程的花旦好不好,ok那最后呢就是给大家分享一下,我们这边课程的reference。

这边看的reference reference不多,因为他的资料并不多,其实我们大部分的东西都是肯代码,啃出来的,ok好那就是也感谢我们的团队,就是真的非常的辛苦大家,这个在这个过去的一个月里面。

真的花了很多的精力把这个东西给啃透,那好的,同学们有没有什么问题,第一个问题,同学问我说nana的这种无限精度的几何,可以无无极渐变的这种几何表达方式,会不会成为未来几何表达的主流方式啊。

就是说我觉得确实非常的promising,就是真的很有可能,但是呢其实这里面的话,有几种不同流派的方法,大家也在compete,比如说null本身是做了大量的工程妥协嘛,而且他这个算法本身非常复杂。

它本身对于比如说啊skinny geometry,就是带有比如说我们大量用的角色,他没有办法表达对吧,对一些动态的集合它也比较难以表达,那么但是的话呢,就是说确实它让我们第一次在游戏里看到。

这种实时的cinematic级别的,这样的几何细节,所以其实所以呢我我们在猜测就是在未来,随着硬件的发展,可能有一些更简洁,更elegant的方法会成为主流,因为其实我们观察整个就是引擎行业。

过去几十年的发展,就是一个新的思想出来之后,都要经过好几代的,不同的就是开发者共同去迭代,形成一个共识,形成我们一代的papi,就像我们讲的deer shading对吧,也是经过了很多代的迭代。

才能形成我们现在这样一个成熟度,那么反过来讲,厂商也在疯狂的努力想去解决这个问题,所以的话呢我觉得这两条路,两条腿到底谁能够跑得更快一点,我觉得在未来几年的话,大家会看到非常精彩的一个,你追我赶的过程。

所以现在的话呢说这件事情大局已定的话,还为时尚早了一点啊,第二个问题是大家问我说,not let的应用空间是不是不止游戏领域,这个答案是一定是yes,因为其实现在可以发现。

就是很多我们用游戏引擎做的这个渲染,已经可以逼近于影视级的需要了,我们已经看到很多的,比如说虚拟拍摄,他就用这样的一个nasa的技术,就做一个巨大的led的屏对吧,上面有上亿个像素在里面。

绘制的山和水非常的真实,然后演员在那个l e d屏前面,就直接进行表演,然后一起拍摄下来,那个感觉就像你真的在实景中,其实在影视啊,在游戏之外的各个领域里面,比如说在这种病对吧,比如说像智慧城市这样。

或者建筑的这种光照仿真里面的话啊,建筑可能不需要,就是我们自然场景的表达吧,所以很多时候都需要拿来的这样的一个技,术好的,那我们今天的问题就到这吧,我们的games 104课程,到这一趴就完美的杀青了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

也不见不能叫完美吧,说实话还是蛮感动的,因为这200多天吧,就是从一开始决定开始做这个课的时候,只是一个冲动,但是没有想到冲动的代价是这么的惨烈,然后就是确实大家坐进去之后,觉得这是一个一种本能。

或者说我们觉得是一份责任,其实这个课程实际上准备过程中,我觉得我们有蛮多的遗憾,就是很多东西没有做到,我们想要的这个结果,我们很希望说能给我们再来一次的机会,把很多课程讲得更好。

但是呢我们确实尽了我们的权力,那我觉得其实为什么要做这门课的话,我觉得用一句话形容,就是每一个想做引擎的同学,他的心里都是有光的,所以我们想把这种光传递给越来越多的人,让大家真的敢于去构建自己的世界。

真的去探索这个技术的最前沿的东西,其实我们自己也在这个道路上,其实很多的挑战很艰难,但是的话我觉得把这份光,这份热爱分享给所有不肯放弃的人,我们在一起,然后我们争取以后再见,我们后面跟大家一直在一起。

好谢谢大家games 104,先我们说个拜拜。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值