GAMES 图形学系列笔记(二十三)
GAMES101-现代计算机图形学入门-闫令琪 - P5:Lecture 05 Rasterization 1 (Triangles) - GAMES-Webinar - BV1X7411F744
亲爱的观众朋友们,大家好,欢迎来到咱们这个现代计算机图形学入门的第五节课,然后咱们从这节课开始,这个之前的变换就已经说完了,咱们开始把这个呃三角形的光栅化开始这个呃说一下。
然后这应该是呃整个咱们第一块的这个呃最重要的部分了,大家可以看到,其实这个如果大家注意我们每一页这个这个ppt啊,封面,每一个封面嗯都会有这么四个图,然后我们的这个课程主页上也有这个嗯。
就是对应这四张图,分别对应的就是咱们这个课要讲的四个主要内容或主要部分吧,咱们第一块也是大家看到左下角这个这两个车子啊,然后阴影这块这块就是我们要给大家说的这个光栅化成像。
然后这个也就是相当于实时的这个应用,这些它们生成这个图像所所着重使用的方法,然后咱们前面几节课呢花了点时间讲了一下这个呃变换,然后这个变换呢相当于是基础,然后应用这些变换。
咱们就最终可以把这些三维中的场景给画在屏幕上,那咱们这节课就开始说这个事情,好吧啊,没问题,那这个今天咱们讲三角形的光栅化,那么在这个啊正式进入课程之前,我们先这个宣布几件事情,第一是这个作业零。
截至目前这个收到了188号提交,这我觉得真不容易,这个课咱们这个又不要求大家做作业,然后大家还这么积极,然后挺好的,提出表扬啊,如果说呃你希望这个把作业零这个提交。
但是中间遇到了一些各种各样什么技术困难呀,然后这个比如说虚拟机不能跑啊,然后这个编译出现各种各样的困难,而这些没问题,是正式作业,零的目的是让你这个让大家在之后的这个作业中,不再会出现这么些问题。
好吧呃挺好的,那么呃好,那这就是关于作业零啊,另外作业灵会不会做批改,大家就提交了就提交了好吧,然后这个嗯从作业一开始,这算是正式作业,然后今天呃这个理想状态下,咱们今天会把这个作业一给放出来。
然后以后呢就是每个星期会有一个作业,然后嗯这个作业啊,或者说从这个作业一开始吧,咱们每个作业都分为两部分,一个算是基本要求,另外一个算是提高部分,就是大家作为自己这个兴趣爱好在上面再加入新的功能。
这这两部分呢嗯会被分开的这个给分,然后如果如果这个课最后咱们结业,大家需要一个证书或者干什么,这个我们会这个以这个基本要求为主,所以说这个提高要求呢大家用来这个提升自我。
然后这个这个感兴趣的同学多做一些,大概就是这么一个要求,好吧呃好,然后呢,那这个有同学,我看到现在现在同学们这个很踊跃的在这个课程bbs上面提问,这个非常好,然后有一点呢就是说嗯跟大家说一下。
就是说呃就是考虑到这个大家问问题以及回答问题的这么一个效率上,还有效率啊,就是说呃大家在发问题之前把这个问题这个想好到底是什么问题,然后我做了一个什么样的事情,得到了一个什么样的这个结果啊。
到底这里出了什么问题,就是说把这些事情描述清楚,这样也方便我以及助教呃,同学们在这里这个帮大家这个呃这个答疑解惑好吧,然后这是一个,然后另外一个是我看大家这个有同学在在用我们games的这个这个群。
在里面问这个课程相关的问题,这个我现在正在和这个呃技术秘书同学以及呃助教同学们在思考,我们要不要这个建立一个专门这个用来用来探讨这个作业嗯,和问题的这个群,专门专门用于这节课。
这样的话省得大家会这个因为讨论而这个错过一些games的其他重要信息,比如说这个有一些好的讲座或者是其他的通知之类的,好吧,这个我们正在呃这个这个思考中好吧,那这个呃是关于bbs。
那么今天今天要给大家讲的这个这个课啊,相比于上节课,那这节课太简单了好吧,然后这节课大家就是这个嗯,听下来我相信大家一定都可以听得明白,那么上节课咱们说了什么呢。
咱们上节课主要说了这个观测这么一个变化对吧,那么所谓视图变换,就是在利用这个呃这个摄像机和物体的相对运动关系,咱们始终把摄像机从任意的一个位置,然后移动到一个这个经典的位置对吧,呃在这个原点。
然后呢看向负z并且向上方向是y对吧,然后把其他所有物体都和这个相机一样的移动,然后这样就可以保证这个我会把这个模型变换应用在所有的模型上,然后把所有的这个视图变换也应用在所有的模型上,然后在这个之后。
我们就知道这个所有物体都是由一个这个呃标准位置的,这个相机看过去,然后我们就需要把它给投影成一个呃照嗯,投影成一个照片对吧,从三维投影到二维,那么我们提到了两两类呃,一类叫做这个正交投影。
一类叫做透视投影,然后这个呃它们的区别就是,正交投影是把这个直接把这个深度信息忽略,然后或者可以理解成相机放在无限远,然后投四投影呢相当于是可以达到一个近大远小的效果。
然后我们还提到说如何去推导这个正交投影矩阵,以及说这个嗯透视投影如何通过先变换成正交投影,在这个这个投影过去对吧,然后就是说我们把这这些举证着重推导了一下,那么大家这个回到一个这个高一点的层面上来看啊。
这个整个这一块叫做观测,这个变换,变换完了之后,无论如何,最后我们得到所有的这个物体,在场景里,所有的物体都会被变为这个呃-1~1的三次方,这么一个经典的这个立方体里对吧,然后呢这个下一步是什么对吧。
这就是我们今天需要回答的问题,说这个在做完观测矩阵之后,所有物体都已经在这个嗯经典的-1~13次方这么一个空间里,下一步我们应该怎么办,然后当然大家知道下一步就是要把它给画在屏幕上,那么怎么画对吧。
这一部就叫做光栅化或者rusty zation,这就大家看到了今天的这个呃两个主要话题,然后如果咱们有时间,咱们把下一节课的这个呃,涉及到这个遮挡与这个呃这个可见性这一块儿也说一下啊。
然后因为下节课内容其实相对比较多,然后咱们这节课尽量能够改正一点好吧,那这就是今天的这个内容,那上一次呢咱们把这个透视投影转化成正交投影,这部已经已经说明白了对吧,然后这个大家可以看呃。
右上方这个示意图,那透视投影转换成正交投影是要保证什么呢,然后它的大小,那么大家应该记得说在这个正交投影里面啊,我们如何定义这个三维空间中的这个长方体对吧,我们用它的这个x轴的覆盖,也就是左和右。
然后y轴的覆盖这个这个下和上,然后这个呃这种的覆盖,也就是远和近这么几个数字来表示这这么一个立方体对吧,我们需要六个,然后呢呃这里既然远和近,咱们这个用透视投影和正交投影表示都是一样的,咱们不用管它。
就是near和far或者n和f这两个值,我们认为我们知道,那么呃在做这个透视投影的时候,我们是要把这一个frost变成这么一个呃长方体,那么我们如何定义这么一个frost对吧,或者说这么一个视锥。
就是大家看到的这么一个近大远小这么一个一个一个呃形状,然后然后这个如何定义呢,呃其实很简单,大家看下面这个示意图,就是说我们从这个呃摄像机出发,我们看向某一个区域。
然后这就好像大家在看一个这个显示器一样对吧,显示器有它的这个呃长和这个宽和高,然后我们可以定义一个宽高比,也就是叫做这个嗯aspect ratio,然后这个宽高比是什么意思呢。
就是就是它的宽度除以它的高度,然后就好像说我们说一个屏幕是什么,这个四比三的,这是早期的或者现在的ipad对吧,或者说16比九的指的就是这么一个信息,那么我们同样可以这么来定义。
就相当于是诶我摄像机摆好了,往一个方向去看,然后我试图看到的一个区域,它的这个长宽比我们把它定下来好,这个这个是可以定义的,然后呢我们还需要定义另外一个这个概念,这个如果大家这个玩相机啊,大家会知道。
然后这个这个叫做呃这个视角,然后呢或者叫做field of view,就是就是表示了什么呢,表示就是就是你可以看到的这个角度的范围,就是说嗯大家还是看这么一个例子哈。
假如说我们在呃盯着从一个这个相机盯着这么一个屏幕去看,然后我们这个连出两道红线的,这两个红线分别从相机连到这个屏幕的,这个上面有一个边的中心和下面一个边的中心。
然后这个中间所夹的角度就是两条红线之间所夹的角度,我们就管它叫做垂直可视角度,这然后这个角度正常是用来这个定义,我看到的这个世界啊,就是说这个我是用什么样的相机看到的,大家都知道这个相机有很多种。
因为这个比如说大家要拍这种近距离的物体,大家需要用到一个这个呃叫做广角的相机,所谓这个广角其实就相当于是这个可视角度会比较大对吧,然后反映在这个frost上,就相当于他张得比较开。
他一开始从零迅速就可以张到一个非常大的一个范围,然后如果他这个呃垂直的可视角度叫做这个field of view,然后它比较小,那相当于它它这个开口比较小,然后这样的话就相当于这个透视投影就越不明显。
就就就是越像什么呢,就是越像这个这个正交投影对吧,但是这样一来你可以这个这个很容易地拍到这个远处的物体对吧,然后呃这就是我们用来定义这个嗯透视投影,它这个视锥需要的两个概念好吧,一个是长宽比。
一个是垂直的可视角度好,那没问题,然后嗯这里是这样,就是说有一些这个这个图形学的这个呃图形学上面,特别是涉及到大家打游戏的时候,这个这个呃会涉及到一些这个水平的可视角度,这两个都是可以相互转化的。
没问题吧,就是说通过这个长宽比,然后通过这个垂直的这个可视角度,我们当然可以推出这个水平的可视角度,那也就是什么呢,就是从这个相机我连出两根线,这两根线分别连向左边和右边的中点对吧。
然后这两条线形成的一个角度,这就是水平方向的这个这个可视角度,所以这都是可以的,那么嗯有了这么两个概念之后啊,这个长宽比和这个呃垂直的可视角度之后呢,我们就可以把这两个概念给转化到。
这个和之前咱们定义这个空间中的长方体,就是用于做这个正交投影的这个长方体呃,这个转化成同一个概念啊,怎么做呢,大家可以看到这么一个示意图,那咱们在某一个方向上放上这个呃,某一个位置放好了这个摄像机。
然后往一个方向看,大家可以看到,如果我们从侧面嗯去这个看,我们这个是这个事件来说,就是说我们会看到这么一个三角形,还是跟之前推导一个一个意思哈,因为我们想想的是,这个相机是往负z方向的嘛对吧。
所以这个距离是n的绝对值,然后这样呢我们又知道这个垂直的可视角度,那可视角度我们刚才说了,是那么两条红线连上面一边和下面一边的中点两条线,他们的家教,那也就是说垂直的可视角度除以二嗯。
这里才是这个这个我们所看到的这么一个三角形,它对应的这个这个呃张开的这个角度,然后嗯那大家立刻就会可以看到一个这个呃三角形和三角函数关系,对吧,如果我们取它的这个呃tgent这个角度的tgt。
也就是这个垂直角度除以二,然后这么一个角度tan是什么呢,是右边的这个呃高度的一半去除,以这个这个呃呃near这么一个距离对吧,也就是说这个右边的这么一个式子就是这么定义的了。
那么呃右边的这个呃怎么说呢,就是说我们把这个呃可视角度如果知道,我自然就会知道这个嗯怎么说这个屏幕的一半的高度,也就是这个top是多少,也就是相当于这个呃这个屏幕的最高点,然后它对应的y的这个值呃。
应该就是就是我们算出来这个t对吧,然后然后呢那屏幕的最低点对应对应的y就应该是负t好吧,然后也就是说我们如果要定义空间中的一个长方体的话,那么这个b就应该等于负t,那同样道理水平方向咱们也可以直接来算。
为什么呢,因为我们知道长宽比,我们知道这个这个知道这个这个高度对吧,知道高度这个总共是t,然后那么他们的这个这个水平方向的宽度就应该是这个呃什么呢,就应该是这个呃t去乘以这个宽高比。
就可以得到它的这个呃可以得到它的宽度了对吧,那也就是说这些概念都是可以相互转化的,那么这里也就是告诉大家,正常情况下,如果我们要定义一个视锥的话,很简单,我们就只需要定义一个垂直的可视角度。
定义一个这个宽高比,然后这个嗯其他的这些都可以自动把它给转化到,这个我们定义正交投影的这么一个呃,远近左右上下这么几个概念上去好吧,然后这里就是就是这个简单说一下啊,这个应该挺容易的。
那么我们上节课停留在这个呃,mvp也就是model view projection做完了之后对吧,大家都知道这个做完了之后啊,model view projection做完了之后呢。
呃所有的物体都会停留在-11的三次方,这么一个经典的这个这个立方体里面去对吧,然后呢嗯不管怎么样,大家可以看到这个我是做正交投影也好,然后最后它会出现在-11的三次方,我要是做透视投影的话。
先做正交呃,先做这个转化到正交投影,再做正交投影,那最后肯定也是-11的三次方,那么自然而然下一步咱们就要知道要这个-11的三次方,这么一个立方体怎么画在哪儿呢,大家都知道要把它画在屏幕上对吧。
那么嗯既然是要画在屏幕上,咱们这个应该要先这个嗯把这个屏幕这么一个概念给定义好对吧,然后什么是屏幕呢,对于图形学来说,咱们把它抽象的认为是一个二维的数组,然后这个数组中的每一个元素是一个像素对吧。
这个其实好理解,比如说大家看到这个屏幕,大家都说分辨率是多少的对吧,比如说是1920x1080的对吧,就表示有这么多个这个像素,并且这么多像素形成了一个二维的数组,然后啊那我刚才既然提到这么一个数。
这个数字对吧,1920x1080,他们的这个也就是这个屏幕的大小,我们这我们管它叫分辨率对吧,这个嗯要么是这个比如说1280x720,我们管这个分辨率形象成为720p,然后如果是这个1080。
1920x1080,我们就管它叫1080p,当然还有更高的叫做2k或者4k对吧,这些就表示了我这个像素的多少,这个就是啊就是它的这个呃分辨率好没有问题,然后呢嗯屏幕是一个典型的。
我们管它叫做光栅成像设备,那么所谓光山啊,就是这个ster这个rua是什么意思,我们平常这个经常说光山话,就是rust orization啊,那么其实这个rua是在德语中啊定义的一个一个一个一个词。
它其实就表示屏幕好吧,然后那么光栅画也就是restaurri是什么意思呢,就是说我们把这个定义为嗯就是呃把东西画在屏幕上,对不对,把这个名词变成动词,把东西画在屏幕上这么一个过程就是光栅化的过程。
那么以后我们就这么说好吧,然后呢呃我们多提一句,我们刚才既然提到像素对吧,大家都知道这个屏幕上有好多像素,然后呢这个像素首先它的名字的由来是叫做picture element。
然后大家把它缩写成pixel这么一个说法啊,然后这个呃像素当然其实挺复杂的,但是咱们在这门课里面,我们把它认为啊是一个一个的这个小的方块,然后每一个方块它内部的颜色都不会有变化。
也就是说要么整个方块是这个什么样的一个,比如红色吧,然后要么整个一个方块是完全相同的,一个白色或者黑色或者什么,就是说像素已经是最小的单位了,在这个里面不会有任何的变化,咱们这么理解,当然这是不对的哈。
咱们之后会给大家在这个看到这个课的最后,大家就会看到像素远远比这个要复杂,但作为一个抽象,咱们这么理解没有问题,然后呢这个嗯一个像素它可能会表示不同的颜色,如果我们认为说这个这个啊它表示的是一个灰度。
就是说从这个黑到白,那我可以把它划分成若干等级,正常情况下大家把它划分成256个等级,然后呢嗯这个就表示了,比如说零等级零,我就表示它完全是黑的,然后等级255,我就认为它完全是白的,那么呃同样道理。
这个我也我也可以用三个不同的数字,然后分别表示这个红色,绿色和蓝色的这个这个强度的等级,那么它组合在一块就可以形成各种各样不同的这个颜色,所以我们认为一个像素类的颜色都可以用rgb 3个值来表示好吧。
然后同样道理一个像素内颜色不会发生这个任何的差异好吧,那这里就是简单的定义一下我们这个屏幕,然后呢呃在这里呢我们先把这个这个呃屏幕的空间也给定义一下,那什么叫屏幕空间的呢。
其实就是相当于我们在屏幕上建立一个坐标系对吧,然后这里呢大家如果看这个虎书,他自己当然有一套定义的方案,那咱们自己也有一套定义方案,那大家可以看这么一个示意图,好吧。
假设我们现在看到的这个屏幕的左下角就是这么这么一个坐标系,那么呃就是我们认为屏幕的左下角是圆点,屏幕空间的原点,然后向右是x,向上是y,那这样的话就相当于是呃我们可以定义这么一个这个坐标系。
从左下角出发的,然后x和y,所以任何的这个屏幕中间的一个点,我都可以用x和y来表示,那么有一些规定,这些规定当然是我们就是说平常这么用,然后就约定俗成了,并没有什么特殊的意义啊。
就是首先我们定义这个像素对吧,呃我们这个像素呢这个它的坐标,或者说我们把它定义成这个这个这个下标,或者说管它叫这个位置或者什么,就是说呃管它叫index好吧,然后就是说像素的这个坐标呢。
我们认为它都是写成xy形式的,然后呢每一个像素它是一个小方块对吧,然后我就用一个整数的这个坐标来描述它,比如说大家现在看到的这个这个蓝色的这个像素啊。
咱们就可以用这个呃二一这么一个呃坐标来表示这个像素啊,大家可以向右数对吧,从零开始对,然后呢,呃我们认为这个这个呃像素都可以通过这么一种这个坐标来表示呢,那么所有的像素如何来表示。
就是说如果一个屏幕我认为它的分辨率是with成height,那么所有的像素那就是从001直到with减一乘以hiit减一这么多,这个这个可行的这些坐标没有问题,那咱们认为从零开始吧对吧。
所以它的宽度就是with这么多个像素高度,自然也是一样,没有问题,那么我们再继续定义这个事情,就是说呃像素大家可以看到,虽然我们用的是整数的坐标来描述它,但其实这个像素的中心在哪儿呢。
大家可以很明确的从这个蓝色的这个这个像素可以看得出来呃,这个蓝色的像素它这个是二一这么一个坐标,那么它实际的中心是2。5和1。5,没问题吧,所以大家如果看这个中心,它在数轴上。
它的这个到底应该是什么坐标,咱们可以这么看,那么对于任何一个像素来说,那么它的其实中心他应该准确的在x加0。5和y加0。5上对吧,那这也是咱们这么一个定义,那么既然这么定义了。
那咱们考虑到一个像素它会覆盖一这么宽度对吧,然后这个就在x和y上都覆盖一,那么咱们整个屏幕会覆盖多少呢,如果我认为整个屏幕的宽度是with,也就相当于有with这么多个这个呃像素每个像素占一。
那自然就是从零到with,然后这个这个高度也是从零到heat好吧,那咱们这么一定义,这样,这样的话屏幕空间就非常清楚了,那么呃大家可以想象,那么我们现在要干什么呢,啊记得吗。
咱们现在有一个这个-113次方这么一个立方体,咱们要把它给转化到这个屏幕上,那自然要做一个从这个-113次方,然后到这个屏幕也就是零到with乘以零到height这么一个空间的一个变换。
那么这就是我们之后要做的事情,呃,大家可以看到这个示意图上呃,右边这个示意图,然后-113次方,我们要把它映射到屏幕空间,然后呃在这里呢会有一个问题对吧,这个原本呢它在-113次方。
它可不是有一个z嘛,也就是说是一个三维的,首先仍然是三维的坐标,我映射到这个屏幕上,那我怎么处理它的这个z方向的值很简单,暂时我们先不管它对吧,这个z自然而然它之后有它的用途,咱们很快就会说。
那么只盯着x和y来看,那就简单了,x和y原本是-1~1的平方对吧,然占据这么一个这个这个正方形,咱们现在要把它拉到0x0到with乘以零到height对吧,那这个太简单了对吧,那这个嗯怎么做呢。
我那我就先把这个呃-11,-11给先给拉成这个让它的宽度是with,让它的高度是height,那么这个怎么做呢,那我们知道原本来说啊,-11-11,它是多大呀,还是这个宽度是二,高度也是二对吧。
我把这个宽度和高度都先除以二,然后再乘以对应的位置或者height,然后这也就是大家看到的这个这个变换啊的呃,左上角的这个3x3,其实大家可以看到对角阵,然后在这个宽度上呃,把它变成with。
高度上把它变成height,然后变完了之后呢,大家别忘了这里中心还是在零零这里,但是我们发现这个呃不是这么回事对吧,我们要把这个呃我们要把这个屏幕空间,他的这个呃左下角定义在原点上。
那也就是说如果我原本这个中心是在零零,那么我要把中心移到它该应该在的这个中心呃是多少呢,就是宽度除以二和高度除以二,咱们回来看,就是说呃这一页上,假如说这个屏幕就这么大,4x3啊。
然后那么它的中心就应该在这个位置,那咱们应该要把它这个之前先给缩放了的这个-1~1,像大小已经一样了,我们把中心从零零移到这边去好吧,所以就是说我们这里要做这么两个操作。
那当然可以写成一个简单的这个变换,那么这个变换就被称为视口变换,也就是相当于是把这个-1~1的平方,然后给变成这么一个呃屏幕空间好吧,然后这里还是一样,咱们不管z啊,z方向,咱们咱们就不动它。
大家也可以看到这里确实z方向这里写的是一,所以说确实z方向没有病,没有经过任何的改变好,那么呃这就是我们要做的最后一个变换了,那做完这个变换之后,大家就可以看到好。
那我定义的之前不管是frost通过这个呃宽高比,还是说呃和呃宽高比和这个可视角度定义的frost,还是说我定义的这个正交投影的这么这么一个哎,这个就是三组这个这个对边的这个这个位置对吧。
呃不管我怎么定义,然后反正他们已经变化到-1~1的三次方了,然后现在我又把它的x y给变到了屏幕上,那也就是说现在我已经可以得到一个二维的,一个一个就相当于场景的一张虚拟的照片了对吧。
那么呃下一步是什么呢对吧,下一步自然就是我们要把这个得到的这些结果,大家别忘了,这仍然是这个这个空间中描述的一堆三角形啊,这些这些这个信息对吧,然后我们要把它变成真正的这个图。
也就是说我们要把它给打散成像素,没错吧,这个呃这里就是我们要说的这个光栅画这么一个过程了,所谓光栅话我刚才已经解释了,就是说大家可以看到这么一个这个例子哈,这个是这个少年派的奇幻漂流。
这个电影里面大家都知道这个老虎是假的,但是做的栩栩如生啊,这个就是嗯这个这个啊图形学的贡献了,大家可以看到这个老虎呢上面有这个各种各样的这个多边形对吧,这些多边形它经过变化,经过各种各样的操作之后。
它会形成在屏幕空间中的多边形,但这不够,咱们要把这个多边形进一步打碎,打成这个像素对吧,显示在这个一个个像素上,告诉我每一个像素的值都应该是什么,这一步的过程应该叫做就是我们所说的光栅化。
把这个多边形这个在屏幕空间真正的给画在屏幕上好,那这就是咱们要说的这个内容好嗯,在这个之前呢,就是说可以用这个进行这个这个绘画的这么一些机器,可不只是这个这个屏幕,这里给大家稍微介绍一下对吧。
这个大家可以看到有一些这个实际的这些呃绘制用的这些工具啊,就是真正能够在一些这个物体上面画,大家可以看到这是一类一个类似机器人的结构,然后他绑着绑上一支笔,然后这个可以根据这个编程的这个这个这个位置。
然后控制它的移动,这样的话它可以真实的在任何的地方去画画对吧,那咱们的这个在屏幕上画,是不是这么一个道理呢,对咱们之后可以再继续看,然后呢同样道理在一些这个制造过程中。
比如说像这个比如用激光去这个切割一些这个金属,然后这些当然也都是控制好的,相当于是在金属上面这个进行一些这个绘制,那么同样道理咱们在这个屏幕上也是一样的对吧,那咱们这个介绍在屏幕上绘制之前。
咱们先给大家介绍各种各样不同的这个呃光栅,光栅的这个显示设备对吧,那么呃这个分别都是什么呢。
大家可以看到这个嗯最简单的,或者说一个非常常见的一个一个这个光栅的显示设备,这个早期啊其实这个嗯很多电脑显示器也都是这样,咱们这个之后会的给大家介绍这个呢是示波器啊。
然后如果大家做过这个什么物理实验或者什么这个应该都这个嗯,见过这个没问题吧对吧,然后这上面它可以形成各种各样不同的曲线,正常情况都是绿的对吧,然后是是这么一个设备,然后呢这个呃这个设备很神奇的。
然后呃给大家放一段这个视频,welcome这个internet,然后这个大家听到这个噪音是真的,这个视频里面有噪音,然后这个视频是在干什么呢,这个视频是在试图用示波器去画一个这个蘑菇啊。
大家刚才应该已经看到了对吧,now first we need a sign wave on our horizontal deflection channel。
and a cosine wave on our vertical deflection channel together,they add up to a beautiful circle,哈可以啊。
所以说呢这个示波器其实是很神奇的东西,他这里说的不知道大家听明白没有啊,他他这个为了画一个蘑菇,然后他用到各种各样的正弦和余弦的波,并且还使用了声音作为这个一种这个噪声的输入,是这么一个意思。
然后自然它还有后续啊,这个后面就不再给大家看了,然后呢咱们直接进入到这下面一页好吧,然后就是说这个示波器本身当然是一个成像设备。
然后它的成像原理是什么呢,它和这个和我们早期的这个这个显示器的成像原理一模一样,什么呢,这个大家可,以看到叫做阴极射线管,然后应激射线管是什么意思,大家可以看到就是比如说有一些这个这个电子啊。
就是在这个左边这幅这个electron immeter这里画的这个事情,它会产生很多的电子,然后这个呃这个会穿过这么一个这个这个显示设备,然后它会发生这个偏转,偏在不同的位置上。
然后会打在这个屏幕上的某一个位置,然后如果这个过程进行了足够快,那就是你不会看到说这个一个一个的这个电子打在这个屏幕上,然后它会变成一个什么样的一个一个形状,对,吧,如果足够快。
那自然每一个点都可以这么操作,那自然而然你从右边向左边看过去,就可以看到一个这个屏幕对吧,这就是非常非常早期的这个屏幕,也叫做c r t屏幕,自然就是这个缩写应急射线管的缩写。
然后这个屏幕这个非常伤眼睛啊,这个跟这这个示波器基本一个原理,很多电子打过来对吧,大概大概是这么一个道理,然后当然这个这个呃后面然后这个得到了一个呃非常不错的提高,然后我们之后再给大家说。
就是说关于这么一个这个crt显示器,它还有一个这个很有意思,的东西,这里给大家补充一下好吧,就是早期的电视也好,或者是早期的电脑显示器也好,嗯他们是如何这个把这么一个一个的点打在这个屏幕上。
从而形成一一整个完整的画的,然后其实很简单,他们是通过一种所谓扫描的方式,怎么说呢,就是说我可以认为它这个我可以控制它,这个电子要打在哪一个位置对吧,那我可以从这屏幕左上角开始,我先画一道线对吧。
然后我在这个换一行,我再画一道线,然后这个都是水平的这样的线对,然后当我画的这些线足够密集的时候,那基本上它,就可以覆盖整个屏幕了对吧,那当然它有一个先后顺序。
然后这个大家可以看到在这个右边的这个示意图上啊,他从从上从上往下一直这么画过来,然后这些线画的足够密集的话,你就可以看到整张图,然后还有一个有意思的现象呢,就是说它这个通过划线这么这么这么些方式啊。
然后成像他其实这个人们是很聪明的,当然很懒的对吧,我们之前提过这么一个事情,这是懒惰是进步之源,然后人们这个发现啊,这个呃我为了让他画得快点儿,然后我其实对于这个这个每一张图像来说,我其实就可以画一半。
什么叫画一半呢,就是我隔一行画一条线对吧,我隔一行画一条线,比如说我在在当前这幅图或者当前这个时间我就画这个第一行,第三行,第五行,第七行,这些基础好,然后呢,那我到了下一个时刻对刀。
或者在下一张图的时候,然后我在画这个偶数行,这个叫246 80,这这么几行,那么这个呃这个技术就被称作这个隔行扫描这么一个技术,这个有什么好处呢,很简单,那你画每一张图的时候。
你的工作量都减少了一半嘛对吧,然后那这个放在一块儿,人眼本身这个,本身能够感知动画是因为人眼有一定的视觉暂留的效应,然后就是说我的这个呃这个每两张画相当于可以呈现,呈现出一个完整的画面。
然后我也不会发现说这个中间其实缺了也行,因为这每两幅画之间相隔的时间非常短对吧,我短暂的这个这个视角会停留在这个呃这个呃呃呃,就是以前画了的这个这个东西上。
所以你每一次看到的其实都是这个这个呃相当于一幅完整的画面,而这是一个聪明的做法对吧,然后这个隔行扫描呢直到现在还在一些视频压缩里面,这个起到一些,作用就是相当于是呃我仍然沿用这么一种思想。
虽然来说我的成像不再是这么成像,而是说我这个呃如何去压缩我的视频呢,那我相隔的两帧之间,哎我这一帧我只记录它的基础行,我下一帧只记录他的偶数行,然后这个我到时候放的时候,反正大家看不到对当然了。
这里还是有一个问题,就是说嗯这个隔行扫描会造成这个严重的这种画面撕裂,特别是对于这个嗯这高速运动的这些画面,就比如说像涉及到一些体育比赛啊,或者什么,如果大家看到有一些这个隔行扫描的这个这个。
视频的输入,大家会看到这个人物在移动的时候,会发生这么一种这样的这种交叉的这样一种这个这个鬼影的现象对吧,这就是这个呃这个隔行扫描的问题了,这当然了,给大家这个随随便说一下。
就是说这是早期的一种显示设备,叫c r t好吧,那咱们可以继续。
那现在的一些显示设备,其实来说这个这个我们就只需要知道它们的原理就可以了,什么呢,就是说呃给我一个显示器,我怎么知道它要显示什么呢对吧,然后呢这个很简单,就是说我的显示器呃,我自然是这个啊,通过这个这。
个这个呃显卡或者说这个嗯通用来说,就是说呃这个内存里面的一块区域,然后显卡里的内存我们管它叫显存啊,所谓这个memory,然后呢就是说内存中间的一块区域,我们把这块区域给映射到这个屏幕上。
这里就是我们认为现在这个屏幕的显示方式嗯,这个之后呢咱们还会给大家讲,就是说我们可以生成这个不同的这个呃,这个图像存在这个显存中的不同区域,然后我们可以告诉显示器,我们让了让它显示呃这个到底是哪一幅图。
然后这里这个之后会这个这个多说一些,总之呢这里,这个大家明白这个显示的图像其实就是内存中的一块区域就好了,那么这里再给大家多补充一下大家这个左边这块,如果大家这个小时候。
这个这个这个这个打过这个这个这个所谓的红白机哈,然后他应该接触过这个游戏,然后国内俗称叫小蜜蜂,但其实它有一个这个这个这个真名的,他叫space invaders,叫太空侵略者啊。
这里给大家这个简单给大家这个这个补充一下这块知识。
ok然后呢呃那咱们刚才既然提到说这通用的显示设备,那现在大家都在什么样的一个设备上显示呢,那现在的,主要显示设备就被称作平板显示设备啊,在这里主要是lcd lcd是什么,马上就给大家说。
然后大家可以看到有两个这个呃两个这个不同的例子哈,一个是计算器对吧,大家可以看到计算器是一个超级低分辨率的这个这个lcd的显示器,然后大家可以看到一个一个的格子。
然后呢手机大家可以看到底下这是一个非常高分辨率的显示器,以及呢到了现在的这个发展,然后呃人们发发明了一些这个这个非常非常高分辨率的显示设备,高到什么地步呢,高到这个屏幕。
的分辨率已经超出了人的视网膜的分辨率,这种屏幕我们就管它叫做视网膜屏幕对吧,然后就是这么一个情况,然后呢大家可以看到不只是这个lcd,更进一步的什么l o l e d啊,各种各样不同的这些显示设备。
那咱们就不再多说,给大家着重说一下这个l c d所谓lcd是什么呢,就是我们管它叫液晶显示器对吧,液晶显示器是什么意思,顾名思义,它就是利用液晶的原理,然后来控制一个像素,它到底显示什么。
然后大家可以从右边的示意图可以看到这个液晶,它,会通过自己的不同排布影响光的极化,也就是说光的偏振方向大家可以看到,其实这个这个呃这个液晶显示器的结构啊,一个像素它这个有两个不同的光栅。
大家可以看到左边和右边呃,这个相当于有两个光栅以不同的方向进行排布,这个我相信大家在物理上都学过对吧,就相当于这个光它其实是有波动性的,然后这个光经过一个光栅,也就是说只会留下这个光在这一个方向。
在光栅所规定的方向上,这个震动的这么一这么一些能量好吧,也就是说通过了光栅之后,光的振动方向,就和这个光栅的振动方向一致,那么大家想象一下,比如说先看右下方这幅图,这个光先通过了这个呃,右边这个光栅。
这个它自然是这个竖直分布的,所以这个光只能变成竖直的震动,然后光又想试图通过左边这一面,它是这个水平震动,那通过完了之后就没了对吧,就是这个就是说你只有竖直的光通过这个水平方向。
那可不是变得什么也没有了吗,那么液晶显示的原理就是相当于通过液晶的这个扭曲,然后把这个光的这个这个这个振动方向渐渐的给调过来,大家可以看到右上方,就是说这个液晶显示这个这个光原本是竖直的。
然后通过这个光栅之后,它被扭成这个呃,不不是通过这个光栅,他通过这这个右边这个光栅之后仍然是竖直的,然后呢经过这个液晶的扭曲之后,把它给扭成了这个水平的,然后它就可以从水平的光栅出去了。
这就是为什么你可以看到这么一个像素啊,它就是这么一个原理啊,然后这个当然得到一个非常这个呃广泛的应用,然后这块呢当然要想理解的话,得需要这个呃呃这个大学物理是稍微知道一些这个光学方面的知识,当然不难。
啊就是说得需要知道一些这个光的波动性,那么呃这里大概就说到这里好吗,这是着重给大家介绍一下这么不同的种类。
那么我们刚才提到这个呃lcd对吧,液晶显示,那还有一种我们广泛使用的东西,这个显示设备叫l e d l e d呢,其实它这个缩写这个就完全不一样了,叫什么呢。
叫light in meeting dialed,然后这意思就是发光二极管的意思,然后这个发光二极管很好理解,要么发光,要么不发光,大家可以看到这这个这个图啊,这个图上面这个是一块板。
然后这个板呢是有各种各样不同的,这个呃,一个阵列的这么一个发光二极管构成,然后有一些可以发出这个呃,这个蓝色有些可以发出红色不同的颜色,这个当然是之前预定预定义好的好吧。
这就是这个l e d这个显示器呃,或者显示设备啊,这些呃简单跟大家说一下好。
然后还有一种这个显示设备,然后如果大家这个买过一些什么电子墨水瓶对吧,如果买过亚马逊的kindle,那家就会知道啊,有一种显示设备是这么一个原理,就是相当于它有这个这个这个黑的有白的啊。
这个不同这个这个这个墨水,然后呢经过这个给不同的这,个这个通电的这个电压啊,或者是模式啊,不同的情况它可以发生翻转,就是这个黑的在上面还是白的在上面哎,这样的话你就可以通过控制这些不同的像素。
它到底黑的还是白的在上面,然后控制它这个到底你看得见看不见字,这就是这个这个电子墨水屏的原理对吧,然后当然它有一个严重的问题,这个问题是什么呢,就是说这个这个um叫什么呢,就是说呃它的刷新率很低。
也就是说你要想改变一次,他这个嗯就是每一个像素它的黑色和白色的朝向,他要花一定的时间,而且是一个,肉眼可见的时间,这就是为什么大家要是有kindle的话,就是说大家会发现翻页非常的慢对吧。
他得这个刷新一遍,然后呢用它看动画更是不可能,就是因为他有这么一个问题,当然它的好处就是看起来非常自然对吧好,那这个呃这就是一些简单的这个成像设备,那咱们现在回到这个呃这个课题上来对吧。
怎么样在这些成像设备上面画东西,然后另外大家还记得咱们咱们这个还是假设这个屏幕上呃,是由各种各样不同的像素构成的,每一个像素是一个这个呃内部颜色不会发生变化的,小方块儿好,那么从这里开始嗯。
我们已经提到说,怎么把把这个一系列的这个三维空间中的这个呃多边形也好,或者多边形的顶点也好,然后我们把它给这个变换到屏幕空间上面去,下面一步就是把多边形实际上拆成不同的像素对吧,光栅化的过程。
那么我们既然提到多边形,刚才大家看到这个老虎啊是一个就靠这个不同的四边形组成的,那么咱们现在看到的这么一个例子是靠这个三角形组成的,然后嗯这里呃就是说呃三角形刚才可以用来表示这个这个三维空间中。
这样一个,一个这个不同的呃不同的命令对吧,然后这个三角形同样也可以表示在二维空间中不同的图形,比如说像这里大家可以看到呃这么一个复杂的图形,它其实也是有很多的不同的三角形构成的对吧。
也就是说三角形啊它表示能力其实很强的,这也就是说我们为什么认为三角形,它这个这个呃会在这个图形学中得到广泛应用,因为它有很多不错的性质,比如说呢这个三角形是最最基础的多边形,很简单。
这个这个没有比这个三角形更这个边更少的多边形了,否则就退化成线段了,对,不对,然后呢任何其他不同的多边形我都可以把它拆成这个三角形,没问题,那也就是说呃这个这是一个不错的性质,就是相当于三角形。
算是所有多边形中的基础对吧,然后呢三角形还有很多这个独特的一些性质,就是说嗯三角形内部只要我们给定个三角形三个点,那我们连成一个三角形,它一定得是平面的,所以说如果大家想象一个四边形,一个四边形。
如果我沿着它的某一个对角线,我这么一折好了,那这个四边形就不再是平面的,但三角形不可能,除非你把它折成两个三角形对,吧然后就是说呃三角形内部一定是平面的,然后呢这个三角形的内外这个定义是非常清晰的。
就是说如果涉及到多边形,多边形里面有洞怎么办,比如说像这个多边形,如果它不是凸多边形怎么办,就会有各种各样神奇的问题,但三角形不存在,三角形的内部外部定义的非常清楚。
并且咱们可以通过这个这个三角形的啊不向量的叉积来定义一个点,是不是这个呃是不是在三角形内对吧,做这样的判断,然后咱们这节课很快还需要用到这个知识,然后呢这个三角形还有一些好的性质。
比如说我只要定义三角形三个顶点,它们不同的属性,那么在这个形成的三角形内,我是可以做一个渐变的,这个就是把三角形内任何一个点的这个属性都给猜出来,就根据它这个三角形上和里面任何一个点。
和这个三角形三个顶点的位置关系,我可以得到一个逐渐的变化,从从这个呃三角形的一个顶点变成另外这个不同的顶点,这就是说它们之间的属性在三角形内部如何差值。
这就是我们之后要提到的这个嗯呃这个这个重心坐标的差值方法好吧,这个之后会说就是三角形是,有很大的优势的,那么咱们现在就盯着三角形来看,那么我们既然知道空间中不管什么三角形啊,xyz什么。
经过一系列变换之后对吧,现在在屏幕坐标我只看它的x和y,那么呃我就会找到哦,这三角形和三个顶点在屏幕上都是什么位置,比如说像现在看大家看到了左边这幅图,然后是个三角形,三个顶点我都可以把它写出来。
然后这个这个当然这是随意的,这个写一写这个坐标,这里认为大家可以看到,其实这里的这个坐标起点在左上角,所以这并不是我们定义的屏幕空间啊,但是没,有关系就是说我们不管怎么样,我们经过了这个mvp变换之后。
再经过视口变换,我们就可以拿到每一个顶点在这个屏幕空间下的坐标,那么我们现在就是要把这个三角形给变成这个真正的这个,这个像素对吧,大家知道这个一个像素了,它是这个呃内部它是不可能有颜色变化的。
那也就是说如果大家看这个像素对吧,这个像素现在正好被三角形盖住了大概一半的位置,那那到底咱们这个应该怎么算对吧,就是说它到底是亮还是不亮呢,然后三角形内部呢这些点这些像素自然应该。
是比如说这个像素应该是全红的对吧,那像这些判断我们应当如何去判断,那这就是我们要下一步要做的事情,也就是光栅化中最重要的一个概念,也就是判断一个像素和三角形的位置关系呃。
更确切来说我们考虑这个像素的中心点与这个三角形的位置关系好,那么这里呢给大家介绍这个一个最简单的做法来做这个光栅化,怎么做呢,就是说我们这个呃通过采样的方法,那采样式是什么什么概念对吧。
所谓采样呢就是说给你一个函数,它是连续的,然后我在不同的地方我去问啊,这个函数的值是多少啊,这个就是采样很简单嘛对吧,然后比如说我们说呃有一个函数fx等于sin x,然后我给他这个x等于一,x等于二。
x等于三,一直等于x等于100啊,这些对应的fx都是多少,或者sin x都是多少对吧,很简单的这个理解,也就是说采样其实就是把一个这个函数给离散化的过程,没问题。
这就是它相当于是一个呃稍微正规一点的定义,那么我们可以看这么一个这个这个代码,这正是我刚才说的对吧,给你个函数f x,你给它不同的x求出不同的这个这个函数值fx这,就是采样。
然后呢采样是一个非常非常重要的概念,在图形学里面,这个我们会涉及到各种不同的采样,咱们这里说的采样是指这个利用这个呃像素的中心,对屏幕空间进行一个采样,然后嗯大家可以想象。
比如说屏幕空间咱们定义是零到with乘以零到height对吧,这么一整个区域,那么我们用像素中心进行进行采样,也就相当于是我们要算出这个呃这个我们需要的某一个函数,定义在屏幕空间上的某某某一个函数。
在不同的像素中心它的值是多少对吧,然后呢我们之后还会提到说我们,还会采样,比如时间,然后位置,然后函数的这个这个这个这个呃怎么说呢,就是物体的这个表面的反射的这个性质,各种各样的东西都可以采样。
三维空间也是,比如说大家可以看到医学中涉及到什么c啊,或者说这个什么呃这个呃核磁共振成像啊,各种各样得出来的这些这些成像的结果,其实成像出来的结果是三维的。
然后就是说我们知道你这个这个病人的体内任何一个位置,然后它的这个比如说这个组织的密度是多少,对可以得到这些信息,那这个我们要把它显示出来,同样涉,及到采样,所以这是采样的重要性好吧。
然后呢那我们这里回到我们要做的这个工作上来看,那我们要采用什么呢,我们要采样的就是说呃给你一个三角形,然后我要在这个像素的中心,然后来判断是否这个嗯这个像素的中心在三角形内啊,这是也是一个函数对吧。
如果我们可以定义一个函数,这个函数什么呢,我们把这个函数定义成这个inside的这么一个函数,这个函数什么意思啊,也就是说给你一个三角形,给你屏幕空间中的任何一个点的坐标x和y。
然后我就要知道说这个点是不,是在三角形内,它当然是一个函数,没问题,大家可以看到对吧,给定任何一个三角形try或者是t啊,没关系,然后给你任何一个坐标,这个坐标不一定是整数,这个坐标可以是任何一个实数。
那给你任何一个xy,你你肯定可以得到诶,这个这个点要么在三角形里,要么不在那,根据它在三角形里,或者是不在,我们定义这个函数是一或者零,那咱们回到刚才的采样,这个我们这里在采样什么呢。
我们就是在采样在屏幕空间中定义的这么一个inside的这么一个函数,就是在这个不同的这个像素的中,心我们要确定这个函数的值到底是一还是零,简单吧,就是说我们要做这么一个事情,然后。
然后呢就是说我们如何去进行这么一个采样对吧,很简单,这个还是还是沿用之前我们的这么一个采样的这么一个呃,这个代码上面的一个定义对吧,那只不过这里我们把它给变成这个二维的形式,什么意思呢。
大家可以看到两个for循环做了什么事情呢,就是相当于是我把整个屏幕上所有的像素都考虑一遍对吧,所有的像素x y,那么这就回到我们一开始的这个定义上来了,那每一个像素它的坐标是整形的x和y。
那么它实际上它的中心在哪呢,它的中心在x加0。5和y加0。5上对吧,然后我们就要判断这个x加0。5和y加0。5是不是在三角形里,所以这个判断我们就通过这么一个函数来表示inside这个triangle。
然后这个他们对应的这个实际上它的这个像素对应的中心对吧,如果他在那得到的结果是一,如果不在得到结果是零,就相当于让这个像素xy它的值要么等于零,要么等于一啊,当然之后我们可以给它不同的颜色。
那在这里就是一个最最最最简单的通过采样的方法来进行,这个光栅化的过程对吧,那么嗯这里就是这个这个呃采样的这么一个呃,在这里光栅栅化的过程中一个最重要的应用好吧,然后呢那这里就是一个嗯怎么说呢。
就是说呃一个简单的回顾吧,就相当于是我们之前定义这个像素,它原本是这个呃index整整形的这个index,然后它其实它的中心是在x加0。5和y加0。5上的对吧,然后嗯现在在这个做工商化这个过程中。
咱们这个已经提到说我们可以定义一个函数,这个函数表示了说这个x和y这个点是不是在三角形内,那么当然重中之重就是说我们如何判断这个点是否在三角形内对吧,那刚才这个呃采样的过程有了。
那么现在我们考虑到这么一个这个细节的这么一个一个函数里面,这个函数具体在咱们的图形学中应该怎么样去实现,那其实这个问题咱们之前在这个呃前面提到这个向量的这个呃,差机这块我们已经提到了对吧。
然后如果大家还有这个概念的话,大家可以看这个三角形啊,这里啊我们有一个三角形p0 p1 p2 ,然后这是三个顶点,然后我们要判断这个点q是不是在三角形内,那怎么办呢,我们做叉积。
比如说现在大家可以看这条这个这个边p1 p2 ,如果说我们可以建立一个向量,从p一到p2 对吧,然后我们去插成这个向量,p1 q也就是相当于是我们这个这个嗯p1 p2 插成p1 q。
可以告诉我们这个q点在p1 p2 的左侧还是右侧嗯,比如说像这里,咱们这个这个插值应用一下又有什么病则对吧,我们可以得到p一差成p2 呃,错p1 p2 插成p1 q得到了这个向量是朝外的。
朝屏幕外面的对吧,然后也就是说会得到一个z的值是正的这么一个结果,也就是告诉我们q在p1 p2 的左侧,然后那同样的道理我们可以判断呃在p0 p一对吧,这个这个q点在p0 p一的哪里呢,在这里看啊。
应该用p0 p一差成p0 q,那么得到的结果仍然是这个呃q点在这个p0 p一的左侧,只不过呢如果我们判断这个呃这个q点在p2 p0 的哪个方向诶,咱们就会发现不对,那这个p2 p0 差成p2 q。
我们得到的结果是这个这个向里的一个向量对吧,然后这就说明秀点在p2 p0 的这个右侧,然后这就说明这个q点不在三角形内,否则的话这个这个q。一定是在p0 p1 p1 p2 p2 p0 。
它的这个呃在这个三三个不同的这个这个这个向量呃,这个的左侧对吧,然后同样道理,如果你这个这个三角形呢是这个顺时针安排的这个嗯,这个顶点的顺序就是说大家比如说把p0 ,把p一和p2 互换一下位置。
那这样的话你就会发现你的这个三个这个在左还是在右的测试,如果它都是说明这个q点在三条这个呃向量的右侧,然后我们才能说明这个q点在三角形内对吧,然后就是说嗯。
这这就是我们之前这个这个说的这个向量叉积的这么一个定义,也就是说我们总结一下啊,考虑一个三角形,把它安排成某种顺序,比如a b c或者p0 p1 p2 ,然后咱们不断地重复它。
就是a b c a b c a b c,这样这样顺序就不会错,我们就会找到ab b c,然后c a而不是ac对吧,按照这么一个循环的这么一个顺序去对这个判断,这个差乘得到的结果要么全是这个z是正的。
要么全是z是负的,只有在这两种情况下才会判定q在三角形呃,这个这个呃p0 p1 p2 里面对吧,所以说啊那行,那咱们现在就可以知道这个函数应该怎么样写出来了对吧,插件的这个这个呃公式我们也知道。
然后现在咱们这个就已经可以判断任何一个点呃,它的这个给定一个坐标x和y我们都知道是否在三角形内,那么在结合咱们之前所说的这这么一个采样这么一个方法。
我们就可以知道这个呃这个每一个像素是否应该被填上一个数字了,那么这里有同学会问这么一个问题啊,就是说呃这个如果有一点,但是正好碰巧他在三角形的边界上,这可怎么办对吧,然后像同行学里面啊。
我们这个这个经常会遇到这样的问题,但通常对于这样的问题,我们要么不做处理,要么特殊处理,那么在这里简单跟大家说一下,比如说在在咱们这门课上,咱们不做处理,也就是说这个点到底算是在这个。
比如说大家现在看到这幅图啊,这个点到底在三角形一还是三角形二上,呃,这个这个这个这个或者说两者都在对吧,然后这个只要自己定义一个标准,自己把这个这个说通就可以了,就是说如果我认为这个点只要在某一条边上。
然后他就就在三角形内,那么得到的结果就是记在一又在二上好吧,然后如果你认为在边界上不算,那也没有关系啊,然后就是说呃这是自己定义的,当然在一些这个图形学的这个api上。
比如说像open gl和这个direct x,他们有着一个非常非常严格的规定,比如说他们认为上边和左边,这一定是这个呃,如果有点落在这个三角形上边和左边的话,然后这呃这两个点这个点都认为在三角形内。
然后如果落在右边和下边的话都不算,那当然这个规矩相对复杂一些,但是也没有必要这个这个特别去掌握它,大家只要知道这是一个大家这个这个要么自己规定,要么不严格的处理的事情好吧,然后这是这个事情。
那么我们刚才提到这么一个,这个通过采样来进行光栅化的这么一个一个过程,嗯那么呃大家在想啊,这个刚才我们写了一个二重的循环,x从零到最大,然后从呃y从零到最大。
也就相当于是我这个考虑一个三角形的光栅化的时候,我就要把所有的像素都给走一遍,是不是没必要对吧,这里这里就是说一个三角形,它其实只能覆盖一个相对较小的区域。
比如说大家可以看到这里一个蓝色的这么一个区域对吧,那我说嗯左边至第一列啊,这么一些像素,它根本就不在这个蓝色的这个区域里,那它更不可能碰到这个三角形,所以我对于这些像素根本就不用看这个三角形。
根本不可能填充到这些像素上,没错吧,那么对于蓝色的这么一个区域,跟这个这个更那个的说嗯,就是更严格意义上来说,因为它是这个这个水平的和竖直的这么一个边把它围成的好吧,那比如说大家知道这个三角形。
咱们把它给变成这个呃,在这个屏幕左右屏幕空间的坐标下,这个p0 p1 p2 ,我们都知道它的坐标x y对吧,然后所有的x我都可以取最小,也可以取最大,然后所有的y这三个点啊,所有的y都取最小和最大。
那么自然就可以得到这么一个这个这个这个方形的这么一个区域对吧,然后呢这个区域,然后如果说我这个像素这本来就不在这个区域里面,那我自然就没有必要去做这个光栅化对吧,因为这个三角形一定不可能覆盖到它。
然后只有这个这个区域内的这些像素,我们才需要做刚才的循环,很简单,就是for x等于这个这个呃x me,然后呢让它一直循环到x max,然后y也是同样这么操作就好了。
就不用这个所有的x都要从零到with,这个整个屏幕上所有的点都这个走一遍对吧,所以说这里呢这个这个bounding box,其实它还有名字叫ais aligned bounding box。
然后我们平常会缩写成aa bb,就是这么个道理,之后还会给大家说好吧,然后就是说这个呃,比如说大家看这里,就是说我可以对这个三角形所覆盖的区域啊,我每一行都找它的对应的这个最左和最右对。
这样的话我连一个像素都不会多考虑对吧,当然这个事情说是容易,但做起来其实不太容易的,而且是这样啊,那这么一个三角形呃,或者说这么一个方法吧,这么一个方法适用于光栅化什么样的三角形呢。
呃那那这个我我猜大家可以这个这个想不出来对吧,什么时候一个三角形其实没覆盖多少像素,它覆盖了不少像素呢,那自然是这个三角形挺窄长的,然后又是旋转过来,就是旋转45度,这样这样正好倒霉。
那就是说对于这种情况来说,挺适合用咱们现在画的这么一种方法,所以说呢呃这个就是说针对不同的情况,那自然有不同的处理方法好吧,然后呢啊所以说这个呃这就是我们提到的这么一个这个光栅化的一点,点。
这个这个简单做法对吧,通过采样这个呃inside的这么一个函数,然后我们得到了光栅化呃的方法,其实说白了就是每个像素就是每个可能的像素吧,检测一下是不是在三角形内,那么这个理论是非常简单的。
那咱们现在提到提一下这个实际的这个这个屏幕的光栅化,或者说我们看一眼这个这个实际的屏幕应该是什么样的好吧,比如说这里这里拍了两个手机的屏幕,它们在显示同样的一个画面啊。
然后大家可以看到这一个是iphone,一个是三星的galaxy,然后嗯这里呢大家会发现不对,那就是这个老师讲错了对吧,一个像素它根本就不是这个这个一个这个小的一块呃,比如说左边这个iphone上面。
大家可以看到一个像素其实是由三个不同的条对吧,呃红绿蓝就是rgb 3个不同的条放在一块变成一个像素,没错,这是像素的这个这个内部的一些这个结构,然后呢大家可以看看右边更有意思了。
右边这个这个是这个红绿蓝仍然是三个颜色,然后这三个颜色它形成了某一种这个图案对吧,这种图案还可以给大家说一下,b a y e r啊,然后呢这里像素根本就不是一个方块的对吧。
你很难找一个方块把它给这个圈起来,说这就是一个像素对吧,然后呢另外还有一个特点,这里好吧,这个这个正好有时间给大家这个多说一下啊,这里大家可以其实可以看到一个一个现象,如果大家仔细注意的话。
这个呃绿色的点其实要比这个红色和蓝色的都要多,这个要怎么看呢,就是如果大家盯着这个这个某一块区域看,其实不容易看清,那我给大家提供一个方法,要这么看,比如说大家就只看红颜色的点。
大家可以大概有一个这个红颜色的点,它的这个密度是多少,我说的是这个三星galaxy啊,右边这个,然后就是说大家可以看到红颜色的点,它大概有一个什么密度,它和蓝颜色的点,它的密度基本上是一样的,对不对。
然后呢,但这个如果大家看这个绿颜色的点,就只看绿颜色的点,大家很明显会感觉到啊这些绿色的点它的密度要比红色和蓝色都要高,也就是说实际上啊这个这个嗯对于这种屏幕来说。
或者对于这个bar pattern来说,他用了更多的绿色的点,然后这是怎么回事呢,这是因为啊人眼它这个这个本质上来看,他对这个绿色这个颜色最为敏感。
所以说在绿色上多一些这个这个不同的这个这个像素是有好处的,哎啊稍等啊,就是说这个同样道理在这个相机里面,其实有很多相机也是这么设计的,就是相当于这个不同的感光元件,比如涉及到绿色的感光元件。
它们就放的多一些,就用通过这么一种这个bar pattern的形式,这这这么一种这个就就是把这些这个原件以不同的密度组织起来,这样的话在绿色上会有更多的感光元件。
也就是说可以得到这个在绿色上更好的这个还原,从而人眼看上去会更舒服,就是这么一个道理,好吧好,这是这么一个呃意思,当然在这个其他成像设备,比如说彩色打印机上大家会看到一个更复杂的这样一个一个这个图案。
大家可以看到右边这是一个左边这幅图放大了一点的结果,大家可以看到这些图案这个分布非常非常奇怪的对吧,这个斜着的这样这样一个蓝色的分布,以及说还有这样的红色的分布,然后还有黄颜色的,就是说在打印的过程中。
大家这个有时候会更多关注一些,比如说如何去最省这个这个末对吧,以及其实我们之后会在颜色这一章专门给大家说,这个是一个打印来说,这是一个检测系统,所谓检测系统就是说你往上加的能量越多,不加加的颜色越多。
他最后得到的结果越黑,然后我们平常提到的这个这个屏幕他们是一个rgb呃,这个他们正好是反过来的,就相当于是这个rgb的值越高,表示它越亮越靠近白色,对吧啊,这里这个简单说一下。
然后呢呃再回到咱们这门课上,咱们这门课仍然认为这个呃屏幕上面每一个像素,好吧,这里是没有问题的,这就是简单给大家说一下好,然后那咱们今天的课就差不多了,咱们咱们在这一课的最后看一个问题对吧,大家看到哈。
我对于屏幕中间这些不同的像素的中心点,然后我都可以判断啊,这个是否在三角形内那行,那我自然要知道好,它在三角形内,咱们就把它填成这个三角形对应的颜色,那咱们又知道像素是一个小方块。
所以如果说这个大家现在看到的这幅图是屏幕的中心点,它都点成了这个对应的,要么是红色表示三角形内,要么是这个白色表示三角形y那对应在不同的像素上是什么呢,大家其实看到的应该是这么一幅图,对不对。
所以一个三角形会会这个变成这么一幅图,唉这个大家就发现不太对对吧,那么大家想要什么呢,大家想要的是这个对吧,想要的是这个三角形,可是大家得到的是什么呢,得到的是这么一个形状,你要说它不是这三角形吧。
也不能这么说对吧,它基本上形状跟它一致嗯,但是大家很明显可以看到一个东西叫做锯齿对吧,这个锯齿就是这个相当于是光栅化图形学里面,这个一直在致力于解决的一个严重问题,好吧,这就这个锯齿的原因到底是什么。
从这个这个图大家就已经可以看出来,是因为这个像素本身它自己有一定的大小对吧,然后并且我们的采样,如果如果咱们用下节课将要讲的内容,就是说我们的采样率对于这个信号来说是不够高的。
所以产生了这么一个信号的走向问题好吧,然后这个所谓走样大家可以看到叫做ali a alien,在这个我们的光栅化图形学上就体现在锯齿上,那么咱们之后自然而然的一步工作就是要抗锯齿或者反走样。
这就是咱们图形学中的一个重大的技术,那咱们之后会在下节课里面给大家说好吧,那今天这个咱们就说到这儿,正好这个呃圆满完成,还提到了这个这个这个走样问题。
那咱们下节课会给大家说这个呃嗯关于怎么样去做反走样啊,然后这个并且会着重给大家分析一下,在这个在这个频率上如何去解释这么一个走向问题,从这个采样的方法上来看,这样的话这两节课大家对比着就会知道。
这节课为什么这么一个简单的话题,咱们一定要通过这么一个采样这么一个概念去分析它啊,把它给转化成一个理论上的问题,好吧,下节课大家就知道了啊,好那咱们今天这个嗯就说到这儿好吧,然后在这啊,我我这样吧。
我现在先来看一看大家这个今天的课上会有什么问题对吧,但是这个嗯内容相对较多,所以说我没来得及给大家回答这个事情啊,好吧嗯似乎没有什么特别困难的问题对吧,然后就是说这个ok啊,那挺好的。
那说明今天这个这个大家这个理解的都挺到位,没问题,好,ok那没问题,但是这样哈就是说呃还是一样,下节课这个预告一下,下节课绝对不容易,因为特别是对于咱们没有接触过这个信号处理的同学。
可能下节课会相对较难,但是我希望下节课咱们把这个事情给说清楚,这样的话联系到这个这节课的这个内容,大家都知道这个采样到底是一个是是怎么回事,以及怎样的基本这个这个成因以及解决办法。
好吧嗯,ok那咱们今天就到这儿,然后咱们把时间交给这个呃这个这个技术秘书同学。
然后谢谢大家好,那咱们下节课再见啊。
GAMES101-现代计算机图形学入门-闫令琪 - P6:Lecture 06 Rasterization 2 (Antialiasing and Z-Buffering) - GAMES-Webinar - BV1X7411F744
好诶可以可以,那咱们准时哎呀,这就开始了哈,行行行,没问题,那咱们现在开始播啊,好这个亲爱的同学们,大家好,这个咱们今天给大家讲咱们这门这门这个现代计算机图形学的第六讲。
然后咱们今天要把光栅画的内容基本给讲完啊,大家可以从这个标题看到,这节课咱们主要说这个反走样和这个深度缓冲,然后这么两个技术,然后这个呃主要是反走样啊,这是今天的一个呃很重要的一块内容。
然后在这个课程之前呢,就我们说几件事,一个是这个嗯作为一对一,目前为止已经有这个49份提交了,这个非常好啊,这个感谢大家支持,然后我估计这个咱们到截止日期应该这个呃有非常多的提交,然后呢我们这些作业。
然后因为是每周进行,然后每一次放出来之后,希望大家早点进行,然后这些作业呢基本上作业框架也经过了,这个这个算是两轮这个英文课的挑战啊,按说这个做作业框架啊,嗯就算是有问题,应该是不会出现特别多的问题。
应该是早点开始,不会有什么损失啊,然后这样的话这个省的之后,大家开始如果说碰到什么问题卡住了,然后这个这个就比较麻烦好吧嗯行,然后啊这是第一个啊,第二个今天啊咱们相比于上一节课给大家介绍光栅画对吧。
光栅画呃就是一个简单的这个这个在屏幕空间的采样对吧,然后相比于上节课,这节课要难得多啊,然后特别是说如果同学们之前没有学过这个信号处理好吧,或者什么信号与系统之类的这一系列的这个课程。
可能会觉得这个非常困难,但是没关系,咱们尽量把这个课给说明白好吧,呃然后如果之前啊大家没有学过信号处理啊,没有关系对吧,然后这个呃就按部就班,这个听起来应该还可以,然后这节课首先是这么一个问题,有点难。
然后这节课本身内容就比比较多,所以呃我之前想了一想,决定发挥这个网课的优势,然后我就快点说,如果中间有什么这个问题的话呢,咱们之后这个对照录像,然后可以呃可以可以可以着重看一下这个呃困难的地方好吧。
那咱们今天大概就是这个策略,然后尽量的把这个内容给完成啊,ok然后呢这个上节课啊,大家应该还记得对吧,咱们这个呃提到了一个在这个啊mvp这个变换之后呢,呃我们提到一个这个视口的变化。
也就是说最终咱们会把这个-1~1的三次方这么一个空间,给映射到这个屏幕空间上面去,我们还专门定义的屏幕对吧,然后呢上节课这个呃我们就提到说啊,当所有的三角形都已经在屏幕上的时候。
那咱们就要把东西画在屏幕上,那这个过程就叫光栅化,然后最重要的这个这个思想就是说我们要利用这个像素的中心,对这个三角形可见性这么一个函数进行采样,然后这是一个这个这个比较麻烦的解释啊。
但是这个我上节课提到说,咱们学完这节课之后,就会明白我们为什么一定要通过这种方式来理解,因为这样的方式方便我们去理解这个呃走样的,这个这个成因以及解决办法好吧,那大概就是上节课说了这么些内容。
那咱们这节课继续好,ok这节课大家这个从标题应该已经可以看到,我们这个会讲这个反走样,然后以及说涉及到这个呃遮挡与这个可见性的问题,然后分别我们用什么样的办法去解释,然后关于反走样。
咱们首先要给大家说一说关于这个采样的理论,这也就是说我们说为什么这节课要和这个信号处理有关系好吧,然后呢这个呃我们就说实际的这个图形学中,大家是怎么做这个呃反走样的好吧,那咱们从这个呃呃问题先开始。
那么上一节课我们提到说一个三角形,那自然是一个连续的某一种信号或者函数对吧,它定义在屏幕空间内,然后现在这个因为已经做完了各种变换了嘛对吧,然后我们可以给定任何一个点,然后可以是浮点型对吧。
任何一个点我们都可以测试这个点是否在三角形内,那对于像素来说,然后我们就用像素的中心,然后这个来检测这个三角形呃,这个这个像素的中心点是不是在三角形内对吧,然后就是像大家看到的这么些这个红点和白点。
这个红点表示三角形内,白点表示在三角形外,然后呢我们把对应的像素就给涂成这个颜色,要么是这个红的表示三角形这个覆盖了这个像素,然后呢要么是白的表示三角形没覆盖,那么上节课我们提到说,如果我们这么做的话。
会得到一个类似三角形的图案,长这样对吧,但其实呢我们希望看到的三角形应该长这样,那也就是说这个中间呢有一个很明显的差异对吧,而且我们可以看到有问题,我们可以看到很明显的锯齿这么一种效果对吧。
那事实上来说,我们不希望有这个呃锯齿怎么办呢,那也就是这节课我们要解决的这个呃,要要提出的这个这个这个解决办法叫做叫抗锯齿或者反走样,那么这里先把这个概念理清一下啊,我们现在看到的这个东西这个现象。
这是锯齿,然后锯齿的学名叫做这个走样叫ali,然后呢我们可以看到这个a d c呢,这个出现在这个这个各种不同的情况下,像这个左边这幅图,它有这个三角形的尖。
然后如果咱们放大是可以看到很明显的锯齿或者走样的现象,那咱们要做反走样,这个反走样就叫做antasy,好吧,然后嗯那我们这个从什么开始说呢,那咱们先从这个呃采样的理论开始说。
我们先分析一下到底是怎么回事,把这个锯齿的这个问题想明白对吧,那么首先我们上节课提到这么一个概念,说这个啊采样在图形学中是一个广泛存在的一个一个一个做法对吧,我们提到说这个光栅化的这个过程。
其实就是说在这个屏幕空间用一系列离散的点,也就是像素的中中心进行是否在三角形内这么一个函数的采样。
然后呢呃对于任何一个这个我们拍出来的这个照片啊来看呃,如果我们把它放大都可以看到一个格子,然后这当然也是这个这个这个我们表示这个图像的基本方法,对不对,然后一个图像本身也有分辨率。
也就是说它有多少个不同的格子,然后我们也管它叫做像素好吧,然后就是说呃呃一幅照片,那自然就是说呃,就是所有到达这个这个这个这个这个感光元件的所在的这个平面,嗯的这么一些光学的信息。
咱们通过这个把它给离散成这一系列的这个图像上的像素,这么一个过程来做的采样,对不对,所以说这个呃这个这个这个照片呢同样也,是一个采样,然后另外还有一个有意思的现象啊,采样可不止可以发生在这个不同的位置。
它也可以发生在不同的时间,比如说咱们再说这个这个呃视频对吧,什么叫视频呢,这个或者动画呢对吧,也就是说这个我们把一系列的图,然后按照一定时间我们把它给放出来对吧,然后就可以形成一个一个动画诶。
然后这个动画实际上来说就是这个在时间中进行的采样,为什么这么说呢,因为我们本质上来说,你们没有见过任何连续意义上面的这个动画,比如说咱们看这些图,如果说我们把,这个这个动画这个拆开。
我们会发现这个呃这个动画是定义在一帧一帧上,所谓一帧就是一幅图,每秒呢给给大家这个放出,比如说四呃,24帧这个这个图像,然后连在一起,大家就会觉得哦这是一个这个呃,这也是一个光滑的这个过渡过程。
让大家觉得这是一个动画对没问题,但实则是我们看到的每一幅图,每一帧其实都是在一个特定的时间点上的对吧,并不是在时间中是连续的,比如说咱们可以把每一帧都叠叠在一块,看这么一个动画。
咱们就可以看到这个网球选手这个击球,和发球的这么一个过程对吧,然后其实每一帧大家可以看到这个可以看到明显的这个离散的,这个球拍的位置以及球的位置对,那也就是说视频其实相当于是在这个图像中呃。
这个这个时间中的一个采样,所以采样呢是广泛存在的,那么同样采样所产生的问题也是广泛存在的对吧,然后这里呢给大家定义一个这个词叫做artifact,所谓artifact呢其实就是在这个图形学里面。
咱们这个这个这个呃的一个黑化吧,可以这么说,就是说这个图形学上的一个概念,这个概念就表示了这个错误或者是,这一切这个不准确,或者说我们不希望看到的结果,就是说一切我们觉得这个这个看上去不太对的东西。
我们管它叫artifacts,然后这个中文呢其实有翻译的叫做瑕疵啊,但是这个比较别扭,所以说以后碰到这个情况,我就管它叫artifacts好吧,就好像这个frost中文叫视锥,然后这还是有点别扭的对吧。
然后这个呃行,咱们回到这个话题上来,然后就是说呢这个采样会产生一系列采样的问题,那首先第一个问题咱们之前已经见到了对吧,我们一直在说的会产生锯齿,然后这个锯齿呢很像一些这个这个,楼梯的一种形状,对不对。
然后就是说这个嗯这就是采样产生的其中一种artifact,那还可能会有什么呢,大家可以看这两幅图,然后这两幅图表示的就是采样所产生的另外一个这个artifact,然后他也有名字,它叫做摩尔文。
然后这个摩尔纹是怎么产生的呢,很简单,这个假如说左边这个有一幅图,然后呢,这个假如说啊,我可以把这个左边这幅图的这个,这个这个这个基数行和基数列全都给去掉,呃,也就是说这个左边这幅图会变成一个小的图。
但是变成小的图的方式,我刚才已经说了,是把基数行和,基数列都给去掉,然后再把它重新对在一块,变成一个小的图,然后显示我还是把它显示成一样大,那我就会看到右边这张图这个效果诶,这个就很奇怪。
大家可以看到这个原本左边可以看到这个衬衫上的这个这个很明确的,这个这个纹理的这些这些方向在在这个右边完全就扭曲了,特别是大家如果看领带,可以看到领带上原本是一个个的格子,对不对。
然后现在这个变成了一个一个这个这种条,呃,这个很神奇这种现象,然后呢呃这个其实大家这个日常生日常生活中也可以看得到,比如说这个拿手机去拍一个这个呃显示器的屏幕对吧。
大家也可以看到会产生一些一系列的扭曲的,这些这些呃这些纹纹路对吧,那这些是怎么产生灯的呢,这些这个也是同样采样带来的问题,咱们之后都会继续说,好吧好,然后呢这里给大家看一个动画啊。
这里考验这个这个网络了啊,然后就是说大家可以看到这是一个纸片,纸片上画到画了一个画了各种各样不同的条纹,然后咱们把它旋转起来诶,大家可以看到这个纸片很显然它是顺时针旋转的,但是呢大家会看到这个在不同。
的这个位置上,怎么会发现这有一些条纹,显得像是在逆时针旋转对吧,在生活中大家也经常会看到这个现象,比如高速行驶的汽车,这些问题都可以通过采样来表示,然后特别就这个例子来说,是是什么采样出现的问题呢。
是我们的人眼人眼在时间中的采样,就好像和那个这个视频是一个道理啊,人也在时在时间这个这个呃上面的采样,然后它跟不上这个运动的速度,就会出现这么一种情况好吧,那然后咱们做一下,总结。
然后我们刚才提到了三种不同的采样,当然还有更多更多啊,这三个只是例子,就是说这第一种这个呃不是采样啊,这个三个artifact对吧,三个不同的瑕疵,不同的错误啊,第一种叫做锯齿,第二种叫做摩尔文。
第三种这个咱们管它叫这个车轮的这个效应对吧,然后嗯这个三三者都分别说明什么呢,前两个说的都是说我在空间中或者说在不同位置上采样会产生的问题,然后第三个说的是时间,但本质上都一样,采样带来的问题。
然后呢这个那么采样造啊,造成这么些这个这个这个呃走样,的问题呢,这个这个本质都是因为什么呢,其实这里给大家做了一个总结啊,就是相当于是信号,也就是函数啊,这个信号的变化太快了。
以至于你的采样的速度跟不上它,在这种情况下,就是说我们这个采样会产生artifact,并且这个artifact我们管它名这个命名叫做这个走样好吧,然后那这是什么意思呢,就是什么叫这个信号变化太快了。
导致这个采样的速度跟不上它变化的速度呢对吧,这里呢我们就需要这个通过这个频率这么一个呃,这个这个这个这个事情来分析它,而这个呢当然本身是完,全可以作为一门课来说的。
但是这个在这里咱们这节课就快速的给大家普及一些这个频率的分析,背后的结果好吧,主要从这个角度上来说,那咱们先看这个这个事情,就是说呢呃我们如何做反走样,我们先给大家这个一个结果。
然后咱们再分析为什么好吧,那这里大家看得清楚什么呢,在采样之前我先做一个模糊,或者说这个滤波叫filtering,好吧,哎那这个这个采样之前做的模糊是什么意思啊,这个这个操作,那大家看这个例子。
那之前说我们为什么会产生这个这个走样问题呢,我们用这,个像素的中心去采样这个三角形,然后呢这个这个这个呃我们会发现这有些点这个完全三角形内,有些点完全在三角形外对吧,所以这些点要么是红的,要么是白的。
然后我们把画出来,这就会产生走样,那么我们说之前做一遍模糊是什么意思呢,大家可以看这么一个这个这个例子,我们加了一个这个过程对吧,首先大家拿到一个三角形,先做一个模糊操作,把它变成一个模糊的三角形。
然后然后呢我再去这个用这些像素的中心点,我仍然去采样,采样的是什么,采样的是这个模糊的三,角形它该是什么颜色,就什么颜色,就比如说咱们看右边这个材料直接点。
这有些点采样到这个模糊的三角形的这个边界才变成一个粉红色对吧,离这个边界远点儿就偏白,离这个边界近点就偏红,就会出现这种情况诶,所以说呢这个呃看起来好像是可以的,对不对。
就是说我们这个这个呃对原始的这个函数或者信号做一个模糊,再去或者说滤波,然后我再去做采样,然后就可以解决这个这个这个呃这个这个锯齿这么一个问题,也就是说我们可以抗锯齿,或者说我们可以做反走样诶。
那呃嗯对就是这么一个意思,然后这里呢有一些这个这个频率的东西,这里就不给大家说了好吧,然后大家可以看看在实际中这个效果会怎么样呢,当然效果是不错的,这个呢是呃呃之前看到的这个怎样的结果。
而这里呢大家看到的是这个啊经过反走样之后的结果,也就是说我先对三角形进行模糊,然后呢我再去用像素的中心进行采样,采样出来的这个颜色该是什么颜色就什么颜色,然后大家会发现诶效果不错的,即使放大了的话。
也没有像之前锯齿这么严重,对吧,诶那是不错的,所以说也就是说这是一个解决办法,然后呢咱们从这个例子上来看也是如此,哎咱们可以看到左边这幅图很很严重的这个走向现象对吧。
然后呢我们如果说先对这个这个不同的信号做这个这个这个滤波,再去采样,然后我们可以达到右边这这么一个这个这个结果啊,然后效果还是不错的对吧,然后呢这里大家就有同学会问这么一个事情啊。
哎我们刚才提到说怎么做反怎样来着对吧,先对这个信号做模糊,然后我在这个进行采样,这么两个操作就可以完成反走样,那么有的同学会,问说我能不能反过来对吧,我先去采样,采样,完了之后不是得到一个怎样的结果吗。
哎然后我做一个模糊处理,然后或者说我做一个滤波,那这样行不行,然后答案是不行,咱们可以看到这个这个左下这个这个呃这个字啊,写的是sample than filter好吧。
然后就是说这个我先去这个采样采样出来,这个呃有这个走样的结果,然后呢我再去做这个呃滤波呃,或者说模糊操作,然后发现结果不对,这不是我想要的结果,右边才是我要的结果,对不对。
右边这个看上去比左边这个要要真实很多,那么这个到底,发生了什么,就是说到底有什么问题对吧,然后其实呢我们先做采样再做模糊,它还是有名字的,叫做blurred aliing。
大家可以看到就是说他其实还是怎样,但只不过走样了之后又被模糊了。
是这么一个意思,而跟反走样不一样好吧,那到底是为什么对吧,然后我们说这个为什么说我们采样这个呃速度跟不上信号变化的速度,就会产生走样诶,为什么说我这个呃这个这个这个呃先去做这个采样。
再去做这个呃模糊操作,然后这个达不到这个反转向的效果对吧,那咱们为了弄清楚这些事情,我们就,需要分析这个评语方面的知识了,好吧,那咱们首先我们来这个分析一下这个这个频玉是什么意思啊。
这里frequency是频率,然后frequency domain,然后中文管它叫做频率啊,好然后这个什么意思呢,首先咱们从最简单的事情开始看,这个没有什么东西会比这个这个正弦和余弦波更简单了对吧。
然后就是说这个大家可以看到上面这个函数余弦,然后下面一个函数正弦,然后呢这个大家可以看到这个唯一的区别,就是他们两个之间相对有一点不一样对吧,左右平移了一些,然后呃用这个这个正弦和余弦,有什么好处呢。
如果大家这个这个把这个呃正弦和余弦,这个就是cos x啊,就是这个x之前的这个系数考虑进去,大家会发现这个有意思的事情,为什么呢,因为这个呃通过调整这个嗯x前面的这个系数。
比如说上面一个函数是二派x cos 2派x,然后下面一个函数是cos啊,四拍x,然后他就会发现啊,这个这个通过调整它前面的这个系数,然后我会得到这个各种不同不同的这个这个余弦波。
然后呢这它们的不同在于什么呢,它们的不同在于它们的频率不同,然后这里我们定义一个这个,这个事情就是说就是呃cos比如二派前面再乘以一个k,再乘以个x,然后呃或者说二派f后面再乘以x这个f这个等于多少。
然后我们就管它叫频率是多少,比如说第一个我们就是二派x那就是f等于一,就是就是频率为一的这个这个余弦的函数,然后这个f等于二呢,就是下面这行就变成四派x,然后大家看到这个用这个频率f呢。
我就可以定义这个呃余弦波,它变化有多快对吧,这f等于二,它很显然它变化就比f等于一要快诶,那我们就可以用这个东西来定义,然后同样道理,对于一个这个函数来说,我们还可以定义它的这个这个这个周期。
比如说这里这个啊余弦余弦波,它的周期就是这个频率分之一对吧,然后就是说呃所谓周期就是说每隔多少这个函数会重复自己一次,大家可以看到上面这个例子,当然是每隔个一呃,这个呃这个函数会重复一次。
然后下面是每隔这个呃0。5它就会重复一次对吧,然后呃就是说这个周期是频率的这个导数,它们俩有这么一个关系好吧,那这里是简单的说一下,然后那我们为什么要介绍这个正弦波余弦波,而且他们。
有不同的频率呢啊那这里呃需要大家去回忆一个事情,大家都上过微积分对吧,微积分里面大家都会提这个概念,就是说这个一个函数的展开,然后函数展开呢咱们提到各种各样不同的展开是什么方法,什么泰勒展开。
要什么别的展开,但是有一个叫做复里叶级数展开,这里是要给大家说的这个这个事情,就是说再说这个富里叶变换这个概念之前,先说一下这个富里叶级数展开,什么叫复利的技术展开呢,就是说任何一个周期函数。
我都可以这个把它写成一系列正弦和余弦函数,它,们的线性组合以及一个常数项,像比如说比如说这里大家看右上方这两个图啊,然后大家可以看到呃这个嗯大家看到我们要描述的这个函数是什么呢。
是这个黑色的这个这个曲线啊,是一个跟城墙一样这种函数啊,突然一下又没了又凸出,凸出来一块又没了啊,然后咱们可以用这个呃这个呃这个是是两个函数来描述它。
一个是大家看到的这个这个左下角这个二分之a a就是它的高度啊,呃二分之a相当于把这个函数的中心往上提,把什么,函数的中心往上提呢,把一个另外一项某一个cos函数呃,大家可以看到一个cos函数。
然后它中心往上提诶,他这个基本上提完了之后就变成右上角这个这个图诶,然后我就看到,然后算是一个进四吧对吧,用一个cos函数去近似一个这样的这种这种我们管它叫这个呃,这个叫什么方式,叫box方式。
也是一个这个是一个周期性重复的box函数好吧,然后这我们当然可以用更多的象来描述它,比如说我们可以引入更多的这个这个余现象,比如说我们这里大家可以看到引入了一个绿色的这个,现象。
然后经过一系列的线性这个这个操作,比如说乘以2÷3派对吧,这些都是算出来的,没问题,然后就是说诶加上一个这个cos函数,诶,我可以用呃,右边整个一个这个这个绿色的这条线。
来近似这样一个类似城墙的这么一个函数对吧,诶我发现这个近似的就准确一些,唉然后我还可以再继续往上加入一个函数,加入一个函数,经过他们的一些线性组合,我又可以看到右边这个就是第三行呃。
第二列诶这个近似的结果就更像这个我要的原始的这个函数了,诶诶我可以再加更多,那,我加更多得到的结果就是越来越像,越来越像,那我可以加无限多项,然后他就会呃这个无限的接近这个呃这样一个周期函数。
这就说明一个问题,就是说我们用这个负离叶函数展开诶,级数展开这么一个办法,就可以把一个这个函数描述成很多不同的这个正弦余弦,像呃的和像这里这是一个特殊情况,只有余弦没有正弦,对对吧。
然后呢呃这说明一个什么事情啊,这个事情就是说呃这个呃傅里叶级数展开,它是和另外一个概念是紧密相连的,这个概念叫什么呢,叫做傅里叶变换啊,所,以这两个其实不是一回事啊,但是但是这两个概念非常相似,什么呢。
大家可以看这个给定任何一个函数,我都可以让它经过一个相当相当复杂的一个操作,变成另外一个函数,然后这个复杂的操作大家完全没必要去看它啊,大家就只需要看左边小写的f x,右边大写的一个fx,它是一个变换。
把一个函数变成了另一个怎么变,写清楚了,但不需要知道,然后呢这个我还可以把这个函数呢,这个这个变换过的函数就是这个大写f,然后这个函数给通过一个逆变换,还可以变回原来的这个,这个呃小写呃。
这个f这么一个函数诶,这个也就是说啊我可以把函数变成另外一个,并且可以把它变回来,很简单,这个操作就叫做复里叶变换和逆弗里叶变换呃,然后呢我们为什么要提到这个事情呢,那咱们回到上面一页来看。
就是说啊大家知道不同的正弦和余弦函数,我们刚才已经分析了,它有着不同的频率对吧,然后呢如果大家看这里这些不同的这个余弦函数啊,这里你会看到说在这个在这个比如欧米伽之前,他有这个呃不同的系数。
比如说t3 t5 t7 t,然后大家就可以,看到哦这些余弦函数它本身都代表着不同的频率,也就是说什么呢,通过这个护理液级数展开,我们知道啊,任何一个函数都可以分解成不同的频率啊。
也就是说这个比如说二分之a它和cos根本就没关系,然后这个这个是这个最最最最低的频率,然后呢这个稍微高一点频率是这个cos,然后也就对应这个左上角这么一个这个变化很缓慢的cos对吧。
然后呢这个我们加入了下一项cos,在加入的是这个呃频率相对高一点的这个这个呃函数,所以说这个相当于是我们可以把任何一个fx照,这么分解把它分解成频率从低到高这么一个形式。
那么这里就结合上这个复里叶变换了,所谓复理叶变换其实就是把这个函数给变成这个不同的这个频率的段,然后并且我们把这个不同的频率的段给显示出来,那是什么意思呢,那咱们先从这个例子来看好吧。
然后这个例子试图说明一个什么什么事情啊,大家可以看到首先有五个不同的函数在这里,f一到f5 对吧,从上到下,然后这五个函数,那咱们经过刚才的分析已经知道哎这五个函数有着不同的频率,频率从高到低呃,呃从。
低到高,从上到下啊,然后呢我们假设说我们用完全相同的采样的方法,就是每间隔这么一段对吧,对这些函数进行进行一次采样,然后我们会发现哦,我们可以采用第一个函数诶,这个这个这个这个采用第一个函数。
我可以采用出不同的点来,然后我们把这些点连起来,我们发现啊,基本上来说我可以大概知道这个原来的这个函数绿线啊长什么样,通过我们的这种采样方法,那第二个函数我也可以这么做诶,第三个函数我一样去材料。
然后这里到第三个函数,大家就已经发现不太对了,对吧,到第三个函数,如果说我还是这么采样,能把它给这个不同的采样点给连起来,我发现对吧,采采样完了之后,我就只知道这些采样点,如果我想恢复出这个函数来。
那我最简单的办法就是把它连起来,连起来,我发现这个恢复的不怎么样啊,这个大家特别是后面这段大家会发现这个恢复出来,这个跟之前的这个呃f3 这个绿色的函数变得越来越远,然后呢大家会发现在后面可想而知对吧。
可想而知,咱们用相同的采样的方法采样f一还行,采样f5 ,我就发现f5 这个我通过我的,采样点可以恢复出的这个函数,那这就差的不行,和这个f5 就就完完全全比不了对吧,和实际的f5 。
那也就是说这里会出现问题,那这里说明什么呢,这也就是说这个这个通过这个频率的这么一个分析啊,我们就可以体会到这么一个事情,什么呢,就是说我们对于一个这个这个函数来说,诶。
它本身应该有一定的什么样的频率对吧,然后我们采样也应该有一定的什么频率,对对于我们这个这个例子来说,我们采样的频率就是通过它的间隔,我们就可以体会得出来,如果间隔很小,就是,采样非常密。
也就是采样频率很高,那当然我们就可以用很高频率的采样点,然后恢复出很高频率的这个这个函数了对吧,那如果说函数本身频率很高,像这个f5 它变化这么快,那我们采样的频率很低,那就跟不上它的变化。
我就没有办法把这个这个原始的这个信号给恢复出来,哎道理就在这儿好吧,所以说这个采样和这个这个函数的这个这个啊频率是非常有关系的,那咱们举这个例子,就是为了说明后面的这个这个呃傅里变换到底能带给大家什么。
然后呢咱们在这个之前,我们,先说这个呃,说一个这个这个通过频率来分析这个走样到底是怎么回事对吧,我们这这样看,比如说我们可以看这么一个函数好吧,还是一个变化挺剧烈的一个函数。
然后呢假如说我们可以采样间隔什么东西,我们自己说了算啊,随便选一些,然后这是我要的采样的间隔诶,然后我会采用出这个函数的呃这一系列的点来,然后大家会发现这个采样的不太行对吧,因为我如果把它恢复出来。
这个会恢复成这么一个黑色的线对吧,这就这就有问题,然后呢这里我们可以再想另外一个问题,假如说我有两个函数,第一这个函数是这个这个蓝色的函数,第二这个函数是这个黑色的这个这个线表示的函数。
就假如说这个黑色的线不是我们恢复出来的,但是另外一个函数,那么我通过这这样一种采样方法,然后我会得到一个什么样的结果呢,得到的结果是我用同样的一个采样方法采样两种频率截然不同的信号。
但是我采样的结果确实是完全相同的对吧,大家可以看到我通过这些白色的这个空心采样点,我来采样这个蓝色的这个函数呢,我得到的也是这么些采样点,我所,以采用这个黑色的函数。
我得得到的还是这么一个这一系列采样点,而这两个函数原本来说他们两个频率差太多了,像这样一种现象,就是我们的这个正规的定义,说这个走样到底是怎么回事,也就是说同样的一个采样方法。
采用两种不同的频率的这个这个函数得出来的结果,我们无法区分它,这就叫做这个走样好吧,那然后就是说这个走样的概念,咱们现在已经在这个这个频率的分析上已经把它给定义好了。
那咱们刚才又已经定义了这个负离叶变换,那咱们现在就可以真正的分,析一些函数它到底拥有着什么样的频率好吧,然后那呃在讲这个概念的时候,咱们就和这个呃和这个这个这个一个重要的概念叫做滤波,咱们放在一块讲。
然后所谓滤波filtering啊,然后它是什么意思呢,就是从频率的角度上来说,很简单,它就是把某个特定的这个频段就是频率呃,就是就是就是说如果有一些这个在在这个频率上,是某一些特定的这些这个呃频率的话。
我们就把这些特定的频率给抹掉呃删掉,然后说这个对应的信号到底如何发生变化,是这么个意思,这就叫滤波,滤波就是,去掉一系列的频率好吧。
然后那我们刚才说这个复离叶变换可以帮助我们理解这个事情。
对吧啊,确实如此,这个傅里叶变换它可以把什么呢,它可以把一个函数从食欲变到频域,这就是这个傅里叶变换的作用,比如说咱们看这幅图,这左边这幅图,这是一个一个一个一个人,不管是什么样的这个这个图像版。
然后我们可以对它做一个傅里叶变换,然后复利叶变换会把这个这个图像从时域变到这个频率啊,虽然哈这个图像本身不代表任何时间的信息,但我们认为这个空间上这个不同,的这个位置啊,也也算是食欲。
这只是它的一个名字啊,就是说呃就是说从这个图像的空间,我们把它变化成了一个频率的空间,那么频率的空间右边这幅图咱们怎么理解呢,很简单很简单啊,这个大家可以看到这个中心我们把它定义成最低频的这个区域。
然后呢这个周围咱们把它定义成这个高频的区域,那就是从中心到这个周围,它的频率呃会越来越高越来越高,然后呢在不同频率的位置上,它到底这个这个有多少信息在这个不同的频率上,然后我们通过它的亮度来表示。
比如说,大家看这个这个图像的这个频率,大家会发现哦,这个图像啊大多数信息都是集中在低频上的,为什么呢,因为它这个主要是中间比较亮对吧,高频信息你说有没有有,当然有。
比如说这个周围大家就可以看到这些不同的这些东西对吧,这个显然不是零,然后高频的信息有,然后但是相比于低频那少的太多了,而事实上来说,对于自然的图片来说,基本都是这样的。
如果大家去真正自己去这个写一个这个傅里叶变换的这个代码,非常简单,不用自己手写,就是说有很多库直接提,供这种这个这个做法就是说呃富里叶变换一张图,大家就会发现啊,真的是这样,就是很多图片都是这样。
这个低频信息集中在中间呃,这个非常多,然后高频信息在外面非常少呃都会有这么一种性质,然后呢这里可能有同学问一个事情啊,说这为什么有水平和竖直的这个这个道对吧,水平一道竖直一道特别明显。
然后看起来和其他都不太一样,这个是怎么回事呢,简单跟大家说一句,这个原因是这个我们在分析一个信号的时候,我们会认为啊它是一个这个周期性重复的信号,那对于,不周期性重复的信号怎么办,比如说对于这张图来说。
它哪是重复的对吧,呃没重复,那我们就认为它其实是比如说他到了右边界之后,他又重复他这个左边的内容,然后继续往右,就好像说这张图在水平方向上被叠了好多个,然后竖直方向上也挨个放了好多个。
就是说它有无限多个这这种这个这样的图好吧,那么我们会发现这个正常情况下,很少有图像的右边界和左边界完全一致的,然后这个这个呃如果我把这个图从左搬到右边,那么它图像左边界跟头像的右边界,它两个要放在。
一块对吧,然后在这条边界上会发生剧烈的信号变化,也就会产生一个极其高的高频,然后像这种情况下,这就是这个这个为什么说我们做这个呃,复里叶变换会看到这么两条线啊,咱们为了分析这个图内部的事情。
咱们忽略这两条线好吧,那然后现在就是说啊,副理变化能够让我们看到这个图像在各个不同的频率长什么样,这也就是说呃更通用来说,任何信号在不同的频率都长什么样,咱们管它叫做频谱好吧,然后就是这么一个概念。
然后呢假如说咱们可以做这么一个操作,刚刚才,咱们大家已经提到了对吧,这个滤波什么叫滤波,去掉一些频率的内容,那就叫吕布,那剩下来的部分是什么,咱们再把它弄回这个原本的图就可以看到对吧。
那咱们现在看这个相比于上一幅图啊,这里发生了什么变化,大家可以看到啊,这里我在这个频率的这个这个空间啊,就是说所谓频率把这个低频的信这个信号完完全全都给抹掉了,没有了,现在大家会发现诶低频的再也没有了。
留下来的就只有一些高频的东西对吧,那我高频的东西它应该长什么样呢,大家还记得逆了也变化,咱,们把它变回去就好了,变回去一看,我发现哦这个高频的东西在图像上好像还是有意义的对吧,特别是对于这张图来说。
我看的特别明显,它其实表示的就是图像的边界,不是图像这个四四边这个边界,我说图像内容上的边界,比如说这个人的这个这个衣服,这个人衣服这个这个校考和这个背景差的就挺多的对吧。
然后就是说它会把这个边界给提取出来,然后就是说我们我们我们做了一个什么操作呢,就只做了一个说这个我们把这个低频的信号抹掉了,然后就做了这么一种滤波,而,这种滤波是有名字的,叫做这个高通滤波。
所以所谓高通滤波意思就是说我通过应用这么一种这个滤波器啊,让这个只有高拼信号可以通过,所以管它叫高通啊,所以高通滤波器就意味着说我们只剩下高频,这个并不要搞错啊。
然后呢这个高频信息剩下来的这些我们分析一下啊,为什么说这个高频信息,它就对应到图像的这些这些这些内容上的边界呢,对吧,我们想这么一个问题,那咱们回到这幅图上来看对吧,我们会发现什么叫边界。
比如说如果我要我要问你,直接直接让你自己来,回答就是说不通过任何数学,什么东西,什么叫边界呢,那咱们其实可以想得明白对吧,什么是边界,那就是说当这个图像这个边界,当某一个地方吧。
它的这个左边跟右边或者上边跟下边突然发生了一个突变对吧,差得很多诶,这个时候我就认为这里是边界,比如说咱们看这哥们衣服,然后这这个地方诶,它下面是这个这个这个衣服,它大概长这样。
然后上面是一个模糊的背景,然后也就是说在沿着这条边左右,它发生一个非常非常剧烈的变化对吧,它发生了剧烈的变化,咱们刚才说这可,不就是这个信号本身蕴含的高频的信息吗,对不对。
这样想就是说这个信号变化非常大对吧,然后那这就是高频信息,那咱们再回到这个这个例子上来,那我自然让他让,如果我让它只显示高频的这个对应的这个这个信息,那我自然就会找到这些边界的内容诶。
所以它是有道理的,那咱们可以再做另外一组实验,那这个实验我们在做什么,这个实验咱们看咱们看一下啊,右边这幅图还是右边这幅图呃,这幅图呃还是频域对吧,那和之前这个原始的图的频率,它是发生了一个什么变化大。
家可以看得很明确,就是说我只留下了这个低频的信息,我把所有的高频信息全都抹掉了,全部都抹掉了对吧,然后我只留下这个低频信息,然后我再把它给变回这幅图,我会发现什么呢,哦我会发现得到了一张相对模糊的图。
对不对,然后就是说我基本还能看清啊,这是这是人,然后说绝大部分细节所有的东西基本上比如说这个衣服上褶皱什么,我就再也看不见对吧,然后这个这个就是说嗯。
就是说我们这里就相当于是对这个信号应用应用了一个所谓,低通滤波器,什么叫低通呢,就只,让低频率通过高频率都被筛选掉了,去掉对吧,然后那高频率被去掉了,大家可以从另外一个角度上来分析。
那高频率就意味着边界,那边界被去掉,就意味着边界我再也看不着了,那从这个角度上来说,确实是这样的,边界看起来就很模糊了,就不再有这个原本的这个边界的概念了,对不对,那所以说唉这就这是有道理的。
那么有同学可能会问一个事情啊,说说老师我看到一个现象,说这边看起来像是这个水波纹的这种东西,这到底是什么东西对吧,然后然后这个东西呢这这个就稍微复,杂一点,咱们待会儿就会给大家说啊。
说到这个这个这个box filter的时候,它是一个不完美的低通滤波产生了问题,然后咱们咱们马上再说啊,那也就是说这里咱们先忽略它呃,不管怎么样,这是一个实验,那咱们还可以做另外一个实验。
这个实验就很有趣了,哎大家可以还是看右边这个这个这个图哈,右边这个是频域,那这次咱们去掉了什么,留下了什么,大家会发现我们把高频信息去掉了,我们把低频信息也给去掉了,留下一些信息算是某一段的频率。
但是这个不怎么特别高,但是也挺高的,但不是低频,那么我们就会提取到在左边啊,就会提取到一些这个不是那么明显的边界特征对吧,那那这个也是有道理的对吧,最明显的这个边界特征对应最高的频率。
咱们在外面已经去掉了,然后中间的一些这个大面积的这个这个相同的这种色块,咱们也给去掉了,因为它是低频信息,所以剩下的自然就是这么一种信息,那同样道理对吧,如果我们这个把这个圈给扩大对吧。
我们留下来的是另外外面一圈,大家会发现啊,我们留下来这个频率更高频了,所以我们现在看到了这个这个,结果哎这个更像是这个高频的这个这个呃边界对吧,所以这一切都是有道理的,这都是可以想明白的对吧。
所以说呢这个这一块儿呃,就是基本上来说是通过这个频率上面的分析对吧,咱们把这个不同的频率和这个信号的变化,咱们就建立起这么一种连起来了对吧,这块我这个是一个呃怎么说呢。
就是说图形学上正常不会特别多说这个事情如果要多学的话,需要学一门课叫数字图像处理好吧,然后就是说这个这门课正常情况下就会教大,家如何去这个这个通过这些不同的这种滤波的方法。
去这个做任何的这些这个这个图像的操作,当然这是经典的操作啊,这多说一句,然后就是说大家嗯平常就很少去做这些评语方面的这个这个操作,但是不管怎么样,咱们这个分析这是很有道理的对吧,咱们把这个弄明白就好。
那咱们现在继续进展对吧,我们已经说了这个滤波对吧。
是什么,然后就看了一下这个傅里叶变换到底能给我们带来什么,然后呢我们现在再回到这个滤波的,过程上去,那滤波我们刚才说是等于去掉一个一一个特定的这个,这个这个频率的信息对吧。
然后呢这个滤波我们可以从另外一个角度上来分析,滤波又等于平均,又等于卷积,好吧,这一下又产生各种各样不同的概念啊,就是说平均这个好理解哈,average,比如说我们这个这个怎么说呢,就是低通滤波器。
大家还记得吧,就只留下低频信号,就好像这图像被模糊了一样,而模糊就是一种这个平均操作啊,咱们马上就讲,然后卷积又是什么,就是这个convolution啊,这这是什么东西,为什么这个东西和这个这。
个这个滤波有关系,而且卷积听上去像是一个什么样的运算对吧,是的没问题,然后这个呢如果要接触信号与处理呢,接触那再常见不过了,那咱们给大家简单说一下好吧,从咱们图形学的角度上来说,有很多简化了的定义。
然后所谓卷积是什么呢,咱们可以看,比如说我们有一个信号,管它是一维的还是二维的对吧,这里我们这个一维的信号也就是一维数组,然后呢这个这个滤波器叫filter filter,这个呃就好像是一个窗口一样。
这个窗口呢可以在左右这么进行滑动好吧,然后像这里正好这个,窗口是对齐了这个信号的,左边这个窗口也可以向右移动一格,移动一格,然后这个窗口的大小呢是三个格子,这三个格子分别上面都有个数。
那这是要干什么对吧,这其实是要做一个卷积操作,所谓卷积操作很简单,就是说我在移动这个这个呃窗口的过程中啊,然后我把这个窗口,这是对应这三个数和这个窗口所覆盖的信号的三个数。
做一个点乘得出来的结果写回这个窗口的这个中心值就可以了,哎大家再回顾一下这个过程啊,这个这个滤波器和覆盖这三块呃,信号覆盖这三块哎,然后他们做点乘怎么做,点乘一一乘起来加起来对吧,哎1x1/4。
3x1/2,5x1/4加起来诶,我发现等于三,然后这结果写回这个格子,也就是说这个这是我要的结果,在这个格子上的的的值好吧,那我们我刚刚说的,就是说这个卷积操作呢是把这个这个这个滤波器。
或者说窗口一直在这个信号上面移动,那么可以向右移动一格,移动一格呢,我们发现诶这个还是这个滤波器,然后这次覆盖的这个这个内容是353哎好,然后呢这个我们把它乘起来,3x1/4,5x1/2。
3x1/4哎一平均而四好吧,a会发现啊,这其实就是一个平均嘛对吧,说白了是什么呢,就是在原始的信号,它的任何一个位置,我取它周围的这个这个呃总共这三个数,然后求一个平均,当然是加权平均。
然后呢我就任意一个数都是周围的数呃,若干数的平均,那得到的结果可不就是最后会得到a a,会得到这个写满了这么一个一个这个最后结果呃的一个新的信号对吧,也就是说这个卷积是作用在一个信号上。
然后呢我用一个这个呃某一种滤,波器对它进行卷积操作,然后并且得到一个结果啊,那就是这这样一个操作就叫做卷积操作,当然这个定义不对哈,这个是不是数学上的定义,这是我们这个图形学上简化了给大家的定义好吧。
然后我刚才说了,从这个上面大家也就可以看明白,其实就是信号在任何一个地方,在它周围的一个区域做了一个平均而已好,这就是卷积,那么卷积呢其实是有一个这个定理的,然后这个定理怎么说呢。
这个这个给大家这个简单说一下,这就给大家下一个结论吧,就因为这个东西其实是证明的,就是说呢嗯实际上如果我想对两个信号进行卷积,那么它其实对应到这个两个信号各自的这个呃频域上。
是两个信号的这个呃频频率的这个乘积,所以卷积操作啊其实和乘积这两个操作是挺接近的,说白了这是什么意思呢,对吧,咱们待会儿看一个例子就可以看明白对吧。
那么这个通过卷积定理我们就可以知道说我如何做一个卷积好吧,我可以直接拿到一幅图,然后用一个某一个卷积的这个这个呃这个滤波器,然后去做一个卷积操作,我也可以把这幅图先复了一些变换,变到频。
域上把这个卷积的这个滤波器变到频域上,把两者相乘乘完之后得到频率的结果,再把它逆附力的变换变成食欲上就没有问题了,所以这两个操作是一样的,所以大家就这个,而且呢呃怎么说呢,就是卷积定理,这只说了一半。
另外一半是如果是在这个呃,在时域上,如果是乘积,那就意味着是在频域上的卷积。
它是有这么一个对应关系的,那咱们看这么一个例子,就可以理解这个到底是想说什么哈,就是说比如说大家看诶,这是一幅图,这是一幅图呢,然后我们想应用一个平均或者是卷积,操作诶。
然后这个这个卷积操作是怎么做的呢,大家可以看到哦,它是一个3x3的一个一个窗口,什么意思呢,就是说我对于任何一个像素来说,比如说呃这个像素在这个屏屏屏幕上,呃,在这个图像上。
然后我取它周围的这个3x3的格子,也就是九个数求一下平均,然后再把它写回这个这个像素本身,诶,这样的话我得到的一个结果大家可想而知哈,任何一个像素都是它周围3x3像素的平均。
那得到的结果可不就应该是一个模糊了的,想这一个图像嘛对吧,那这个操作其实就是每,一个像素取它周围并呃3x3和这个这个呃呃滤波器,或者呃数学上我们管它叫卷卷积核,一个道理做一个这个卷积操作,然后写回去啊。
ok然后呢呃做做一个点乘操作,然后写回去,整体上这个过程叫做卷积,那么我们也可以怎么做,我们刚才说了这个卷积的这个定理对吧,卷积的定理告诉我们,我拿到一个图,我可以先把它做复联的变化。
变成食欲而变成频域上的这个这个结果,这就是大家看到的频率频率上的这幅图好,然后呢我的这个卷积核本身也可以,这个在在这个嗯频率上,写出来,也就是说把这个这个3x3的这么一个一个呃,就可以变成这幅图。
那我们刚才说了,这个时域上我做的卷积,那对应到频域上,我就要把这两个信号乘起来乘起来,其实大家发现哦这个卷积核呃应用到这个呃频率上面去啊,绝大多数地方都变成了黑的。
只有中间这块留下来的一些这个这个白的东西,当然大家会发现有一些r对吧没错,然后这个马上我们再给大家解释,但不管怎么样,绝大部分能量集中在这个地方,那如果我拿这个函数去乘。
以原来的这个呃图像对应的这个呃这个频率上的信息呢,我们得到的结果就是这个结果右边这幅结果,而右边这个结果呢我可以通过逆弗里变换变回这个原来的支付图,然后这里就会发。
大家就会发现诶这个好像这个卷积定理有道理,为什么有道理呢,是因为当我在这个频率上把这两个信号他们的这个啊频谱乘起来之后,我会发现,实际上就好像说我对这个呃左边这幅图,它的频率进行了一个低通滤波对吧。
我就只让他留下了最低频的内容,然后我们刚才分析过这个事情了,低,频内容是什么来着,如果我们把低频内容给这个逆弗里叶变换过去,就是这个图像对应的模糊的图像,哎也就是说这个是对的,没有问题。
也就是说我们通过这种方法验证了一下,这个这个这个嗯这个卷积定理是对的,没有问题,那么就是说呃重复一遍时域的卷积等于频域的乘积,当然了,这个仍然是不是多好理解的一个内容啊。
这个就是说这个本来应该是很多节课在信号处理课上说的内容,然后咱们现在就已经直接给大家下结论了,但是接受起来可能稍微慢一点,没关系啊,就是说,呃我们卷积定理有道理,并且咱们可以解释它可以好。
那么呃我们回过头来看这个卷积核,也就是说这个滤波器自己这个滤波器是什么东西啊,我们看到它是一个3x3的一个盒子对吧,然后这个3x3的盒子,然后还这个成了个1/9x1/9,是为了干什么呢。
是为了让这个呃这个经过卷积操作之后,这个图像的这个整体的颜色值跟以前不会发生变化,如果都是你比如说大家想吧这个任何一个像素取它周围的九个像素,然后呃然后分别和这个这个这个box对吧,上面的每。
一个1x1下,然后加起来,那可不就等于一个像素,等于周围的九个像素之和了嘛,那可不是图像这个这个月这个月滤波越明亮了嘛,那可不对嘛对吧,所以我们要做一个这个所谓这个归一化的操作。
把这个嗯所有的这些系数都变成1/9,这样的话这个卷积就不会引起这个呃整个图像亮度的变化,就这么个目的,那这就是一个典型的一个一个这个呃滤波器,而这个滤波器我们刚才看到了哈。
我们刚才已经分析过这个滤波器放在这个频率上,我们看到基本都是这个低频的信息,和其他的这个嗯频率的内容撑起来,就只留下了其他的这个频率内容的低频这个部分。
所以这个box filter也就是这个呃盒子形状的这个滤波器。
我们管它叫做这个低通滤波器啊,就是这么一个意思,然后呢这个呃我们可以这个再做一个简单的实验哈,这个嗯一个盒子它显然有一定的大小对吧,然后我们可以把这把它这个从左边,这这是它在时域上的一个信号对吧。
就是一个小的小的一个格子,然后咱们把它给变成这个频率上诶,变到频率上会发现哦对应是这么一个形状,那下面我有,一个问题对吧,如果这个这个盒子在食欲上它变大了,它就变大了的话。
诶在这个频率上它应该如何变化呢对吧,或者说这个这个如果这个盒子在实际上变小了,在频率上应该如何变化呢对吧,大家可以先想一想,那咱们现在进行下一页对吧,那大家会发现如果说我把这个这个盒子变大了。
变大了的话,它对应在这个频频率上反而变小了,诶这个要怎么理解呢,其实理解起来是完全正确的一个事情,比如说什么呢,咱们之前为了模糊一张图,咱们用一个3x3的一个卷积核对这个图像,进行滤波对吧。
然后我们会得到一个模糊的结果,那如果大家想象一下,如果我不用3x3的,我用一个比如21x21的对吧,我用63x63的,像这种这么大小的这些这些这个这个呃box。
然后呢我对于任何像素我都取它周围那么大一块区域,然后再平均起来,那得到的结果大家可想而知对吧,我用一个更大的这个box去这个对这个对这个呃图像做这个卷积操作,那得到结果肯定会越来越这个这个模糊没错吧。
越用越大的这个这个box它越模糊,当然也可以这么想,比如咱,们用一个超级大的box,用一个比这个比这个图像还要大的这个box,那得出来结果,那各处基本都一样。
因为因为把这个所有的这个图像上的这个像素都给加起来了,或者说我们再想一个极端,如果我用一个超级小的box,如果这个这个box比一个像素还小,那不等于是这个完全没有做滤波吗,对吧,那也就意味着说。
如果用一个超级小的这个box,那么它对应的频率上面的范围就会超级大,他把所有的频率都留了下来,没错吧,那所以我用一个大的这个box,我就只能留下更低的频率,也就是说让,结果变得更模糊。
所以这是非常有道理的一个事情对吧,那通过这种分析,我们就这个呃看了一下诶,我这个不同的这个这个卷积核,它本身它这个频率应该怎么样去理解好。
那么咱们刚才已经提到说好这个滤波等于卷积,等于在这个频频率上进行这个留下一段的这个这个频率对吧,然后呢呃我们现在在定义另外一个事情,那咱们从频率的角度上来看什么是采样好吧。
然后采样这里大家已经看到结果了啊,什么是采样的,采样其实就是在重复这个频率或者说频域上的内容,诶这是,什么意思呢,咱们可以理解一下好,那咱们看这么一个例子嗯,左上角大家看到的这么一个函数。
它是一个这个这个某个连续的函数好吧,然后假设它这个反映在这个频率上,它长这样,这是他复联的变换的结果啊,长这样,然后呢,假如说我要采样这个函数,那咱们现在这个想一想啊,诶什么叫采样呢,对吧。
我我要把这些函数变成一系列离散的点对吧,我就只留下这些在某一些位置上,它的这个函数的值不就行了吗,这就好像什么呢,好像说我在这个这个函数上去乘以一个另外一个函数,大家可以看另外一个函数是什么样的。
是说只在一系列的这些这个呃固定位置上有值,而在其他地方都没有值,就或者说为零啊,结果为零,那咱们可以想象,那如果说我用这个函数呃,就是c这个函数吧,乘以a这个函数得到了什么呢。
得到的可不就是这个这个a函数上面的一些离散的点嘛对吧,然后呢这个c它其实这个一个一个箭头啊,这它是有名字的,叫做冲击函数,然后这个冲击函数的定义就是就只在这个位置上有值,然后在这个其他位置上没有值。
然后大家这么理解,应该问,题不大好吧,然后乘出来的结果就是这个e这个结果其实其实就是一系列的点啊,和之前咱们画的那些空心的白点是一回事,就留下了一堆点,那这就是采样对吧,给你一个原本的信号。
你留下它上面的若干个点,那咱们现在呃已经说明白了对吧,怎么做采样呢,给你一个原始的信号a然后呢你去乘上一个这个一系列这个冲击函数,这个叠在一块儿对吧,这个这么一个函数就可以得到采样的结果诶。
那大家可以看这是在时域上了,这个函数乘以另外一个函数得到采样的结果,那如果,在频域上大家还记得这个卷积定理吗,对吧,就是说啊食欲上的乘积对应到频域上是什么呢,是卷积,那好那我们这个原始的这个函数。
它对应的这个频率不频率呃,上面的这个频谱我知道,那采样的这些函数,这个我可以告诉大家,这个经过傅里叶变换之后,它会变成另外一系列的冲击函数,间隔不一样,但还是一堆冲击函数。
那么我们说这个呃实际上的乘积等于频域上的卷积,也就是说我要把这个两个对应的函数a和c对应的频谱,b和d在频率上把它扯,把它卷积起来对吧,那么卷,积起来的结果就是b卷积d得到的结果是f诶。
大家就会发现这有一个神奇的现象啊,这个这个大家看一下这个呃,有一个函数原本是连续的,我把它采用了之后,变成一系列离散的点,其实我在频域上做的操作是什么呢,就是把它这个原始的这个函数。
它的频谱给复制粘贴了很多,对不对,就是就是做了这么一个操作,所以咱们总结起来这个略过中间的这个采样过程,那也就是说采样是什么,采样就是在重复这个一个原始信号,它的频谱对吧好。
那这样理解的话就可以就可以想明白,说这个为什么会产生怎样现象了,好为什么会产生怎样的现象呢,是因为我们这这个这个采样啊,采样的这个这个不同的间隔会引起频谱,以不同的这个这个另外一个不同的间隔来进行移动。
那如果说我的采样,假如说啊原本的这个函数,它的这个这个或者是信号,它的频谱长这样,然后我把它复制粘贴,按照这么一个不长来复制复制粘贴啊,大家可以看到啊,好我可以看到啊,这是原本的频谱啊。
这也是原本的频谱,这左边也是原本的这个信号的频谱,没问题,那如果说我采样这个采样,率不足,或者说我采样的不够快,采用的不够快,就会造成一个问题,就是说这个原始的这个信号啊。
它的这个复制粘贴它这个呃这个中间的间隔就会非常小,ok就是说我采样的不够快,意味着我我的采样点之间的距离很大,然后对应到这个频谱的这个复制粘贴上,就是说原始的这个信号,它这个呃复制粘贴它这个频谱嗯。
他自己的频谱啊,它中间的间隔就会越小,所以大家会发现食欲跟频率有好多相反的关系啊,你采样的越越这个稀疏,然后其实对应频频谱上他这个班级这个频谱的,这个内容就班尼特别密集,然后我就会发现单一的太密集了。
就会发现一个问题,说这里原始信号的这个这个这个信号和我复制粘贴的这个信号,在这一块混在一块叠在一起了对吧,唉像这种情况下,我就说这种情况下发生了走样,所谓怎样在频率的角度上来说。
就是嗯频率的这个这个频谱在经过这个复制粘贴,或者说班尼的情况下发生了这个混合,然后这种情况或者叫混叠啊,这种情况就是这个产生走样的原因好吧,然后那我觉得说这个是有道理的,为什么呢,大家可以想象一下。
啊比如说咱们还是原原本一个三角形,咱们回到光栅画上来看诶,原始的三角形,如果说我这个下面有好多好多像素对吧,然后像素非常小非常小,然后那我这个去一个像素去采用对吧,相当于对这个同样一个信号。
我采样的密集了诶,我看到的怎样的现象就会少很多,那如果我每个像素都非常大,像素跟像素中心间隔非常大,那就相当于我用稀疏的采样,那产生的走向现象就很严重,对道理就在这没问题吧。
所以说那这就是一种对这个对这个走样现象的解释,那么咱们就可以通过这,个这个事情来分析,那什么是反走样好吧,咱怎么样,那咱们可以看看有几种不同的这个不同的做法,比如第一种其实已经跟大家说了啊。
第一种就是说我可以增加采样率,增加采样率呢是这个终极解决办法对吧,比如说我的显示器,我原本显示器是一个古老的显示器,640x480的分辨率,这个一个像素非常大,很明显可以看得出来对吧。
那然后我要去用它去这个光栅化一个三角形,那当然看起来锯齿很严重,那我如果说我用现在的这个视网膜显示器,分辨率几千乘几千对吧,那,这种情况下像素就小一些,像素小一些意味着什么。
像素跟像素之间间隔小意味着采样率频率高对吧,意味着在频频谱上,它频谱的班级它的间隔大就不容易出现这个这个频谱的婚礼,哎所以说呃这当然是一个解决办法,但是这个是嗯这个并不是这个这个呃怎么说呢。
反走样要做的事情,因为你想啊这个反走样我们是在同一块屏幕上做的事情对吧,然后我不可能说我通过开启某个反走样的选项,我可以让我分辨率增加很多对吧,受制于物理限制,那它当然就不是我要的这个反走,样对吧好吧。
然后呢这个呃另外一个做法就是说如何降低这个走样的这个问题,那我就是说我真的要做这个反走样,那么反走让大家回到刚才一开始这个课之前啊,咱们给大家定义这个这个反走样的一个操作,怎么操作来着对吧。
先做个模糊再做采样,那这个有没有道理呢,那通过我们刚才的频率分析,我们这个这前面都是铺垫啊,算是这个意思,就是说通过前面的频率分析,我们就可以知道好,我们这个先做模糊再做材料,它是有意义的。
然后对应到这个频率上来说,什么叫模糊模糊,就是说低通滤波对吧,什么叫低通滤波啊,就是说我把这个高频的信息先给拿掉对吧,这就是模糊好,那我们把它重新翻译一下,怎么做反走样,先把一个信号高频信息拿掉。
然后再采样诶,为什么这样行,那咱们可以看这么一个例子,那对于还是对于这么一个函数啊,这个函数自己它就是对应到频谱,它就是中间长这个梯形,然后呢就是说大家还记得哈,如果说我原本的这种这种稀疏的采样。
在这个地方会发生一个这个频率混叠对吧,那就那就会产产生走样,那么如果我们先对这个原始,信号进行一个模糊,也就是说我把它的高频信号砍掉,砍到哪了,砍到这个这个这个呃方块,这个虚线方块之外。
我认为是高频信号,我不要了好吧,那砍掉了之后,那剩下的信号是什么呢,剩下的信号就是这样的一个一个形状对吧,这么一个形状的一个一个信号,然后我再以这个原本的这个稀疏的这个采样率来采样它诶。
我发现在这个时候他这个这个这个信号,它它它对应的这个频谱在这个位置它就不再发生混叠了,诶是不是这么回事啊对吧,就是说这样一来哎我先去做一个模糊砍,掉高频,让这个频谱它覆盖的面小。
然后我再以这个原本的间隔去复制它,就不会发生混叠了,那这就是我们的解决方法,反走样好,那这个就就把这个我们的做法啊,这个模糊操作和这个这个评委的分析结合起来了,那咱们再回到我们的做法上面来好。
原本说我们这样采样,直接采样不出问题,那咱们现在这个先对这个信号做模糊,把这个三角形变成一个模糊的三角形,然后我再采样出来结果。
那自然得到的结果就是对的了对吧,然后呢我们实际的操作中,实际的操作中我们用什么,这,个这个这个滤波器对吧,来进行一个信号的这个这个模糊操作。
或者说这个卷积操作对吧,那这是一个问题,就是说我们回到上面来,那就是我我到底怎么才能把一个三角形变模糊对吧,这是大家要问的一个问题对吧,后面采样我知道怎么做。
那就是说现在所有问题就在于我怎么做这一步这个滤波操作,把三角形变成模糊三角形,那很简单,那我就用一个呃一定大小的这个低通滤波器,对它进行卷积就可以了对吧。
卷积也就是平均就是把一个这个三角形任何呃某一个位置的一个点,让我取周围的一块,然后把这一块的结果平均起来。
唉这就是对这个对这个三角形进行模糊操作的办法,那么是取什么样的块呢,很简单,最简单的这个这个块儿,那在这个图像上对吧,最简单的一个块大家很好理解,就是一个像素,这一个像素自己它正好是一个小方块。
然后这个小方块呢它这个就是一个box filter,咱们之前说了对吧。
它是一个低通滤波器,它起到的作用就是这个这个模糊操作,那咱们要怎么做呢,那其实就是说呃先做一个模糊操作,也就是卷积,那大家知道原本三角形它是,一个这个要么这个点在三角形里,要么三角形在三角形外对吧。
它是一个这个二值的函数,然后现在呢我们就是说我们要把这个函数做一个卷积操作,用每一个这个像素对应的这么这么一个小的box对吧,我做一个卷积操作,或者说我求个平均,然后我再把这个球的平均值的中心采样。
哎对对,其实不需要采样的,对平均值这个呃就是一个值,咱们待会儿会看的对吧,然后也就是说这里就是我们的做这个呃卷积操呃,不是不是做这个这个反怎样操作的基本方法好,我对于每一个像素我,把三角形求个平均值呃。
然后我再做采样,那么这就是我们要做的事情,大家可以看到对于任何一个像素,我都知道这个三角形可能会覆盖,比如说要么完全不覆盖它,要么覆盖完,要么是一部分覆盖对吧。
也就是说比如说我这里看到的都是不同的像素好,不同的像素,这个这个在这个像素里面,三角形覆盖了它的左上角,然后这里覆盖了它的一半,感觉他很多,然后呢我刚才说对于任何一个像素内部。
我们都对这个覆盖这个面积啊,求一个这个平均对吧,比如说像这里,比如说覆盖了咱们,说1/8啊,那它的这个值就应该是这个1/8的这个亮度,然后呃呃然后这个呃然后这里覆盖了一半,那它的值就应该是一半的亮度。
然后呃不是不是亮度啊,覆盖多少,就意味着这个就是就是就是说没覆盖的7/8啊,就是覆盖大概就是有这个87%的y85 的八是多少来着,12。5对吧,87。5对的这个这个白色,然后呢如果覆盖完了。
那自然就是全黑对吧,那也就是说在这里我把这个呃呃怎么说呢,我把这个这个像素内部它的这个这个值诶,给这个平,均起来了对吧,这就是我们所说的这个卷积操作好,那么如果我们可以这么做的话,那问题就解决了。
然后在实际中要如何操作啊,好吧,这个好像没什么办法啊,而且是这样,其实连这个第一部分都没说完的,好吧,这个感谢大家理解,那咱们刚才说到哈怎么怎么做来着对吧,把一个三角形。
然后对于对于它覆盖的每一个像素诶,我都这个这个这个求一下它覆盖面的平均对吧,或者说没覆盖面的平均,然后但这事儿说着容易做,着难啊,怎么才能这个这个这个把一个三角形在三呃。
在某一个像素里面覆盖的区域算出来,这个这个不容易对吧,这个而且说这个计算量也挺挺多的对吧,那呃怎么办呢,所以说人们研究出来的一种近似方法,所以说咱们现在把它给说清楚啊。
就是说我们现在所要给大家介绍的叫做multi simple anta类型,也就是说用更多的这个采样点来进行这个反走样,那么那么它是一个这个对反走样的近似,它并不能严格意义上解决这个开某样的问题。
那么他是怎么样工作的呢,就是这个m s a a怎么,样工作的呢,就是说对于任何一个像素里面,我原本不是这个,假如说我用这个这个一个一个一个点,这是我这个像素能裁掉的这个点对吧。
然后我认为一个像素被我划分成了好多个小的像素,这个这个这个划分成好多小的像素,就好像现在大家看到这个这个像素被划分成了这个4x46个像素,然后呢呃然后呢每一个小的像素假如说它有个中心对吧。
然后我可以这个这个嗯判断这些点是不是在这个三角形内,然后我们再把这个判断的结果平均起来,是不是就是我对这个这,个三角形对这个大的像素啊,它的覆盖区域的一个近似对吧,如果我有非常密集的点。
比如说100x100个点诶,那我就可以得到一个相对准确的近似,那如果用4x4得到的不准确,但没关系,效果还是挺好的,比如说咱们看这个,看这个结果对吧,然后呢呃这里可以看到一个一个这个这个例子。
什么例子呢,但是这个一个三角形覆盖了若干像素,每个像素挺大的,然后呢假如说我可以把一个像素内部多加一些采样点对吧,比如说我用到这个两个这个这个呃就是2x2的一个这,个这个更小的这些这些点嗯。
然后呢这些每一个点我都可以判断是否在三角形内,那咱们挨个判断,比如左上角这四个小的点诶,这都没被三角形覆盖,所以覆盖率是零,然后这个得到结果是零,然后同样道理一直可以做做下去,考虑到这个像素的时候。
咱们把它加入,这就考虑这四个点,这四点我会发现啊,刚才啊刚才会发现这四个点有一个点在外面没被覆盖,三个点被覆盖了好,那我就认为这个像素它在三角形对,如果说我要求这个三角形在这个像素内的平均的这个值。
或者说覆盖,率,那它就是75%,就是这么个意思啊,咱们可以继续进行,咱们可以看到这个这个像素呢,它我用了四个不同的点去感知是否这个像素,而是否这些点在三角形内,那我会发现有一个点被感知到。
也就是这个点会在三角形内,然后其他三个都不在,那覆盖率就是25%,然后就是说这个这个呃得到一个这个覆盖率相对较低的结果,也就是说我把这个像素的值写作这个这个像素,这个三角形在这个像素内的近似的覆盖率。
也就是25%到红色,然后就是通过这么,一种方法来做诶,所以说我们可以把这个这个呃那通过这么一种方法,然后我们可以做一个这个抗锯齿的这么一个效果对吧,然后在这里我们稍微停一下,是这么回事。
首先呢有一个有一个这个这个概念得得这个说明白,我们刚才说了啊,这个m s a a通过更多的这个这个样本,然后我们来近似的是什么,近似的是第一步就是反走样的,第一步也就是模糊这么一个过程。
然后呢模糊完了之后,就相当于是每一个像素内部,我已经知道这个三角形的覆盖率,我这个求了平均之后是什么,的,然后就会得到这么一个结果对吧,得到这么一个结果之后,算是第一步做完了,模糊操作做完了对吧。
相当于是我用一系列的这个box去模糊这个三角形,这步做完了,然后咱们再采样采样很简单,这里就变得无比简单,因为一个格子它是同一个颜色,你采样在它中间,那它就应该是这种颜色。
所以说得出来的结果就应该是这个结果,所以说在这里强调的一点是,m a n m s a a就是说它解决的是这个这个嗯,对这个信号的模糊这么一个操作,这个这个这个操作,而下一步操作的采样,这。
部分操作相当于是这个隐含在这个过程里面了,但其实如果大家认为真的下一步有一个采样没什么关系,所以也就是说msa绝对不是靠提升分辨率直接解决的这个走样问题,因为大家可以看到就是说我通过那么些采样点。
增加了这么些采样点,我只是为了近似一个合理的这个覆盖率而已,并没有真的提高这个像素呃,这么些这个比如说屏幕上的分辨率对吧,它该这么些像素还是这么些像素,所以说通过这种方法来理解才是一个这个正确的。
对这个反走样的理解没问题吧,就是说,嗯不是说通过提高了采样率而完成的,我通过那么多不同的这些点,仅仅是为了呃得到一个近似的这个三角形和覆盖而已好,那么说到这儿应该就比较明白了。
所以这个呃这个m s a a基本就是这么一个工作原理,然后咱们看这个效果自然是可以看得出来的,这是没有这个抗锯齿的,然后这是有抗锯齿的对吧,所以这个效果挺明显,然后呢呃这里masa a说到这儿。
然后咱们可以停下来做一个非常非常非常简单的思考对吧,说我这个通过msa a啊,然后呢这个这个这个这个呃可以得到,一个抗锯齿的效果,而且效果还不错,但是我们知道这个对吧,no free lunch对吧。
没有这个免费的午餐对吧,那么呃我们为了引入这个m s a a,我们为了做到抗锯齿这么一个效果,然后我们到底这个牺牲了什么东西对吧,这个事情很很显然,这个这个大家应该这个一目了然的事情。
因为我们用更多的点去测试是不是在三角形内对吧,那当然是增大了计算量,通过增大计算量,然后这个这个得到的抗锯齿的效果,而且增大了多少计算量,我其实这个可以说的明白对吧,比如说一个像素,我用这,个呃4x4。
那就是16倍的计算量,然后如果2x2,那就是四倍对吧,然后就是说我这个通过这种方法呃,来来来做这个抗锯齿,那么现在多说一句,就是说啊人们都是这个很贪婪的,对不对,人们根本不希望用那么多的这个材料。
这个这个数量去这个去呃,怎么说呢,就是说呃达到这么一点点这个效果,大家希望说这个我只需要用很少一点的这个这个采样的这些点,然后我也可以达到这个这个嗯比如说4x4这么一个一个格子,这个采样点的效果,嗯。
我假如说我只想用八个零,对吧哎然后人们就会发现这个事情是可以的,而且事实上在工业界的应用上来说,人们用的并不是一个这个像素,咱们把它规则的划分成比如说4x4个点。
取中间的一些这些这些更小的这些所谓此像素,它的中心不是这么做的,然后人们会用一些这个这个更加有效的一些图案,来分布这些不同的这些点好吧,然后把这些采样点分布在一定的这个这个图案上面。
然后有一些点还会被这个临近的不同像素所附用,所以说通过这种方法来说啊,就是说这个这个大家就会可以看到,我们刚才说m s a a专门强调说他用的这个不同的这这这么些点数,不是说增加分辨率来解决这个问题的。
那么通过这个工业界的做法,咱们可以得到另外一个体会,对确实确实是这样的,因为有一些这些采样点,它是会被各种各样不同的像素去复用,仅仅是为了通过这些点来去检测三角形的覆盖而已,所以说从这个角度上来说。
这就是为什么我们可以用一个不规则的一个呃,这个这个分布来描述这个嗯,增加了这么些采样点,所以这就是为什么比如说大家打游戏的时候,大家会,发现好,我采用启用抗锯齿,我用m s a a的方法。
然后我用这个四倍,然后我发现帧率往下掉的可没有,这个没有那么多,不会掉到原来的1/4对吧,道理就在这儿,但这个有很多的这些这个这个样本得到了复用,所以非常好,当然在这里。
这个不给大家都说这个这个具体说它到底是一个什么样的分布了好吧,然后咱们在之后的这个光线追踪这块啊,给大家稍微说一说,这个涉及到一些随机数,或者涉及到一些这个怎么样去分布这个样本。
才能达到一个最好的覆盖效果,咱们之后会,说然后另外一个事情给大家总结的事情就是什么呢,咱们这里提到了一种抗锯齿,但咱们这个课叫现代计算机图形学对吧。
这个一种这个抗体是显然无法代表说现在腾讯学的我这个发展,然后呢呃我们这里就给大家介绍两种吧,这是我个人的理解,就是说抗锯齿方案有特别特别多的抗锯齿,不同的抗锯齿的方法,我给大家提另外两种。
一种叫fx aa,一种叫ta a我认为这两个是算是这个除了msa之外最重要的两个了,而且个人意见哈,就是说而且这两种方法呃得到了工业机的广泛应。
用那所谓fx aa是一个缩写叫fast approximate,aa,就是说这个快速近似抗锯齿,他怎么做的呢,它和这个这个呃增加这个样本数就没有任何关系,它是一个图像的后期处理。
就是说我先把这个这个这个一个这个有锯齿的这个图得出来,然后我再做做一种什么样的操作,然后我把这个锯齿给弄掉对吧,是这个意思,但是大家大家还记得吧,如果我先得到一个有锯齿的图,我再去对他做这个模糊操作。
这是不对的,咱们一开始就已经说了对吧,然后大家有兴趣的同学也可以从这个频率的分析上来看,那,么咱们再回到这个fx a a上,他怎么做的呢,很简单,这个得到一幅图有锯齿,然后他把这些边界都给找到。
通过一些图像匹配的方法找到,并且把这些边边界给换成没有锯齿的边界,简单吧这么一个操作,而且非常非常快,所以说它是一个和采样无关的,它是另外一个在图像层面上做的这个抗锯齿,然后效果挺好的。
然后呢这个t a a是什么东西,ta是最近几年才刚刚兴起的一个这个抗锯齿的方法,但是非常非常简单高效,什么呢,大家从t可以看出来,这个t叫temporal,temporal的意思就是与时间,相关的。
然后意思就是说我怎么样去做抗拒什么,我去找上一帧的信息,咱们比如说这个意思啊,比如说这个我们还是用这个像素呃,内的一个点,一个点没有做m s a a来来来感知是否在三角形内。
然后假如说我们看到的不是一个运动的场景,假设说一个静止的场景,相邻两帧显示的东西一样,但相邻两帧我可以用一个像素内部不同位置上的点,来感知这个三角形呃,这是我在三角形内。
那大家会发现这个这个在时间范围内得到了这个静态的,这个场景的图啊,会各不相同,在这个边,界上有一些之后出现了边界,有的时候没出现边界,然后这个temporal aa。
他的这个思想就是说我复用上一帧的这个这个这个感知到的这个结果,然后就是说上一帧的这个每个像素的值在这周还会继续发挥作用,然后被应用进来,然后就就是说这相当于什么呢。
相当于是我把m s a a对应的这些样本给分布在了时间上,然后并且在当前这一帧来说,我没有引入任何额外的操作,所以这是一个非常这个这个这个聪明的做法,当然了,对于这个运动的物体怎么办。
这个咱们之后在这个实时光,线追踪上给大家说好吧,因为那个用的核心思想其实和这个呃temporal aa的思想一样,这里多说一句哈,对于这个工业界,它是美国的工业界来说。
这个temporal aa大家都倾向于念成temporal aa,因为temporal本身还有这个暂时性的这么一个意思,所以大家为了区分这个意思,大家把这个这个音译读了,这个读成这个temporal。
所以人家这么说,说了一个事儿啊,好然后呢这个啊这里再多说一句,就是算是今天的这个内容总结吧,就是说嗯在这个提到这么一个抗锯齿这么一个概念的时候,一定还得提另外一个和他很相。
似的一个概念叫做super resolution,其实相当于这个中文叫做超分辨率,所谓超分辨率的概念和抗锯齿就不太一样,但是本质是相似的,就是说超分辨率什么意思,比如给给大家一张图。
比如说是512x512的,我们要把它给拉搭乘1024x1024的,然后但是呢大家知道如果把一张小图给拉大,那看的全全都是锯齿对吧,然后就是说我想把这张图拉大,但我又不想让他看到这个锯齿对吧。
那其实说白了是什么呢,说白了其实就是说呃大家有一幅这个呃高分辨率的图,但是你的这个采,样的这个这个率不够,就是说你高分辨六的图是1k乘以1k的,可是你采样到的结果只有512x512的。
你想把这个高分辨率的图给恢复出来,所以可以这么理解,从这个角度上来说,那这个超分辨率这么一个过程和这个这个这个嗯怎么说呢,就是说这个这个我们的抗锯齿这么一个过程。
或者说m s a a这个抗锯齿的这个过程,这是非常相似的对吧,都是要解决这个样本不足的问题,这里就介绍一种这个做法,叫做d l s s,然后咱们把这个这,个呃这个超分辨率这个过程做出来什么意思。
就是说原本有张小图把拉大了之后,那肯定有些细节缺失缺失怎么办呀,没关系,咱们猜出来就好了对吧,猜出来怎么猜呀,什么技术适合猜呀,这个事情相信大家都比较熟悉对吧,一切涉及到猜测的这些技术。
然后我们可以给他足够的这个经验性的东西告诉他啊,出现在在任何一个局部,然后我应该如何把细节补上去,一个一,那我刚才就是说这两个事情不是一回事,但是本质相同好吧,那这个好吧,没办法。
因为这个内容相对来说难一些,然后又多一些,然后咱们就说到这儿,而且还没时间说这个怎么样去呃,考虑这个深度测试,以及这个这个这个嗯就是遮挡啊这一系列的事情,那咱们就留到下节课了来再说好吧。
那这节课到此为止,那关于抗锯齿这块,那咱们就已经完全说明白了,说的内容相对较深,然,后这节课难,然后咱们这个之后如果课后大家就愿意多花点时间,这个这个多看一下这个这个视频。
唉也欢迎大家这个呃踊跃讨论好吧,ok那咱们这个就暂时说到这好,然后之后这个嗯就交给我们的技术秘书同学。
然后这个各位同学这个赶紧去吃饭啊,实在是不好意思行。
ok那就说到这儿,咱们下节课再见啊,宝贝啊。
GAMES101-现代计算机图形学入门-闫令琪 - P7:Lecture 07 Shading 1 (Illumination, Shading and Graphics Pipeline) - GAMES-Webinar - BV1X7411F744
感谢大家一如既往的支持,那咱们今天开始讲第七课啊,第七课大家可以看到这个从这节课开始呢,咱们要开始讲着色shading啊,然后之前咱们这个光栅化这块部分就算是这个顺利结束了,但是呢有一小块知识。
关于这个深度测试这块,咱们还没说,那咱们今天这节课一开始先把它补上好吧,那咱们今天这节课要讲一些这个这个光照这个着色嗯,图形管线,然后这都是什么意思呢,咱们很快就知道,那么在这个课开始之前。
我们说几个事儿啊,第一是这个这个大家非常踊跃啊,我发现这个目前为止作业一诶已经交了300多份提交了,呃,这个这个非常夸张的,因为作业零我上次记得说是200对吧,然后所以一竟然这么多那行,那从这一点来说。
我们确实需要更多的助教,然后所以说啊那我们会从这个这个之前已经提交了申请了同学中,然后开始这个这个招募助教,然后我们看看这个嗯,这样的话到时候回答大家问题应该也方便一些好吧。
然后呢这个啊嗯作业二今天一切顺利的话,咱们就会把作业二放出来,作业二关于什么的呢,就是关于咱们这个很快待会儿要说的这个呃关于深度测试的,然后就是说呃当你有更多很多三角形叠在一块的时候,它们之间互相遮挡。
这个问题如何解决,然后然后呢这个我刚刚才在课前问大家,这个作业一,大家觉得难度如何,大家反映难度还可以啊,这这样的话呢这个作业二肯定不成问题,作业二相对简单好吧。
然后呢嗯这个我在想我们原本安排了这个着色,我们要讲两节课,然后说一说这个实时渲染的这个动态,嗯我这里发现一个问题,就是着色这块内容相对较多,可能着色自己可能就需要讲三节课。
然后这个咱们尽量这个稍微稍微说这个快一点啊,在保证这个说明白的情况下啊,说的稍微快一点,然后咱们看看这个这个要怎么安排好吧,那大概这个就是咱们现在的这个呃课前的一些这个要说的内容吧。
那咱们这个立刻进入课程内容,那么在之前的几节课里面,我们提到说这个光栅画要怎么做对吧,特别的我们提到一个事情,就是说如果你有一个三角形,我们要如何把它给画在屏幕上对吧。
我们提到了说哦屏幕它其实就是一堆像素,一堆像素就是每一个像素是一个这个这个这个小方块,并且颜色是一样的,个数是一样的,那么咱们就用像素的中心对这个三角形覆盖这么一个信号做采样。
然后我们分析了说这个这个为什么我们这么采样会产生走样问题,以及说我们如何做反走样,一个基本思想就是先做模糊,然后再做这个这个这个这个采样,这样就能解决问题。
那么我不知道有没有同学这个课后思考过这么一个问题啊,那我们说这么做是对的,可是我们没有说在这个频域分析的情况下,怎么呃,证实说我这个先采样在做模糊是错的对吧,这里给大家一个提示哈。
先采样就是把它这个信号的频谱进行翻译,然后它会有频谱的混别,然后这里采样呢相当于是在混叠了之后,然后再把这个信号给截断,那这个时候大家就会发现这个混别的信号还是混别的信号啊,这里是算是一个提示。
关于说这个为什么另外一种方法做不行,那么咱们上一次就说到这里对吧,然后到这里我们就已经可以把一个三角形给画在屏幕上了,然后这里这强调了一下一个三角形对吧,那这个大家自然会问这么一个问题。
那实际的场景有很多很多不同的这个这个三角形,组成好多这个空间的三角形,然后不同的形状,然后这个各自呢离这个这个这个相机的距离也不一样对吧,然后咱们如何把这个这些三角形这个画在屏幕上。
并且让它们的遮挡关系是对的,近处的永远要遮住远处的,那这个问题今天咱们来解答,也就是说我们要回答这个可见性或者遮挡这么一个问题,嗯然后呢我们解决方法这里也写清楚了。
我们的解决方法叫这个深度缓存或者深度缓冲啊,就是或者叫z buffering啊啊啊,或者这个英文叫做depth buffering一样,然后呢这个呃我们在这个之后就进入这个着色这个环节。
咱们提到这个嗯怎么做着色,怎么样分析光照,然后这个现代的这个硬件的图形管线,就是说现在的硬件中是如何做着色的,咱们把这个问题说清楚,那今天这个咱们尽量把这些都覆盖到好,那么咱们要说的是什么呢。
是这个嗯可见性这么一个问题对吧,那大家想这个场景中有很多不同的物体,那我要把这些物体都给放在这个屏幕上,那自然涉及到一个顺序的问题对吧,这个我要先把什么放上去,再把什么放上去,然后这样使得这个图啊。
最后我看上这张图是对的,那么这个很直观的一个想法是什么呢,那我应该把这个最圆的物体啊,先把它给画在屏幕上,然后呢我这个逐渐的把近的物体再给这个补在这个屏幕上。
让它覆盖这个以前的这个这个这个远处的物体对吧,逐渐的我这个从远到近,这样把这幅图给画出来,就可以得到准确的做法呃,这个这个准确的一个一个结果,那么这个正是这个以前啊这些画油画的这些画家。
然后他们是如何作画的,对吧,比如说这里这个大家看呃,这里呃再画一幅图,然后呢这里这个画家们先画了一个呃远处的山对吧,然后呢这个画家又在这个基础上画了一个近处的这个草地。
然后遮挡住了一部分这个远处的山对吧,然后呢在这个草地上面,画家们又在上面加了好多树,然后这些树呢又挡住了之前画的草地,当然还挡住了一部分山对吧,这样的话就等于是把这个这个过程完完整整的给做了出来对吧。
而这个算法什么算法,就是说我们有一个场景,我们先把远处的东西画好,画在屏幕上,然后远处的东西先做光栅画,然后近处再慢慢慢慢慢慢,这个这个把光栅化做完。
我们就可以得到一个处理了正确遮挡的一个一个正确结果啊,所以人们管这个算法叫做画家算法,就叫pandas algorithm啊,那么这里多说一句啊,这个画家是指油画家啊,就是先把这个远处的东西画完。
在网上画新的东西的时候,会覆盖掉以前的这些东西,而不是说比如说我要画一个素描或者是干什么,然后我再把它一点点画出来哦,这个就不不涉及顺序了,这是两个事啊,我们说的是这个会永远这个新化的东西。
会覆盖这个这个以前画的东西啊,这样的话这个画家算法这就好理解了好吧,然后呢这就是这个人们怎么去画这个这个这个呃这么一幅画,那在图形学里面是可以这么做的对吧,比如说咱们如果要画一个立方体啊,画一个立方体。
那立方体要怎么画呢,那咱们沿用这个画家算法,咱们可以先画最圆的这个这个面对吧,嗯假如说就是前后两面,然后当然后面这个面咱们先画,画完了之后,咱们再考虑画周围四个面对吧,比如说这个左面下面右面上面诶。
这四个面画完啊,然后呢咱们在画这个呃,中间那就是就是就是就是最前面这个面,最前面这个面最后画上哎,把这个之前这些都给挡上诶,然后大家会发现这挺有道理的对吧,然后这个这个得到了正确的结果,没问题。
也就是说画家算法在一定情况下是适用的,但是呢如果有同学在这里啊,稍微抬杠一下啊,这个呃有个地方没说清楚,因为我说我们把这个周围的这四个面给画好,呃,我说先画左边下边右边上面。
可是咱们如果不是这个顺序怎么办,这个我们都知道这周围的这四个面,对于我来说,我觉得他们离我是差不多远的对吧,都比这个这个最远的这个面要稍微近点,都比最近的这个面要稍微远一点。
那么这四个之间的顺序是怎么样的呢,那比如说我要是先画右边这个面,再画上面这个面,再画左边这个面的时候,大家可能就会注意到,比如说这里当然我没有画出来,就是这个鼠标,我现在题目的地方。
这里应该就会出现一道线,然后呢嗯咱们在画完下面这个面,再把前面这个面填上之后会发现不对,得到的结果就是在这个基础上,这里多了一道竖线,那也就是说我画的这个顺序啊也挺讲究的,就是说我这个是巧合。
先画左边这个面可以画对,那我要是先画右边上面在左边的下面呃,然后再画前面,这样做就不对,那也就是说我想定义这个深度啊,其实挺难的,就是相当于距离,就是离我们这个观测点的这个距离,我们管它叫深度。
这个不容易对吧,当然了,这个这个啊在一定程度上,咱们说这个画家算法其实是可以的,然后呢呃它可以比如说我在这个所有的物体,然后它的深度我把它排序,然后从远到近,然后咱们把它给画出来。
然后大家都知道哎这个排序要花多长时间呢,需要n log n的时间,如果有n个这个三角形呃,那我们花这么长时间,然后一个个把它关上画上去就可以了,但是有一个情况非常特别,大家可以看是这么一个情况呃。
这是一个什么情况呢,这个也就是我刚才提到的,说这个我们呃我们刚才说这个立方体周围四个面,这还属于简单情况,这里是一个更复杂的情况,诶这里发生了什么,大家可以看到啊,有三个三角形,这个都是空间的三角形嗯。
p q2 这么三个三三角形,而这三个三角形呢,如果我问大家这个三角形谁在前面,谁在后面呢对吧,谁离我的这个这个相机更近一些吧,谁谁覆盖谁,大家就会发现有有一个很严重的问题。
因为他们两两之间都存在一个覆盖关系对吧,这个p3 角形会覆盖q3 角形,那q3 角形覆盖r3 角形,偏偏r3 角形回来又覆盖这个p3 角形,那这个时候就形成了一个环。
也就是说他们在这个在这个深度上存在一个互相遮挡的关系,那在这种情况下,那我就没有办法定义他们之间的深度关系,那我自然也就不可能用这个画家算法,然后我提前把它给排个序呃。
然后我在这个按照一定顺序来来这个把它画出来,因为那样永远都会是错的,对吧,哎那这样的话呢这个这个嗯这就反映说呃不行,说我们这个嗯实际上的实际的做法中呢,咱们不能用这个画家算法,所以为了解决这个问题。
在图形学里面大家是怎么做的呢,大家引入了一个概念,叫做这个深度缓存或者深度缓冲or z buff,然后呢这是一个这个现在大家广泛采用的一个算法,那么这个算法是在干什么呢,那么这个算法其实也是很简单的。
这个算法呢它其实就是在说好吧,那我既然说对于这个空间中的三角形,我不好,这个排一个这个他们之间的这个相信这个这个呃远近这么一个顺序,那我对谁比较好排呢,我对每个像素来说,这个挺容易分析的对吧。
如果我每一个像素,然后我认为它会看到哦,这个三角形或者那个三角形或者另外一个三角形的某些部分,然后这个每一个像素我就可以在这个像素内永远去记录这个像素,所这个表示的这个这个几何,它的最浅的深度。
也就是离我们最近的这么一个距离,那么这是什么意思呢,这个当然我们马上就会给大家来说,那么为了完成这个深度缓存,这个通常大家都在这个图形学中的做法是这样的,就是说我们这个会渲染最后的这个成品的这个图。
也就是我要的这个这个这个结果啊,就是说我要的最后一张图像,然后呢再生成这个图像的同时,我们也会生成另外一个图像,这个图像呢只存这个任何一个像素,它所看到的几何物体的这个最浅的深度的信息。
然后我们管这个图叫做深度图或者深度缓存,也就是说啊始终我们是同步生成两个不同的东西,一个是最后的结果,咱们把它叫做frame buffer,我们把它给存在这个frame buffer里。
然后另外一个呢是生成这个我当天看到的场景,任何一个像素对应深度,然后就是说它存在一个叫做depth buffer,就是深度缓存里面,然后这么两个两个东西同时生成,然后我们利用这个深度缓存的这个这个想法。
然后我们来这个这个这个维护遮挡信息,那咱们说了这么些,还没开始说怎么做呢,对吧嗯在这之前我们提一个上,如果大家还记得的话,我们在这个在这个变换中间啊,我们提到这么一个事情。
说我们始终假设我们的相机是放在原点,并且是往负z方向去看过去的对吧,那这样的话我就是说我看到的所有的z都是负的对吧,并且如果这个数字小,反而说明这个这个这个这个呃离我们远,然后数字大呃。
反映了离我们近对吧,是这么个意思,那么在这里呢为了简化这个计算,我们把这个之前看到的这个z啊,然后给这个这个换一个概念好吧,换一个概念就是说我们认为现在啊我们这个呃固定相机,我们往场景中间去看。
我们得到了一个普通的深度,这个深度大家就可以理解成是这个点到这个到这个呃摄像机的距离,而这个距离呢永远都是正的,并且越小的距离表示越近,越大的距离表示越远,那咱们就是说单单纯对这个深度的测试来说。
咱们正假设这样比较好理解一点好吧,那咱们这样就可以来继续看这个这个深度缓存的工作原理了,在这之前呢先给大家看一眼这个深度缓存。
如果我们做的对,应该得到一个什么样的结果啊,我刚才说说这个对于一个场景来说,我们最后要渲染出一幅这个画面,也就是我们左边要的这幅图,然后呢我们同时还要这个维护。
说这个这个这个呃所谓任何一个像素看到的深度,那咱们看右边这幅图,就是说这个深度这张图,而这两张图永远是同步生成的,那右边这幅图的深度如何理解呢,咱们可以看这么一个位置。
比如说大家都知道这个立方体如果这么放的话,那我相信这个角应该是离我们的这个这个呃这个试点,或者说眼睛诶或者摄像机最近的地方,那它的深度就应该浅,那它的值就应该小对吧,然后呢呃我们知道比如说这个点。
这个点呢呃离咱们的这个试点那就相对较远,然后呢那它对应的深度就大,然后深度就大,反应在如果把它给反映在颜色上,就会它会越白对吧,对任何的像素我们都这么去记录它。
比如地板这里我会发现哦这个地方这当然地板离我们近啊,深度要浅,然后这里地板离咱们远,那咱们这个这个深度就就就这个这个这个呃相对较大一些对吧,那那这里就说明这个是对的,没问题。
那这一个深度的图或者说这个深度缓存嗯,就是我们渲染这幅图的时候,这个对应要产生的,那么呃我们说这是最后的结果呀,那咱们一开始这个这个算法应当如何去进行对吧,然后其实很简单,那咱们可以想象一下。
比如说啊咱们看这个呃,同样是这么一个物体,它有很多三角形组成,然后呢每个三角形都有可能会覆盖某个像素,那咱们现在盯着一个像素来看,比如说就这个三角形吧对吧,假如说呢这个这个这个像素啊,这个像素。
然后我一开始先画了这个地板,那我知道地板由三角形构成,这个三角形有可能会覆盖到我现在鼠标停留了这么一个像素,然后呢那我就会把这个a地板在这个点上对应的深度给记下来。
诶那么现在如果我又把这个物体给放上去了,那我就知道我现在这个物体上一定又有一些三角形,它会这个覆盖到这个像素,然后这个时候我们做一个什么操作呢,我们就考虑说哦在这个像素上。
这个这个这个物体的三角形会告诉我们哦,这个物体在这个像素上它应该是一个什么样的深度,然后他看了一眼,说我这个当前的这个深度啊,是记录的是这个地板的深度诶,我会发现我要画上去的这个东西。
然后就是说这个物体它在这个点上深度要小于这个地板,在这一点上,这个这个这个之前记录好的深度,那么就意味着好我新画进去的这个物体,在这个像素上,至少他要遮挡住这个地板,于是呢我要把这个点画上去。
画到左边这幅图上,并且我要更新右边这个图,他写的这个深度是多少,然后把这个深度更新成一个更浅的深度。
那整个算法大概就是这么一个流程,咱们总结一下啊,就是说这个深度缓存怎么做呢,首先我认为所有的这个深度缓存中的所有的像素,他们一开始记录的这个这个距离或者深度都是无限远的。
然后呢咱们这个咱们这个把这个这个这个一个个三角形,咱们以任何一个顺序啊,这个往里面做rest orization,我们刚才说刚才说了,就是说这个呃深度缓存。
它的最基本思想就是我每一个像素内记录它的最浅深度对吧,那么对于任意一个三角形诶,然后我都可以把它光栅化成这个不同的像素,所以我们就可以找到它这个任意一个三角形覆盖的任意一个像素。
这就是之前的这两个for循环的意思,那么我找到这个三角形对应的像素呢,我就知道哦,我这个新的三角形,如果我要画在这个像素内,那对于这个像素来说,它的这个这个深度在我这个新三角形上应该是什么样的深度。
然后如果这个深度小于我这个深度缓存之前记录好了的深度,那么我就把这个深度缓存的值,这个这个更新成这个小的这个深度,并且把这个新的这个三角形在这个像素给画进去对吧,我们所有操作都在一个像素上进行。
那如果说哦我这个我要先画进去一个三角形,比如说这个呃,我已经知道他要覆盖哪些像素,然后我可以算出偶在这个像素上,它应该对应的深度是多少,但深度很远比我现在已经记录了的深度要更远。
就意味着那他百分之百要被我这个当前已经记录的深度的这么一个,物体给遮挡,所以我就不应该这个把它给画在这个最后的结果上,我也不应该这个更新这个深度缓存,那么它就是这么一个道理。
那么到这里应该就是比之前这个要清晰多了,那么咱们再通过一个例子,然后可以这个更清楚地看到这么这个深度缓存到底怎么工作的,好吧,其实非常简单,看这个例子,还说这个就应该可以完全明白了。
那么一开始呢深度缓存我们存的全都是无限大的值,这个r呢咱们就认为它是无限大的值,这里多说一句啊,这个c加加里面是有无限大这么一个概念的,有一个in这么一个数,然后呃然后呢如果这个大家用不好这个数的话呢。
也可以把它定义成一个足够大的值,比如说这个这个这个十的十次方对吧,这也非常大,然后就是说只要它够大,我们认为它无限大好吧,那么一开始所有的像素它的距离都是认为哦深度是无限大的。
那么咱们现在先把它先把第一个三角形,这个红色三角形啊,咱们把这个三角形给光栅画,或者说画到这么一个屏幕上去,那么怎么画呢,那这个三角形我知道哦,它要覆盖,比如说左上角这个像素唉,然后它会覆盖这个像素。
它会覆盖好多像素,那对于每一个像素来说,咱们都做这么一个判断,好这个三角形它肯定我知道它这个这个不同位置,它对应的深度是多少,诶这个咱们下节课给大家说怎么算啊。
这但是每一个三角形它肯定自己不同位置有不同深度,这咱们应该知道好吧,那这样的话就是说对于左上角这个像素,我们发现哦三角形深度在五,然后这个左上角原本我记录的深度是在无限大诶,那我就说这个三角形。
我应该把这个三角形画在这个这个frame buffer上,并且更新这个左上角这个像素,它当前当前的这个最浅深度已经变成了五,那么对于其他的像素都是一样的,比如说这个左下角这里诶,我发现我和这个像素相比。
这个新的三角形呢要比原来我记录的深度要浅,所以我就要把这个新的三角形在这一点,在这个像素上把它划进去,并且更新深度缓存,那么这里更新完了深度深度缓存之后,大家就可以看到哦。
这里啊这里很多这个这个这个数字对吧,这也表示了这个深度,然后右边这个右边这个这一部分呢,由于这个三角形没覆盖到,所以影响不了,所以再次强调咱们这个深度缓存是发生在任何一个像素内的好吧。
然后下面这个就是这个相对有意思的一个情况了,那对于上面这个情况来说,那简单,那是三角形上的每一个点,它深度都比这无限要小吧对吧,那么如果我们在这个基础上想要再插入另外一个三角形,比如说这个三角形。
大家可以看到这个蓝色三角形,这个蓝色三角形呢大家就会发现哦,这个蓝色三角形它这个左下角这么一个点啊,离我们这个是这个视角要更近,然后它这条边离我们要更远,大家可以想象一下这是个什么样的三角形啊。
这是一个这个这个从这一个一个离我们很近的这个左下角这个点,然后我们这个空间中这个更远的方向延伸的一个空间三角形啊,是这么一个东西,然后呢咱们把这个呃把这个三角形药呃光栅化到整个这个这个屏幕上。
那咱们怎么做呢,同样道理,我们考虑每一个这个覆盖了的像素,那我们知道好这个新的三角形会覆盖这么些像素,咱们如果看它的左上角这么一个像素诶,我发现这个像素新的三角形对应的深度是八。
而我的屏幕上已经有一个三角形占据了这么一个像素,并且它的深度是五,我们就会立刻知道哦,这个新的三角形它肯定要被原来的这个三角形,它的深度是五的,这个三角形给这的,就单说在这个点上,在这个像素内呃。
所以说我们对于其他的这些判断也都应该是如此判断,比如说这个不是这个七啊,这个七这个这个位置这个像素我发现和这个五相比啊,它它仍然大于这个五,说明我们新的三角形在这个像素上一定会被原来的三角形所遮挡。
所以咱们什么事都不用做,直接忽略它就可以了,那么有一些三角形就不是这么回事了,比如说咱们看左下角这个这个三对三这个这个数来说,诶,我发现如果我要把它给画在这个像素上,我发现哦原本深度记录的是五。
说明原本那个三角形离得挺远呢,在这个点上,那么我新的这个三角形在这个点上离得要更近,那也就是说新的三角形会遮住原来的东西,那咱们做两个事,第一把这个像素涂成新的三角形的颜色,也就是说新的三角形会被看到。
第二更新这一个像素对应的这个深度值,那当前这个像素所看到的最这个近的深度,那就应该是三了,就不再是五了,那咱们对所有的这个像素都这么操作,哎那可不就是能得到一个准确的结果了吗,那在这里就可以看到哦。
原来这两个三角形啊,这个各自会覆盖另外一个三角形的一部分对吧,然后就是说呃通过这样一种办法,我们就可以维护一个逐像素的深度,那这样就可以得到一个准确的结果对吧。
那所以说这就是我们这个这个深度缓存算法的这个核心啊,再重复一遍,所有的操作都是针对任何一个像素来说的,我们要通过一个深度缓存去维护任何一个像素,像素当前能看到的最浅的深度。
然后呢这个这个呃整个一幅图都是都是这么同步的,把这个渲染的结果和这个呃和这个深度图这个同步更新,然后我们就可以最后最后最后就会得到一个准确结果了,那么在这里这个我们分析一下啊。
我们刚才说画家算法我们有n的三角形,把这n的三角形排序一遍,要花n2 n时间对吧,那么在这里呢大家可以看到,如果说如果我有前提啊,认为每个三角形大小都不是特别大,不是特别小。
它会覆盖一定的这个常数个像素好吧,我们假设是这么一个概念,比如说一个现像三角形都会覆盖,比如100个左右的像素,那这样的话,那这个深度缓存它的这个算法复杂度是多少呢,那大家可以想象。
我无非就是一个一个三角形往里填,每个三角形考虑它覆盖的常数个像素,那就是常数乘以三角形个数那么多个操作诶,那那那也就是说对于n个三角形来说嗯,就应该是o n的一个算法诶,那么这里有同学要问了诶。
我们现在是要做一个这个顺序这么一个问题哈,你怎么可能通过这个这个呃o n的算法就解决了这个顺序问题呢,就是有这么一个遮挡的问题就已经通过解决了,我们学算法课可不是这么说的对吧,我们说这个理论上来说。
要想对一系列的数字排序,然后这个得到的结果呃,就就应该是这个至少是n log n的时间复杂度对吧,那么在这里这个诶我确实得到了一个正确的顺序,谁遮挡谁对吧,但是呃这这里为什么只花了线性的时间呢。
为什么是o n呢对吧,那么这里其实是一个误解,这里我们并没有排序啊,这里其实来说我们对于任何一个像素都始终是在记录,只是在记录他这个当前所看到的最小值对吧,比如说大家这个去买东西,去买东西的话呢。
这个这个我想知道这买同样同样东西,这个到底这哪家最便宜对吧,那么我只需要这个挨个把每一家看过来,唉我始终记得说我这个当前最便宜的这个价格是多少对吧,这就可以了,那也就是说我们这个呃深度缓存的算法。
其实只是在对每一个像素一直在求最小值而已,他并没有说求求这个呃这个除了这个最小值以外,其他三角形之间这个互相的遮挡关系好吧,那这个时候咱们把它说清楚对吧,大的直接就扔掉了,就那么简单好。
然后这里是它的复杂度,那么问一个问题对吧,这个这个这个这个我们刚才提到说,画一个红三角形和一个这个紫色三角形哈,然后如果我先画那个紫色的三角形,然后我再画这个红色的三角形,得到的结果是否会不一样呢。
呃当然这里我们假设一个事情啊,就是说这个不会出现这个两个嗯不同的这个三角形,在一个像素上有相同的深度,这么一个情况好吧,如果我们假设这么一个前提的话,那么大家会发现这个这个顺序啊。
这个这个呃就是说我们这个深度缓存这个算法它有一个非常好的性质,那就是他和这个深度是没有关系的对吧,就是呃不深度啊,它和这个这个这个顺序是没有关系的,不管你通过什么样的顺序,先画哪个三角形。
后画哪个三角形,你只要维护对了这么一个深度缓存的算法,最后得到的一定是一个这个这个同样的一个结果啊,假设不会有这个任何这个两个两个三角形,在同一个像素拥有相同的深度,这个假设,那么我们多说一句。
为什么我们假设这个事情啊,因为其实来说这个假设是有一定的道理的,因为在这个嗯图形学中或者任何的这种几何的这种表示方法里边啊,很多的这些这些数字我们都是用这个浮点型这么一个精度来表示的。
就是说啊就是我们很难去准确地表示一个这个有理数,所以我们用浮点型总会造成一定的误差,然后浮点型和浮点型判断相等,是一个非常非常困难的事情,就是说在实际情况中,你几乎不可能说两个浮点型的数字。
特别是通过运算来的,两个浮点型的数字是一样的,那么基本上来说可以认为两个浮点型的数永远都不会相同,那如果我们认为这个事情的时候呢,那自然就不会有两个完全相同的深度值,当然这是一个强行解释。
在实际的这个过程中啊,这个确实真的会出现这个这个这个深度完全一样的情况,跟这种情况如何处理,咱们这节课这些课上就不做多说了好吧,然后呢这个可以,那咱们就是就是嗯把这个事儿给说清楚。
然后呢总结一下这个深度缓冲或者深度缓存,这是一个非常非常非常重要的一个算法,然后在这个算法呢就是广泛的应用在几乎所有的这个这个硬件中,目前来说所有的光栅化都会做一个这个深度的这个测试。
然后就是说呃这样的话每一个像素,然后我维护一个这个深度的这个测试,然后就可以就可以得到正确的遮挡算法好吧,这是一个这个非常实用的算法,然后这里再多说一句,咱们之前是不是提到说为了做这个反走样。
为了做反走样,我们可以用这个m s a a的方法,我一个像素内部取好多好多不同的这个这个采样点对吧,那这些对于不同的采样点来说,如果我们要应用这个深度缓存,那我们就需要对于每一个采样点做一个。
它这个这个他所能看到的深度这么一个信息,也就是相当于这个z buffer,其实这个还得考虑到说这个嗯,这个呃可能是不是对每一个像素应用一个深度,而是对每一个这个采样点进行一个这个这个呃z版本。
这么一个一个记录好吧,然后嗯这就是啊我为什么提这个事呢,是因为咱们这个作业二里面有一个提纲内容,就是说为大家感兴趣的话,大家可以说可以可以对这个m s a a的结果做一个这个深度缓存。
然后如果做的对的话,大家这个应该会看到这个这个非常不错的,这个美观的这个这个边界的这个效果,好吧啊行,那没问题,那咱们说到这儿啊,这就是深度缓存,目前来说有什么问题吗,同学们,我正好我也看一下啊。
这个这个有没有同学问这个事情哦好吧,有同学问我说说为什么我这个说左手这个右手我总是反的啊,这是因为这个这个这个我这边这个摄像头这个是反的,对,这是好问题,比如说我现在举的手是我的左手啊,没有问题。
然后这个这个这个这个呃我我想想办法看这个要怎么处理啊,嗯然后有同学说为什么这个近处是黑的,因为近处是这个深度直小啊,这个如果把深度值变成颜色值,颜色值小可不是意味着是黑的嘛对吧,这个意思好。
然后我看有没有新问题哈,嗯嗯好,应该差不多,那咱们这个深度缓存,这里说到这儿,到此为止,咱们这个呃关于这个这个这个嗯光栅化这块就应该已经说的明白了,那咱们下面继续进展。
那当然这个感觉效率又稍微低了那么点好吧哦,有同学问透明物体怎么处理,透明物体处理不了啊,the buer一定处理不了这个透明物体的深度,然后然后这个需要特殊处理好吧,然后ok那咱们先继续进展,好吧好。
那咱们说完光山话再说这个这个着色,那咱们为什么要说着色呢,比如这个咱们可以先看一看我们目前都学了什么,然后先这个这个从这个稍微高层次的理解一下,我们现在到这个到目前为止都讲了什么。
比如说呢这个大家可以看左边呃,左上角,然后我们有了这个那么一个模型对吧,空间中我也可以定义一个摄像机,然后呢我可以把这个模型通过某些变换,然后变换成某种姿势,像这个机器人对吧。
然后呢我可以通过这个啊这个视图变换,然后我把这个呃摄像机始终放在000往负z看对吧,大家还记得这个这个view这么一个一个一个变换对吧,然后然后呢这个嗯变换完了之后。
那我自然就要把这个三维空间中的东西变成这个二维的,那么这就是投影这么一个变换啊,这个变化完了之后,我知道所有东西都在这个二维的呃这个屏幕上了,那么根据它二维的屏幕上的这个这个呃。
二维的屏幕和这个和这个嗯就是我们做完了这个投影变换的,-1~1的三次方这么一个这个立方体这么一个互相关系,我们就知道x和y应该如何映射,也就相当于这个三角形在屏幕上会覆盖哪些。
这个屏幕空间上面的这个坐标,然后呢咱们会把它给变成一个这个这个呃采样了的结果,也就是光栅化对吧,那也就是说我们做过model view projection,然后再做这个viewport呃。
这个做完了之后再做realization,现在我们已经可以把它给填在这个屏幕上了。
那么我们目前所做的可以给大家一个什么样的结果呢,大家可以看这么一个例子,是一个动画啊,这个大家可以看到是一系列的这个呃这个这个立方体对吧,基本上来说是立方体,然后这个就在屏幕上这么这么旋转。
当然这这张图这个看上去大家可能会有些视觉误差,有同学告诉我,他是这个逆时针转的,有同学说这是顺时针转的,所以到底是怎么回事呢,这个是正是因为出现了一些问题,让这个我们的大脑啊无法接受,这到底是怎么回事。
因为因为这并不是我们期待看到的结果,我们期待看到的是什么呢,我们期待看到的应该是这么一个结果,没错吧,就是说我们期待看到的是这些这个这些立方体,大家可以看到,虽然每个立方体是同一个颜色诶。
那么那么在同一个立方体,同一种颜色的立方体的不同面上,大家可以看到这个不同面的朝向啊,这个为什么会给我不同的颜色,而反而这样看来我觉得更真实些,比刚才这个对吧,大家可以看对比一下,这是之前的这个结果。
然后对于这个这个新的这个结果诶,每一个面它颜色略有不同对吧,这个为什么看上去就更真实一些呢,这也就是说我们这个下一步要做的操作,也就是着色,就是当我把这个不同的三角形都给画在了这个屏幕上之后。
它都变成不同的像素之后,我问这么一个问题,这些像素的值或者颜色都应该是什么呢对吧。
那么这就是着色的内容,那么从这张图大家可以看得非常明确对吧,比如说这个真实的世界,这个是是是这个非常非常非常复杂的,当然这并不是真实世界啊,这个是渲染的结果啊,就是说呃这个呃大家可以看到。
比如说像这个这个这个应该不是咖啡啊,某种巧克力奶茶对吧,然后看到他这个这个泡沫对吧,看到这个比如说这里这个杯子里面这个这个这个茶吧,咱们假设是这样,然后蛋挞,比如说这个葡萄。
当然这葡萄看起来不怎么真实对吧,为什么大家看到的这个这个不同的东西啊,它这个这个呃会显示出不同的颜色对吧,为什么可以看到这个五彩缤纷的这个世界对吧,然后呢在不同的光照下,比如说咱们这个都可以想象。
比如说我这个光源挪一下什么位置,诶我看到的这些物体还是什么些物体,它们并没有发生位置上的变化,但是诶颜色上发生了变化,但也就是说这就是说我们目前来说暂时还没开始解决的问题。
这个问题就是所谓着色这么一个问题,那么呃到这里呢,这个如果有同学之前看过这个games系列啊,有一节这个给大家说这个着色的课,我们在这里这块儿是跟那个应该是很相似的,那咱们这个呃如果听过的话。
如果没听过的呢,咱们这个这个呃就把这一块儿,然后算是从从头学起来好吧,那么所谓着色,那我们既然已经用了这个概念了呢,咱们就一开始先给它一个定义对吧,那什么是着色呢,那咱们查一查字典。
可以查到这个尾式的字典告诉我们哦,这个这个着色呃,shading啊,名词,然后说是干什么呢,说可以说是这个这个这个着色的意思就是darkling or coloring of an illustration of。
diagram with parallel lines or a block of color,这说的什么意思呢,首先他做了两件事情,第一引入明暗的不同,所谓darkening。
有些地方呢会有这个呃明亮一些,有些地方会暗一些诶,然后color ing相当于有些地方有颜色,有些地方有不同颜色,有些地方没有颜色对吧,然后就是引入这么的一个过程,那通过什么办法呢。
自然这里说的是说在绘画上通过什么办法引入明暗和颜色的不同,然后呢我们所说的是在图形学上有什么不一样对吧,那么大家可以想象,如果大家学过呃这个素描哈,比如画一个球,然后我知道有一个这个光源。
然后光源这个这个打到的这个这个球上某一块也会形成一个高光,挺亮的,然后呢这个背向光源的这一面又由于接受不到光,然后它就比较暗,然后呢这个会产生一个投影,然后这个影子里面就是这个比较深的颜色对吧。
然后就是说谁定的,在我们途经学里面,这个做的工作大概是就是这样,然后呢说明这个这个字典定义的没什么问题,但是呢对于咱们这这门课来说,我们把它定义成什么呢。
我们把它给定义成对不同的物体应用不同材质这么一个过程叫做着色,那么这个好理解,比如说这一个一个一个球,它可以是一个石膏球,它可以是一个金属球,可以是个木头球,那各不相同。
为什么说这个这个呃一一个同样的球诶,看上去各不相同,正是因为它有着不同的材质,所谓材质,也就是说这个呃不同的材质,肯定和光线的相互作用有不同的一个方法对吧,那么那么这就是表示了这个不同的材质。
那么咱们这么理解就可以把这个着色和材质放在一块儿去讲好吧,那咱们这么这么想好,那么这个ok那么我们这里呢给大家举一个举个例子,说一个最最最最基础的这个这个着色模型对吧,然后这个叫做什么呢。
叫做bling phone,可以看到啊,这是一个这个这是它的名字叫blaying phone,这是这个呃这个命名呢是考虑到这么两个人,然后把这个名字结合在一块这个布林峰。
然后这个或者呃大家可以看到叫做反射模型,所有反射模型呢我们就是说这个光线如何与这个这个材质进行作用,并且是如何去反射的,好咱们把这个事情搞清楚就可以,那么这个bling缝反射模型。
就是我们要说的一个这个呃这个着色模型好吧,那么呃咱们可以先看这么一个例子,说我们要说的这个模型到底是怎么回事儿哈,就是说大家可以首先看这么几个这个茶杯对吧。
然后我可以看到说哦这个茶杯应该是在这个呃某一个光源,应该这个光源在这个右上这么一个方向上的这个一一张照片对吧,然后这个光源呢这个照亮了整个这个这个这些茶杯,我可以基本的看到说啊。
这个茶杯上大概有那么些这个不同的地方,我看到它这个这个这个颜色啊,有那么几个这个有特征的地方,第一我可以明显的在每一个茶杯上看到一个高光对吧,这个是这个是算是这个绘画上的一个术语,叫做高光。
就是特别亮的一块对吧,然后呢我们又可以看到一个什么现象呢,我们又可以看到哦,基本上来说整个一个这个这个嗯这这个茶杯的这个表面啊,除了高光,其他的是一个变化,相对不是那么剧烈的一个一个颜色的变化。
比如这里从黄颜色变到这个深颜色的这个黄颜色对吧,然后这里红颜色这里相对较浅,这里红颜色相对较深,那么对于这一系列变化不是特别明显的这一块呢,我们管它叫做漫反射部分好吧,所谓漫反射。
大家这个学过物理对不对,这个漫反射很好理解,强就是一个漫反射,什么叫漫反射,这个光线,一根光线啊打到墙的这个墙面上,然后它会被这个反射到四面八方去,说明这个墙特别粗糙对吧。
然后会被反射到各个不同的地方去,然后这个高高光同样也可以这么理解,高光是怎么来的呢,那就是说如果有一个表面特别光滑,那么我我有一根光线打到一个表面上去。
那他就会就会往这个它的这个这个这个所谓镜面反射方向附近,这个去反射,那这个我们就管它叫做高光这一项好吧,然后呢另外一项比较有意思,咱们这想一想这么一个问题哈,这里有一个光源在右上。
那按说哈按说这一个这个位置,就是我们这个鼠标线所在的这么一个位置,按说他应该不能被这个光源所照亮,也就是说他他看不到这个光源,那我们学过物理知道说如果有一个点,它看不到光,接收不到光。
那么这一点应该是黑的对吧,那我们看到东西之所以看到东西,那也就是说这个点肯定是接收到光了的,那这个是怎么回事呢,这个时候啊我们说这个点接收到的光照,它并不是直接光照,它是一种间接光照,什么叫间接光照。
我给大家举个例子,比如说特别是这个这个图上来说啊,比如说这个光源会达到这个墙面某一个位置,比如说这儿,然后这个墙面是漫反射,那总有一部分光会打到这儿,打到这桌子这个地方,打到桌桌子这个地方。
这个桌子稍微有点镜面对吧,然后他这基本上来说他会这个肯定多少有一点光会打到这里诶,打到这里之后,他再会经过这个反射回到人的眼睛里,诶,这样的话我们就说这个点确实他接收到了一部分光,接收到什么光呢。
光线打到墙,打到桌子再达到这个点诶,也就是说它不是直接接收到的这个光照,它是通过别的物体反射接收到的光照,那么这个时候我们管的这个这这部分光照叫间接光照,那当然了,对于间接光照来说,这部分相对复杂。
咱们在之后的这个这个路径追踪这块给大家介绍,然后呢这一块儿呃,在这里我们做一个假设,假设什么呢,假设在这个点上,这个点它可以接收到来自四面八方的不同的反射光,而这个反射光基本上来说只是是一个常量。
咱们这么理解好吧,就假设说任何一个点上,它都会接收到这个来自于环境的反射光,然后这个反射光很复杂,但咱们把它简化掉,就是这么个意思,那么咱们总结起来,从这幅图上我可以看到说这个着色呀。
就单单说从这一个这个光源上来看,就会形成三种不同的部分对吧,一个是高光,一个是漫反射,一个是这个环境光照对吧,然后然后呃呃然后呃是是在这个位置对,那咱们把这三部分分别都分析表示出来。
咱们自然就可以做出一种材质,使得它长得跟这个这个杯子基本上很相似对吧,那咱们可以看看这个如何进展好吧,那么在进展之前,咱们需要定义一些东西对吧,我们定义一些什么呢,定义一些关于这个这个表面啊。
啊这个那这个光源啊,这个观测啊,各个不同的这些方向,咱们把这些事先说明白,那咱们可以看右边这幅图嗯,我们现在考虑的光照呢是考虑任何一个点上对吧,然后就是说我们可以假设说啊。
我们看到的这个点叫做shading point,就是这个这个这么一个点,我要考虑这个点它的着色结果是什么,那么对于一个shading point,他应该在一个物体表面上,它在一个物体表面上。
物体表面可以是曲面对吧,但是我们认为在一个局部的一个非常小的范围内,它永远是一个平面,那在一个一个极小的范围内,我可以这么理解,然后呢同样道理,我可以在这个平面定义平面的法线。
所谓法线就是指这个垂直于这个平面的一个一个方向好吧,然后然后这个呢就就就对对应到这幅图里面,这个发现就是这个n这么一个向量,然后这个我同样呢可以规定另外两个方向,什么方向呢,第一观测方向。
这里比如说我的相机在这个位置,那么我们从这个shading point网相机去连一个方向哎,也就是这里指指的这个v这么一个方向,我们管它叫这个呃,观察方向或者观测方向无所谓。
就是view direction,然后呢这个同样道理,从这个点我看向这个光源,我也可以看到一个方向,这个方向我们管它叫这个光照方向叫l就light light direction好吧。
然后呃我们就定义这么几个方向好吧,shining point,然后发现然后观察方向v和这个光照方向l,然后这里呢多说一句,就是说呢这个我们既然定义它是方向,那么这些向量自然而然都应该是单位向量好吧。
这个v也好,n也好,l也好,如果大家还记得的话,我们只想表示方向哦,那那就是说我们把它定义成这个单位向量长度永远是一,那么这三个向量长度都是一好,那那是呃这一点,然后呢另外一点关于这个呃这个平面上。
比如任何一个点,就是这个shading point本身它是一个什么样的颜色对吧,我应该定义一些跟这些这个物体表面相关的属性,比如说它有多么亮对吧,比如说这个大家知道如果这个陶瓷的物体外面上了鼬之后。
然后就会看起来这个非常亮,然后如果没有的话,看上去基本上来说就就这个跟这个石膏很像对吧,所以这这样一个这个有有多么亮,这个我们管它叫shininess,这个和亮度没关系啊,这是不同的事,呃。
所谓shininess,然后color这也就是它的不同的颜色,比如说一个这个光打到一个这个这个这个木头上对吧,木头各处你可以看到纹路,但其实基本上反射这个光的这个呃方法是一样的。
仅仅是说各个地方有一个不同的颜色,然后那么肯定会有一些这个呃每一个点各不相同的,这个物体表面的属性好。
那咱们把这个给定义好之后啊,之后的就比较容易了好然后呢这个在进展之前我们再多说一句,就是说这个呃我们所说的着色啊,目前来说我们所说的着色,我们刚才规定了说哎这个着色的点shading point。
然后它的各种不同的方向,我们那考虑就只考虑这个点和其他几个不同的方向,我们不考虑说是不是这个点在阴影内,就是这个意思就是说所谓local就是说局部的意思。
就是说所谓局部意思就是说呢我考虑任何一个点的着色情况,我就只看他自己,然后就就就顶多就看光照和观测的这个这个范围呃,这个这个方向,那我不考虑说其他物体的存在,比如说像这里呃,我鼠标停留的这个位置啊。
大家可以看到这么一个物体,首先我可以猜测这个灯光可能是在左上角对吧,那么按说这个物体应该会投射出来一个阴影,在这个地方应该是有阴影的,但是在这里阴影我们不考虑,为什么呢,因为在这一点上。
我们考虑它的着色,我们只考虑这个光线来的这个方向,我们并不考虑这个光线是不是被别的东西挡住哈,就只看他自己,然后我们别的都不管,那这里就是说我们着色为什么它有局部性,就是我们这么说的。
那也就是说呃考虑了着色之后,大家可以看到明暗变化没问题,但是大家看不到阴影,那么阴影怎么生成呢,咱们之后再说好吧,那在这里其实问题并不大哈,因为说这个中文上这个并不会有一些这个这个企业的出现。
就是说这个shading和shadow这两个事情,一个叫着色,一个叫阴影,这两个上中文好区分,英文上稍微困难一点,可能大家会有会有一些这个问题好吧,那咱们说清楚啊,着色不考虑其他任何物体的存在。
考虑这个点自己。
然后这个所以没有意义好,那咱们这个这个继续往后进展哈,那咱们刚才已经提到了,说这个有三个不同的部分,咱们分别把它表示出来,那怎么表示呢,那咱们可以这个这个从最简单的开始,从漫反射这一项开始。
那么我们说啊什么叫漫反射,当你这个有一个物体达到这个物体,这个这个呃不有一根光线达到物体的这个表面努力点的时候,那这个就叫漫反射,那么呃这个这张图大家就可以从这里看到哦,有一个入射的光线打到这个点。
然后这个反射会向各个方向去,那咱们把这个事情表述出来就好了,对不对,然后呃这这个自然是如此,那么这个事情呢却没那么容易,比如说咱们可以看一下这个这么一个例子哈,就是说嗯当我的这个这个物体表面啊。
我考虑的是这个这个所谓shading point,他的这个表面的朝向和这个这个光照有一定夹角的时候,然后我会发现这个刚才大家可以看到那几个旋转的立方体了,对不对,我会发现这个得到的明暗是不一样的。
哎这个就很奇怪,同样的光,这个我照到同样的表面上,以不同的角度照上去,为什么得到的这个这个明暗不一样呢,诶这个这个时候呢就是说我们要分析一下这个这个道理,大家可以看这么三幅图,这么三幅图。
假如说啊这里我有这个六根这个光线,假如光是离散的啊,假如说光是离散的,然后这个我可以用不同的光线来代替,每一根光线代表了一个固定的能量,然后呢我假设有一个这个这个呃物体表面呃,在这里,然后我发现哦。
如果它和这个光线来源垂直的话,那它会接收到所有的六根光线,那如果说我这个表面旋转了某一个角度,在这里正好是60度啊,然后我会发现旋转了之后,这个表面只能接收到三根光线。
那也就是说这个时候呢这个物体表面就应该暗一点,那当然如果说我要把它推广到一个这个某个理论上去呢,那也就是说这个物体表面的法线和这个光线来源方向,也就是l方向和n方向这两个方向。
它的夹角决定了说这个物体这个呃这个物体表面应该有多么亮对吧,那么呃这里就是说我们通过观测可以找到的一个一个结论,那么这一个这个更科学一点的理解是这样的,首先呢我们要考虑说这个光啊,它是一种能量。
这个光是能量就说明什么呢,就说明这个呃我要看到的这些物体其实相当于是这些物体,它接收到了多少多少多少的能量对吧,那么我们说这个大家比如说这个都用过这个太阳能对吧,所谓太阳能大家用多大的这个太阳能板。
他就能接收到多少能量对吧,然后就是说如果我这个板用的大小不一样了,接收到能量自然不一样,那如果我要考虑一个这个shading point的自己,那么我要考虑他接收到多少能量,我就考虑它周围一个单位面积。
我认为他这个面积始终是不变的,然后这个它这个着色点周围的一个单位面积,它会收到多少能量,这样才有意义,否则的话它跟面积有关对吧,那这样的话这这这就说明不了问题,所以咱们用单位面积。
这就是为什么我们旋转这个的时候,这个这个这个呃嗯物体表面啊,它这个呃单位面积的大小始终不变对吧,然后呢就考虑接收到多少能量,然后那么我们想接触到多少能量,在生活中我们其实是观察到的,为什么呢。
我们想象这么一个问题,为什么说这个这个地球上有四季之分,为什么有冬天对吧,为什么,为什么这个这个有冬天夏天之这个区分对吧,那么这个是为什么呢,大家学过地理对吧。
这个并不是因为说这个夏天我这个太阳地球离太阳要近一些,然后冬天要离远一些对吧,那是怎么回事呢,其实是是这么回事,是因为夏天我们所处的这个位置,比如说北半球,然后它会被光这个直射。
这个光照几乎是垂直这个我们所处的这个地方的对吧,然后呢呃这就说明这就说明这个夏天和冬天的区别,或者说冷和暖的区别,其实是应该是因为这个光线和这个我们所处的这个地球这个表面。
当前这个位置它的夹角不同而造成的,而这个就解释了说为什么北半球是这个夏天的时候,南半球是在冬天,因为光线直射北半球的时候,然后这个时候光线就你不是在直射南半球,所以南半球那边接收到单位面积。
接受到能量要小,所以道理一样,那咱们说了这个这个之后呢,我们再回头看这么这么一个这个漫反射这么一个原理,那么我考虑任何一个shading point,它周围的单位面积会接收到多少能量。
那么它自然是和这个这个光线的这个角度呈一定关系的,那这个角度接收到多少能量,这个我们有一个这个定律叫lambert呃,余弦定律,然后这个这个numbers这个定律呢,这定义了什么呢。
定义的就是说哦我接收到的这个能量和这个光线方向和光照方向,和这个呃法线方向,它们两个之间的夹角的余弦是成正比的啊,当然有道理的,大家可以试试特殊值对吧,如果这个法师前方向和光照方向一样。
那就是直射就接收到所有的能量,那如果说他们两个不是直射对吧,然后就是说特别的一种情况,就是说如果他这个这个嗯物体表面方向,这个呃被旋转的这个嗯几乎和光照方向垂直了哈。
就是说它的这个法线方向几乎和光照的方向垂直,那也就是说啊光照方向几乎和这个表面是一平的情况下,那这个单位面积几乎就接受不到多少光对吧,那这样的这样说就有道理,那么咱们通过这个就分析说了。
说这个啊嗯给定一个嗯trading point,他的这个嗯漫反射部分,它会接收到多少光,那么我们提到了接收,我们再提提一个事情,就是传就是就是发生,就是说这个呃能量是从哪儿来的对吧。
我们知道东西这个物体不同的物体被这个光所照亮,那么首先这个光得得产生对吧,那咱们想象一下光是一种能量,如果我们假设这个光来自于一个光源,在这里呢,我们认为它是一个点光源。
那么这个点光源无时无刻不在以一定的这个呃这个这个方式对吧,往四面八方辐射出不同的能量,那么我们有一个这个很这个聪明的观测方法是什么呢,我们认为啊在任何一个时刻。
这个这个点光源辐射出来的能量往四面八方能量,如果认为往四面八方都是一样的,那么这能量一定集中在一个所谓的球壳上,就是这这么一个意思,比如说在某一个时间,这个能量集中在这里。
那么在下一个时间它会传播到这里,仍然在一个球壳上,因为往各个方向去的这个速度我们也认为是一样的,那么同样道理,过了很长时间之后,它会这个能量会集中在这样一个球壳上,但是呢我们所说的是任何一个时刻。
这个这个呃这个能量他们现在这个它它它的位置在哪对吧,这个时间零在这里,时间一在这里,时间多少在这里,但是有一个定律是能量守恒的定律对吧,对于我之前这个什么时候所辐射出来的这个能量。
然后没有任何的损失好吧,那么在这个中心离得离中心近的球壳上的能量和,在这个离中心远的球壳的能量上诶,应该是完全相同的能量对吧,这是正是这个远处的这一个球壳上能量,正是某一个时刻。
这个进出的是这个求和能量呃,传播过去的,那么我们发现一个问题哈,原本说这个能量都集中在一个小的轴壳上,就意味着这个球壳上每一个点或者每一个位置啊,它的能量是很多的,然后呢这个这个传播过程中球越变越大。
那球壳的这个这个呃表面积也越变越大,那也就意味说在某一个点上,在这个球壳的某一个点上,它其实对应的能量它是越来越少越来越少,对不对,那如果我们考虑能量守恒的话,我们考虑在一个单位的距离。
就是这个就假设说啊,这个球壳它和这个呃嗯这个点光源的距离是一的时候,那么我们定义这个光的强度是i记得这里是强度之后,我们会给大家说定义这个这个就光线传播的这个各种各样的物理量啊。
这里我们用强度其实来说并不合理,那么咱们在这里先这么说着好吧,就是说我们认为啊在这一个点上,这光的强度是i那么如果它传播到这个距离为二的这个距离,就是说这个距离嗯在这个球壳上这一个点。
那这个点这个时候这一个点上的能量就比在中间这么一个球壳上,这个点能量要小很多,那么考虑能量守恒,那么这一个点的能量在单位上面,然后如如果我们乘以它的球壳的面积是四派对吧。
就是四派乘以这个i应该等于什么呢,应该等于这个四派二平方乘以这个地方的这个呃光的强度,那这是能量守恒告诉我们的,那这个时候光的强度是多少呢,那一推就推出来了,就是i除以二平方。
就相当于这个事情告诉我们什么呢,这个事情告诉我们这个光线在传播的过程中,如果我们考虑单位面积在任何一个一个一个位置上,然后它这个这个呃所能接收到能量是和这个光线传播的距离,乘乘这个平方反比的。
就是说这个这个是r平方对吧,就是说这个呃光线传播的距离越长,然后它这个呃对于任何一个点,它接收到的能量,然后呃单位面积上接收到的能量是是这么一个衰减的规律,好那么现在我们就得到了第二个结论。
就是说我们假设知道一个点光源,然后呢我们就知道说呃这个我的shining point离点光源有多远,那我就知道有多少的光真正传播到这个点光源的附近了对吧,然后这就是说呃我可以呃这么算出来。
这么算出来这个呃有多少光传播到了当前的shading point,我们又知道有多少光在这个shading point上会被吸收,那我们把这两个结合在一块儿。
我们就可以得到这个diffuse的这个这个表示方法了,是什么意思呢,咱们看一下啊,就是说假设我们有一个点光源,这个点光源呢离这个shading point有一定的距离,这个距离我们可以简单的算出来。
然后这个距离就是二,那么我们就知道,如果这个点光源我定义它的光强度在这个呃这个单位面积上呃,单位距离上它的强度是i那么在这么远的距离上,在这个r的距离上。
它传播到这个shading point上的能量是多少,也就是说到达shing point的能量,我们又知道到达了这个地方的能量会被这个这个物体表面接收,而且接收多少取决于刚才我们说的lamber对吧。
余弦余弦定理,然后我们就知道说这个有多少能量会被接收,然后这个余弦呢自然就是这个两个两个向量,两个单位向量的点乘,就是这个夹角的余弦没有问题,那接收到了多少能量,然后呃然后呃到达了多少能量。
然后接收了多少能量,我们就可以算出来这个关于漫反射这一块儿,最后我们到底应该会看到多少能量,就是也就是说看到物体的明暗,就可以通过这个来算出来了,没问题吧,那这里有很多事情需要提啊,第一这个余弦好算。
两个向量的点乘,咱们老早就说过了,呃,单位向量的点乘,那么这里为什么要做一个max 0是什么意思呢,就是说当这两个这个这个向量点乘呃,得到了一个负数的时候,那我们就觉得这里应该没有什么物理意义。
因为有一个这个光线,就是说呃从下面穿过这个这个物体,达到了这个这个物体的这个表面,然后然后这种情况下才会出现说这个l和n的点乘是负的,嗯那这种情况下没有任何物理意义,因为我们考虑的是反射。
没没没说什么折射什么其他事儿对吧,那这种情况下我就认为这种呃是不可能有贡献的,所以说这个嗯当这个n和l点成成负数的时候,我们就认为它是零了好吧,那也就是说呃有多少能量到达,有多少能量被接收。
然后都考虑完了之后,还有一个事情呢,就是说我们原本考虑说是是是这样哈,就是说呃对于这个这个点来说,他自己本身为什么会有颜色,我们考虑一下这么一个事情,对于对于这个shading point有颜色来说。
只有一个可能性,就是说这个点它会吸收一部分的这个这个颜色啊,或者说能量,然后它反射出去的是它不吸收的部分,咱们学过物理对吧,那么我如果任何不同的点有不同的吸收率。
那我自然得出来的这个这个结果就会产生不同的颜色,特别是对不同波长产生的颜色对吧,那咱们在这里也可以去呃这个把这个事情给描述出来,如果我们定义有一个系数在这个多少这个能能量这个被接收了之后啊。
呃定义一个系数,这个系数定义成kd,然后这个这个呃就表示这个diffuse啊,就是这个漫漫摄像的系数,那如果这个系数它是一,那就表示这个点完全不吸收能量,那该多少能量进来多少能量反射出去,那是最亮的。
那如果说这个这个这个值是零,那就意味着哦吼这个表面是黑的,那意味着我这个这个光线打到他之后,所有能量都被吸收了,没有能量这个反射数据对吧,那如果那这样的话,就是说这个这就是这个这个这个表示了一个明暗。
表示了这个这个点本身它到底吸收多少能,那么如果我们把这个数量表示成一个向量,它有红有绿,绿有有有蓝,分别都是0~1之间,然后咱们就可以定义一个在当前这个这个呃shing point上。
就可以定义某一种颜色,就是就是这么一个道理好吧,然后就是说我们可以通过这种方式诶,我们这样把这个所有的事情都给这个描述清楚,那么到最后一步,我们说漫反射,那既然是光照对吧,打到这个点上。
那就意味着一个事件,就意味着我不管从哪儿观测它,就观察他观察这个点,那我看到的结果应该是一模一样的对吧,也就是说这个如果大家还记得这个光线啊,那么我从这个方面上看得到的应该是一个能量。
然后从另外一个方向看得到另外一个能量应该是完完全全一样的,也就是反映了说我们这个漫反射像啊,应该跟你的观察的方向完全没有关系,跟这个v完全没有关系,那么咱们从这个右边的式子上来看也是如此对吧。
我们考虑的是这个呃光线与这个法线之间的夹角,就是这个n点成l我们完全没有考虑这个杯的事情,而这是有道理的,那么到此为止,这个漫反射这就说明白了,那么大家可以看一下这个漫反射说明了一个什么问题啊。
比如说大家看这个比如石膏球这么一个物体,左边呢有一个这个左上角有一个点光源,它在照亮这么一个石膏球,我们会发现啊,这个太有道理了,为什么呢,因为我看这里是是是白的。
然后这个从白的这边这个渐渐渐渐过渡到黑的,那么为什么这里是不是白的呢,因为这里这个接收到了更多的能量,为什么接收到更多的能量呢,因为这里的表面法线对吧,法线是垂直于表面的这个方向。
它和这个光照方向是一致的,然后然后就是说这个这个当然就是那个cos那个夹角得到结果是一,那么为什么在这个侧面上它的结果会变黑呢,那大家可以想象在这个侧面上,比如说这里,那他法线是朝哪儿的。
那是朝我们这个这个方向对吧,然后我们知道这个呃light的方向从左上角来,也就是说我观察到呃,不好意思,这个观察到这个光光线的这个这个方向,这个l啊是往那儿去的,然后呢这个法线方向往这儿来的。
那么他们点成非常接近于一,而这些接近于零呃这两个方向非常接近于垂直,也就是说这会告诉我们嗯,这里接收到的能量要相对较小诶,所以这就说明它会有一个这么一个渐变这么一个过程好。
那这个就是说这个漫反射会告诉我们的呃,呃这个这个道理好没问题,那这个漫反射我们刚才说啊,前面有一个关于颜色的系数,那这个系数自然决定了它整体上有多么这个明亮,假如说每个点定义一个相同的系数。
这里呢这个就是一个很小的kd对应对应的值,这里就是一个相对较大的kd对应的值好,那到目前为止,咱们就把这个漫反射这部分说明白了,然后然后这里呢大家可以看到有一个现象什么呢。
就是说我们说漫反射表示了这个嗯在在这个任何一个点上,有光线打进来之后,可并不意味着说这个嗯大家看到的这个这个结果就是完全是平的,而是说跟他的这个呃当前的这个不同的位置,它的这个表面朝向是有关系的。
只不过意味着什么呢,意味着说不管你从哪个方向看这个点,比如说咱们还是看这个点,如果光光源位置不变,那就意味着l方向和n方向都不变,那么我们我从这个正方正的这个方向上去看这个点。
跟我从侧面去看这个点得到的结果,看到的结果亮度是应该是一模一样的,这个才是漫反射这个基本原理好吧,那咱们这个就基本上来说就说说到呃,今天这节课就说到这里,然后咱们下节课会继续把这个着色这块给说完。
然后咱们把另外的几几点,这个这个这个这个嗯嗯就是高光下和这个环境光下,咱们把它加在一块儿,最后能得到一个准确结果好吧,那那咱们说到这儿啊,我现在来看一下啊,这个嗯有同学问了一些问题啊,嗯ok嗯好哦。
有同学提到说这个kd呢这个考虑到能量守恒的原因,是不是应该加一个这个加一个嗯,嗯嗯某一个这个这个嗯常数其实应该是的啊,就是说我们之后会再提这个准确的这个模型上会给大家说这件事情。
我们目前所说的这个bling phone呢,这个模型是一个相对简单的模型,然后基本上来说不太考虑物理真实性,虽然大家看到中间还涉及到一点点推导对吧,其实有一点道理的,那么那么呃但是它不是完全准确的。
这里kd呢我们管它叫漫反射系数,但是确实并不是一个这个呃准确的物理上的写法,咱们之后会说好吧,还是一样,到了这个路径追踪这一块儿会给大家着重把这个事情说明白,然后所以它是一个经验性的模型。
并不是一个这个这个完全符合物理的模型好吧,然后呢这个呃前面有同学问说,为什么这个我要按球的表面积算,而不是按照这个圆的周长算,而是因为这个我们考虑三维空间中的这个这个能量的辐射啊。
比如说三维空间中有一个这个点光源,它当然是往三维空间中这个任何一个这个方向去辐射,那看到的自然是一个球的表面对吧,这么这么理解没问题,那这个好吧,嗯那今天这个咱们就说到这儿啊,然后偶稍等哈。
嗯嗯那是在模型空间哦,这个嗯并没有关系啊,这个这个在任何什么样不同的空间里面没有关系,就是说我们认为所有点都是世界坐标里面,然后就是说嗯所有的计算都是这个这个嗯。
就是就是就比如说把这个shing point,然后以及这个光源,也就是说发现所有的东西都是在这个世界坐标里面,这个描述的都是他的这个嗯就是xyz啊,然后我想象一下啊,嗯其他应该好像没有什么其他问题了。
差不多吧,那那咱们今天这个就说到这儿,然后这个这就是为什么这个我们需要三节课把它给说完对吧,原本两节课的内容我觉得太赶,而这样说的话,嗯ok应该能够好理解一些,那么课后大家需要理解的事情是这样。
就是说第一我们这边这个讲的第一个这个漫反射这一部分啊,希望把这个多少光这个到达shining point,然后以及说为什么有颜色,把这几块不同地方理解清楚,之前要写那个呃这个深度测试哈。
那一块相对较容易,然后那块儿稍微读一读伪代码,然后应该可以写得比较顺利,嗯大概就是这么安排,然后咱们下一节课把这个关于着色这块儿得说完,然后这个管线这块儿应该也可以说完,差不多好吧,那咱们就这么安排好。
哎呀行,那就谢谢大家,然后咱们之后得有问题,欢迎在这个论坛上踊跃提问啊,不一定非要和作业相关啊,和这些概念性的东西都可以问啊,那咱们把时间交给技术秘书。
然后同学们咱们下次再见,谢谢大家啊。
GAMES101-现代计算机图形学入门-闫令琪 - P8:Lecture 08 Shading 2 (Shading, Pipeline and Texture Mapping) - GAMES-Webinar - BV1X7411F744
感谢大家的支持,那咱们已经讲到第八课了啊,这个这个呃不错,哎呀说起来这这这个啊我这个这个课程这个标题还没改成games好吧,那今天就先这么这么正,内容已经改过来了啊,然后就是说呃我是这么想的。
每讲一次呢,这个调整一系列的新东西,然后这个中文课肯定跟之前的英文课有着这个呃这个一系列的区别,好吧嗯,ok那咱们这个从标题可以看到,然后今天讲shading的第二部分着色二对吧。
然后把这个一个着色模型讲完这个不灵棚的模型,然后把这个图形管线和这个纹理映射给大家说清楚好吧,然后在这个这个课程之前呢,说几个事儿啊,一个是这个呃,你作业二作业二目前有45份提交,非常好啊。
然后这个还是鼓励大家尽早开始,然后我说了这个作业框架都是经过这个两字这个英文课的考验呢,所以所以说这个早点开始应该不会有什么问题啊,就是说不会涉及到说这个框架会导致大家早点开始。
会这个这个其实这个动作还会慢一些啊,然后有同学反映说得到的三角形这个上下颠倒,这个没有问题啊,为什么呢,一个是说首先就是说我们这个在这个框架里面,和我们这个推导里面可能会存在一些不一致的这个情况。
就会得到左手左手和右手系的问题,那么出现这个问题不用担心,然后这个就放在这儿,另外一点呢我们作业肯定不会说这个,比如说上一次作业,咱们让大家写这个嗯投影或者什么,那这次需要用到它,那只需要用到它呢。
如果这次产生这个上下颠倒的问题,就算之前用的是错的,那也不应该是这次作业的错误对吧,那所以说这个这个完全不会给大家会重复去扣除一些分数啊,或者干什么,而这次呢作业主要就集中在这个深度测试上。
大家把这个做好就没问题了好吧,然后呃当然能做对是最对了,否则到后面大家看到各种各样模型都是商业电脑的,那就那就不好看了对吧,不过也没关系哦,然后呢我注意到大家在论坛上面向大家讨论非常踊跃,这非常好。
特别呢我在这里感谢一下这个各位同学们,这个这个耐心的给其他的同学们解答,然后还出现了各路大神解答的非常非常的好,然后我这个感谢大家啊,也也是这这个就就觉得这个这个这个同学们都很厉害啊,这个这个很好。
然后又愿意来听我这个课,然后这个再次表示感谢,那咱们这个这个作业二说到这里,下一次的作业呢是关于这个咱们说的这个着色的部分,然后大家写一个不灵棚的模型,并且做这个这个呃纹理相关的东西。
做一个凹凸贴图和一个位移贴图这么两个事情,那这是什么意思呢,咱们今天会说好吧,然后呢今天我们会说一些这个很多这个这个内容,但是都挺简单的,所以咱们今天听下来,按说就没有问题,那这是今天的安排。
那上一次呢我们提到这个不林逢的这个着色模型,说起来就是说在一定的光照下,我希望算清楚一个点,它应该是这个这个是什么样的亮度对吧,有什么样的颜色,那我们之前分析从那几个茶杯的例子啊。
我们可以看出有一个漫反射,像有一个这个高光,像有一个这个环境光线,这三项我们都要把它考虑进去,那么上节课呢我们提到了漫反射想,然后这里呢有两个事情给大家这个呃再次强调一下。
第一我们说这个着色是在一个某一个这个这个shading point上,在对应这个这张图呢,大概就是这么一个点,在这张在这个点上来计算它,然后呢我们这个这个要想得到一整张图。
那我们势必要应用这个着色很多次对吧,在不同的地方应用,那这个就是待会儿要给大家说的这个着色的频率的问题啊,这是一第二呢嗯就是说我们提到的既然是各种方向。
那么其实我上一节课的这个嗯这个课件里面没有这么标哈,但其实我指的是这么个意思,比如说啊我说这个lighting的这个方向,就是这个光照的方向是从这个呃shining point指向光源呃,怎么算这个呢。
就是光源的位置减去10框的位置,然后求一个这个呃归一化,把它变成单位长度呃,然后就可以得到这么一个向量,然后所以说啊我现在提到的各种方向,法线方向n,然后之后我也就不标了啊,这里这么这么表示着好啊。
那行那咱们就可以继续了,对吧啊,然后这节课大家可以看到我们会把这个嗯布林风着色模模型说完,以及刚才说的着色的频率,然后渲染管线,如果有时间,咱们把这个这个纹理映射和这个呃重心坐标的内容说完好吧。
那么接上一册的内容啊,说我们提到了这个呃漫反射像,那漫反射像是做了一件什么事情呢对吧,首先这个光打到了某一个shading point上,那也就是说漫反射像和这个观测方向v没有任何关系。
从右边的式子也可以看出来,确实漫反射像和v没有任何关系,那么漫反射像怎么推导的呢,大家应该还记得,我们推导了一下这个光源,它在传播的过程中,会根据它传播的距离,然后产生一个能量的衰减。
那这个这一项呢i除以二平方,就表示了有多少能量实际到达了这个shing point,那么到达了还不够,还得被吸收,那我们分析了一下,关于这个冷热啊对吧,关于冬天夏天呀,关于这方面的原理,我们就知道哦。
原来接收多少能量,是和这个呃入射的方向和法线方向的夹角是有关系的,夹角余弦,夹角余弦,大家知道两个单位向量点乘90夹角余弦啊,就是这么个意思好,那么多少能量被这个到达了,这里多少能量被接收。
就是多少能量被这个反射出去,那如果说这个呃材质本身有颜色,那咱们在前面加上这么一个这个所谓漫反射系数,然后加上这么一个颜色,那当然大家可以看到这是一个很惊艳性的模型,但是它有一定的物理的道理在里面对吧。
那行那就是说这里就是这个漫反射像,然后慢慢车像长什么样呢,咱们可以看得出来对吧,是这么这个这个同样的一个球体,然后它这个比如说光源在左上角,然后它照亮了应该长这样。
然后不同的这个漫反射系数决定了它的亮度或者颜色没有问题,那咱们今天接着说啊,那么我们现在要把这个呃这个这个呃高光效给加进去,那么首先啊大家想一想这个什么是高光,或者说在什么情况下我能看得到高光。
那大家可以想一想,高光肯定是说这个这个平面啊,这个或者说这个物体它应该比较光滑对吧,那比较光滑的物体,它的反射都有一定的特性是什么呢,就是说它的反射的方向啊,呃都非常接近镜面反射的方向。
就是如果是个镜子,那当然这个物体是无限光滑的,那给入射方向给法线,那我们当然可以求出来它的出射方向就一个方向,这个二方向,那那如果说这个呃,如果这个物体它这个比较光滑,比如像光滑的金属。
那它没有像镜子那么光滑,那也就是说它的反射方向会沿着这个这个镜面反射方向二,然后有一个那么个分布,那什么时候我能看到高光呢,那自然就是说我的观察的方向和这个镜面反射方向接近的时候,我能看到高光。
那其他时候我都看不到高光,那就是说我们这是一个基本的观察啊,这就可以告诉我们好,这个呃这个高光下是由于这个观察的方向和反射和这个镜面反射方向,也就是v和二足够接近的时候,我们就得到这么一个高光效。
那这就是我们的一个一个经验性的观察,而且很有道理,但是呢我们这个不临风模型,他做了一个很聪明的一个一个一个事情是什么呢,就是说它看到了一个一个现象,就是说啊当我的观察方向和这个镜面反射方向二接近的时候。
其实就说明了这个法线方向和所谓半程向量很接近,诶,这是什么意思呢,那大家可以看就是如果我有一个这个入射方向l出射方向v,然后我可以求它的角平分线方向,大家都知道,如果说我这个有两个这个单位向量啊。
然后我想求它的角平分线方向,太简单了,把两个单位向量一加,比如说l加上v根据平行四边形法则啊,那我知道他加出来的方向一定沿着这个他们两个中间的这个方向,然后呢我再把它做一个这个归一化,把长度变成一。
这就是这个怎么求这个所谓半程向量h就是这个by sector,然后呢呃这个啊就是这个h和n接近,一定程度上,它就是反映了这个v和二接近,比如说大家可以看到这里。
这个l呢和v它产生的这个半程向量和法线挺接近的,那我们回到上一页,我们会发现哦,这个时候其实就是这个这个观察方向和镜面反射方向很接近,所以v和二接近就说明了h和n接近,它们两个之间是有一定关系的。
那么不灵风模型就是这里面这个做了这么一个聪明的假设对吧,然后这样的话呢有什么好处呢,就是说我为了衡量说我到底能不能看到高光,我只需要看这个n和h是不是接近,所谓半程向量和法线是不是足够接近就可以了。
那么咱们回到刚才的这个呃同样的漫反射的呃分析的思路哈,就是说怎么样衡量两个向量是否接近呢,很简单,还是一个点乘,如果说两个方向足够相近的话,那我们点乘的结果自然就是这个这个啊接近一,对不对。
如果说两个向量它离得方向比较远,那就是接近零,那当然是反过来方向的,咱不考虑对吧,那所以说大家从这个呃这个式子呢就可以看得出来对吧,多少能量到达了这个shading point还是一样考虑嗯。
只不过这里呢我们要考虑的事情,就是说呃我的这个半程向量方向是不是和法线方向足够接近,那所以说用了这个他们俩的点乘,然后呢同样道理,关于这个呃高光相呢,我们也会给它一定的颜色。
通常呢这里大家认为高光都是白的,所以从通常来说这个k s这个这个呃这个镜面反射系数啊,我们管它叫镜面反射系数,通常就认为是一个一个白的,一个是一个一个一个颜色好吧,然后这里呢嗯大家可能会注意到一个事情。
嗯对吧,就是有同学说啊,那你这个多少能量到达了这个点是对的,那这里怎么我们就不考虑多少能量被这个点真正吸收了呢,对吧,不管什么反射,我们肯定都得考虑这个呃,这个说的非常对没错。
就是说实际如果我们要做的对的话,我们确实还是需要在这个镜面反射向上,仍然也要考虑多少能量被吸收,然后就是有有之前那么一项这个呃l和n的电车呃,但是这里没有考虑呢。
是因为这个嗯不林风模型它是毕竟是经验性模型,它这一点把它给简化掉了,然后就是说我们主要关注的就是说我是否能看见这个高光,是否我的这些方向保证了我能够看到高光,就是n和h足够接近好,那这是第一点。
第二点呢就是说这个这个有同学问,那我为什么我要用这个这个这个半程向量和和这个法线,它俩是否是否接近,那我真的我就用这个反射镜面反射方向二和飞他们两个是否足够接近,他们两球会点成不也行吗,当然行,没问题。
然后那个模型就被称作这个phone reflectance model,然后如果说我们用这个这个n和h之间,他们两个是否接近,这个就叫不林风,the reflectance model,这个是一个改进。
那为什么说不林风模型是一个改进呢,是因为半成向量太好算,对于这个这个嗯这个向量来说,大家可以看到我给一个这个观察方向,给一个这光照方向加起来除以它的这个长度,就就就就可以得到它特别好算。
那如果要算反射方向可不好算,就是说这个给定一个入射方向,给一个这个呃法线,然后你如何得到法律的这个反射方向,你可以把它写出来,没问题,但是你可以看到它的计算量会增加很多好,那这就是第二个问题。
为什么这个布林防火模型用的是n和h的夹角好,第三个问题大家可能会接触到这样一个事情,呃不是注意到这么一个事情,大家看这里是什么对吧,大家会看到这里有一个指数的指数p在这里,这个跟之前就不太一样。
说我要衡量两个向量足够接近,是点乘确实能衡量他们足够接近,我为什么要在上面这个呃这个弄上这么一个指数呢,对吧,哎这里其实大家看这么个例子就可以看明白了。
说啊这个呃向量之间夹角余弦确实能体现两个两个方向之间,是不是足够接近,但是呢它它它这个这个容忍度太高了,就是这么个意思,大家比如说啊,大家可以看到当两个向量的夹角在45度的时候,我觉得他已经离得挺远了。
对不对,但是这个这个这个他们俩之间夹角余弦仍然告诉我们,它有一个相对较大的值,这就是说如果我们真的就用这个夹角余弦去生成这个高光的话,我们看到一个超级大的高光对,那这个就就不太合理。
我们平常认为这个高光啊都是非常非常亮对吧,集中那个很小很小的区域,这就说明什么呢,说明这两个方向只要他离开的稍微远一点,我就不算他是在高光里了对吧,当他们离得非常近,我才认为他在高光里。
所以说我们对这个夹角余弦做一个简单的操作,就是在它上面这个乘上呃,不是乘上,把它加上若干个指数,就是它的多少次方对吧,大家就可以看到随着这个指数增加,比如说增加了64次方,大家就会看到诶。
这个基本上可以了,大概说明哦在20度或者30度左右吧,呃这个基本上我就看不到高光了,如果说这两个离得非常近,在30度之内,那我能看到一点高光啊,这就很合理对吧,那通常来说这个这个系数呃就是指数啊。
用多大嘛,正常情况下在这个布林风模型里面,大家会用到100~200这么一个数字,也就是说64其实还不太够啊,正常情况下呢也可以想你看到那么小的一个高光,基本上有个3度5度。
基本上就已经这个这个看不到这个这个就是3度5度之外,基本就看不到对吧啊,所以说它是用来控制它这个高光到底有多大的,然后呢咱们可以实际看一个例子。
那么这里呢嗯大家看到一堆球,这是一个组成了一个矩阵对吧,那是什么意思呢,大家可以理解一下,就是呃这个这个其实显示的是漫反射像和这个高光像在一块啊,因为高光相实在太小了,然后就是说如果不加上漫反射像。
看到的就是基本上点啊,然后就是说嗯这里大家可以看到,如果我考虑不同的列,就是就是呃不同的行啊,从上到下看,那这就相当于是这个呃镜面反射系数,然后这个系数在增大,那这个系数就表示了它的亮度对吧。
这个并没有太大的意思,但有意思的地方在于横向来看,比如说咱们来看最后一行,这个最后一行呢大家可以看到随着这个指数p增长诶,我可以看到越来越小的高光诶,这个是非常有道理的。
我们这个指数p就是用来控制这个高光的这个大小,所以说啊那这个没有问题,这就是我们如何理解这个高光效好。
那高光像咱们这个这个这就到此为止好吧,然后呢,那咱们还剩最后一项,这一项是什么呢,就是环境光照相,如果大家还记得环境光照是什么意思啊,就是说呃我们之前说那个茶杯,茶杯有一系列的地方。
它这个根本不可能直接被这个这个这个光源照亮,但它却不是完全是暗的,为什么呢,因为有很多这个光线它可以弹射很多次,然后从四面八方打到任何一个其他的点上,所以说呢对于茶杯的背面的一些点也一样。
它能够接收到来自环境的光,那么大家可以可想而知对吧,来自环境中光,这是一个多么复杂的东西,那我们就做一个大胆的假设,我们认为啊这个任何一个点接收到这个来自环境的光永远都是相同的。
呃这个而这个强度叫做i a啊,叫做这个来自环境的这个这个这个光大概有多强,然后呢来自四面八方,然后呢我们就认为好任何一个点当然可以有自己的颜色呃,然后然后这个就是相当于环境光的一个一个这个系数好吧。
然后就是说呃把这两项结合在一块儿,我们就可以直接近似的得到一个环境光,那么这里大家从这个式子就可以看出来,或者从左边示意图也可以看出来,第一环境光不不讲究从哪个地方进来对吧。
它跟这个实际的直接光照的方向没任何关系,也就是说它跟这个l方向不应该有任何关系,那么另外一点,他不管你从哪儿看,你这得到的结果也应该是一样的,和你的观测方向也没关系。
那这样的话也就说明这个环境光和v也没有关系,那这个并且它这个和法线也没有关系,所以环境光啊其实是一个常数,那如果环境光是一个常数,大家想象一下,那基本上来说啊,其实就是某一种颜色,你看到某个物体对吧。
然后任何一个地方它都有一个常数的颜色,所以总会给你看到一个平的一个这个这个呃结果,那这就是环境光,环境光呢它的作用,就是保证没有地方完全是黑的,把所有的这些那其他的这些项都加起来,然后提升一个亮度。
就是做这么一个工作好,那当然这是一个非常非常大胆的假设,这事实上不是这么回事,然后事实上如果要计算这个很很精确的计算,它,我们需要应用到全局光照的知识之后会给大家说,然后嗯这块非常的难。
然后之后咱们再继续说,当然当然这里的这个环境光下就是一个非常大胆的简化。
那么咱们把所有的像头加起来,就可以看到诶这个环境光我刚才说了对吧,不管什么形状,不管在哪一个常数颜色,那这个这个漫反射光慢慢慢热像啊,漫反射像呃,和观测角度无关。
但是和这个呃光照和这个法线的方向角度诶有关好吧,那也就是说这里这个这个呃漫反射,想在这个这个比如说呃发现和光照方向不垂直的时候,诶它会减小啊,没问题,可以这么这这么得出一个这个例子来。
然后嗯关于这个高光下高光,像大家这这个刚才已经说了对吧,只有在很少的地方会产生高光,而高光会非常亮对吧,那么我们把这个所有的项目都给加起来,就可以得到右边这么一个结果,而右边这么一个结果。
但是看起来就觉得觉得非常这个呃有趣,有点像塑料,对不对,有一点有一种这个高光这个感觉,然后这个又有这个defuse,然后这个本身又不存在任何地方全是黑的,这是这种情况,然后把所有东西加起来。
那这里就是我们所说的不林冯这个反射模型,然后反应在式子上很简单,把这三项全部都加起来就可以了好吧,然后这里呢就是这个这个这这这三块,然后咱们把它都给加起来,这就是我们的着色模型。
那么这个下一步是什么对吧,我们刚才这个其实给大家提示了对吧,着色模型我们考虑了任何一个点,所谓shading point,而任何一个点它应该长什么样,那么下一步自然是要对所有的点。
然后做一遍这个这个着色操作。
那整个一个场景我就能够看得见,没错对,所以说嗯行,在咱们讲这个着色频率之前,我先这个停下来啊,我先看一眼这个大家这块有没有什么其他的问题啊,我有同学反映说,如果一个点它这个这个凹下去的话。
环境光是不是应该暗一些,嗯从这个嗯不林缝的模型上来看,并不是如此,那实际上应该是这样哈,就是说所以我说它是一个这个这个简化啊,啊有人问为什么不用这个逢魔性啊,道理就在这儿好,没问题。
然后有同学说磨砂表面是否没有高光啊,不能完全这么说,看磨的程度了对吧,然后这个diffuse不不考虑point view的距离,不考虑不考虑没问题,然后如不考虑物体到到观察点的距离造成的能量损失啊。
还是同一个问题哈,就是说这块要如何解释呢,这块想要弄明白得去学这个radiometry这块之后会给大家说,就是说大家就会知道说为什么我观测离它多远,其实是没有关系的。
就是说就是说这个这个这个而这个呃光光源离这个点呃离了多远,其实这个有能量的损失,但其实是这么回事,就是说我们其实一直在能量能量这么说啊,这个不合理去,这个就是说我们在这个呃这个光线传输的过程中。
我们用到更多的一个概念叫做radiance,然后这个东西和大家平常理解的概念这个并不一样,所以说呃如果说大家这个看一个东西,然后这个比如说离得远,觉得它会暗,然后这是另外一种现象。
我们之后再解释现在的这个知识不足以解释它好吗,就是但是但是没有问题,现在这么做,就是说和这个物体到观察点之间的距离是没有关系的,好吧呃先这样,这不算是什么解释了,给大家一个预告好吧。
之后我们会给大家说清楚这个这个呃一系列这些关于radiance啊,irradiance啊,这些概念怎么样去理解,怎么样去解释,怎么样精确地做出来这个光线的传播。
然后如何用它来解释这个现在大家用到的这些问题,嗯所以readings是不是辐射什么东西,不记得了,中文怎么翻译,之后到那个时候我们再说吧,好吧哎这里先先这么这个呃这么说着,那咱们先进展下一部分好。
没问题,那么呃这一部分我们要说的就是着色频率,然后着色频率是什么意思,就是就是大家看这么几个例子就可以看到了哈,大家可以看这这三个球,这三个球呢首先他们拥有完全相同的这个几何形状。
就是说它们的几何表示在空间中是一模一样的,没有任何问题,从哪儿可以看得出来呢,从这个球的边界对吧,这三个球虽然大家看上去它这个这个颜色什么东西长得各不相同,但从边界上就可以这个暴露这么一个信息啊。
这三个这个球其实他们模型用的一模一样,然后那为什么说我这个着色了之后,它的这个结果各不相同呢,那这时候就是我们所说的这个着色频率,所谓着色频率,这里给大家说一下,就是说啊这个着色我要把它应用在哪些点上。
咱不是说着色是应用在一个着色点上吗,确定point的对吧,那如果说我把这个着色应用在一个这个面上,比如说这里看到的不是三角形面,就是把四边形面那一个面,它是假如说它是个平面。
然后呢我就知道这个平面它有一个这个固定的法线,然后呢我这个求出来它的这个这个呃这个shading的结果是多少,然后我认为整个平面都长这个颜色好,那也就是说一个平面我只用做一次协定啊。
那我得到的就是这么一个结果,那自然看上去不怎么好对吧,那中间这幅图,然后这个做了一个什么操作呢,他做了这么一个事儿,就是说啊对于这个呃这个呃你每一个平面哈,然后它本身不是有四个顶点吗。
我每一个顶点我都算出一个它顶点对应的法线哦,那每个顶点有自己的法线,那我就每个顶点做一次着色,然后做一次着色之后,然后那那自然是这样,比如说这三个顶点围成一个三角形,那在三角形内部。
那那这些它他们三角形内部的这些点应该都是什么颜色呢,那没关系,我可以通过一种方法叫差值的方法算出来,所谓差值就是说啊我知道三个三个三个顶点呃,它们的颜色是什么,我问三角形内部某一个点。
它的这个颜色是什么,并且我希望它有一个平滑的过渡啊,这个叫差值之后给大家详细说,那呃回到这个问题上来,那么这里着色应用在什么上面呢,应用在每个顶点上进行一次着色,那右边这个我相信大家可以想象得出来对吧。
右边的这个着色应用在哪儿呢,它应用在每一个像素上,也就是说我对于这个呃每一个这个四边形或者三角形啊,顶点求出一个法线的,然后把这些法线的方向在三角形内部进行插值,然后就得到了任何一个这个像素。
它都有一个自己的法线方向,并且我可以做一遍这个着色,那就是说我这个着色应用在每一个像素上,那我可以得到一个非常好的结果而来,那就是这样的对吧,那这就是它的这个本质的区别。
那咱们把这些呃这些方法都做一个正规的定义好。
第一如果我说每一个三角形它是这个平面啊,然后呢我把这个这个三角形的这个法线求出来对吧,这个好求,然后怎么怎么做呢,这个三角形的两两边做一个差距,就就就可以求出这个呃三角形的这个法线,好求出一个法线。
然后呢我这个我这个根据我这个我这个呃lighting啊,view啊这个方向,然后算出一个这个设定的结果,那就是这个三角形长什么样,那自然对于三角形内部,它不可能有这个着色的变化。
也就是说得到一个完全一样的这个结果好吧,哎那也就是说可以得到呃右边这么一个结果啊,那当然结果不太好,然后但是呢他有他自己的名字叫做flat shady啊,然后我们叫叫这个名字,然后呢我们说的第二种方式。
哎这里有同学要问了,就怎么求啊,我不知道啊,给我一个这个3d的模型,我一个我这个比如说一个三角形,它的发现我会求,可是一个顶点的法线,我怎么求啊,马上就给大家说,现在咱们先假设这个顶点的法线能求哦。
那那那求出来之后每个顶点做一次着色,那每个顶点就有颜色了,那每个顶点比如三个顶点固定一个三角形,那三角形内部的颜色通过差值的方法算出来,大家可以看到结果比这个flat shading要好啊。
然后这个这个但是基本上来说,比如说像右边这个球,当这个三角形稍微大一点的是吧,这个高光什么我可能就看不见了,然后就会存在这种情况,当然这个对于这个球来说啊,这个嗯这样着色效果也并不是特别好对吧。
然后这样的着色在每一个顶点上进行一次着色,也是有名字的,叫gotiating,然后这个显然它这个不是个英文的发音啊,听起来发音有点像骨肉啊,就是这个意思啊,所以对比一下啊。
flat shading是一个三角形,grow shading是一个呃呃顶点,那自然对于每一个像素,如果说啊我我把这个三角形的三个顶点求出来,各自的排线在三角形内部。
每一个像素上我都可以插值出一个这个呃独特的法定方向,那么我对每一个像素进行一次这个着色,那么就可以得到一个相对比较好的结果,这个结果就叫做phone shing,然后这里呢呃区分一下概念。
我们之前提到一个这个呃这个着色模型,某一种着色模型叫呃不灵魂摆设模型啊,这个这是一种着色模型,然后只不过它中间出现了缝这个名字,然后呢这个这里的funciation指的是一种着色频率。
这是碰巧这两个事情是由同一个人来发明的啊,另外多说一句,这个冯这个人呐真是天才嗯,大家可以看到这个他这个至少在目前这个课上的,他就已经留下了两个事情的,第一是这个着色模型。
第二是这个呃逢时ating就是逐像素做这个着色对吧,然后但是很可惜是天妒英才啊,他这个读完博士之后呃,好像是这样,在博士期间好像就是这个和病魔作斗争,然后读完博士之后,第2年好像就去世了。
呃这个确实是一个非常惨痛的事情啊,然后这个嗯诶这个这个渲染界好像一直是挺惨的,然后去年还有一位这个欧洲的渲染的大牛,然后去世了,这个呃也是英年早逝啊,然后当然了,这个都给大家说一说吧。
这个这个之后的这个这个呃唉所以更应该把这个东西写好啊,就是这个意思行吧,那咱们提到的这三种不同的着色模型啊,flat shedding是逐三角形,grow shading,逐顶点风切ding是读这个呃。
主主主像素好。
然后就这三种,然后呢这三种其实大家要硬说它有什么样的区别呢,这个其实这也取决于具体的模型啊,然后就是说我们不能始终说这个,比如说这个呃flash shing,它就一定会很差,为什么呢。
大家看这么一个这个3x3的这么一幅图,这个图什么意思呢,就是每一行啊用的模型都是一样的,而行与行之间,比如说第一行跟第二行相比,第二行就用了更多的三角形,就这个几何形体本身更加的密集了。
就是几何形体本身定义的更加光滑,那就是说呃第二行跟第三行相比,这每一个这块几乎都几乎都小的看不见了,那在这种情况下,就是说呃大家可以看到哦,当我的这个几何足够的复杂的情况下。
哎我其实就可以用一些相对简单的这个着色模型,然后得到的结果其实还是挺好的对,然后就是就是说它有这么一种关系在里面,也就是说着色频率对吧,它取决于这个这个面或者点,或者说这个呃顶点,或者说像素。
它它们本身出现的频率,当我的这些面出现的频率已经很高的情况下,我就不再需要去用这么复杂的这个这个呃逐像素的这个呃着色,当然话反过来说就是这么一个意思,就是说啊这个我们如果看第一行,那我们知道啊。
phone shading自然会有更好的结果,但是由于每个像素都要做一次着色,那肯定要比这个flat shading这个开销要大,但其实呢如果这个呃模型变得足够复杂。
尤其是今天这样这样一个这个复杂的模型这么一个情况啊,这个这个嗯当这个模型足够复杂的时候,可并不一定说我这个竹这个面或者是猪这个顶点得到的效果,就比如像素要差,然后呢这个呃逐像素做也不见得。
就是说这个呃工作量要比这个竹这个表面呃要办,因为如果这些这个三角形面数量已经多得超过了像素数,那可不是说做flat shading,反而这个计算量要大的嘛,对不对。
所以说这个就是取决于啊具体的这个这个呃物体,当然对于这个常见的一些这些呃这个面本身不是特别特别密集的,那当然我们还是说for shing会给大家一个非常好的结果好吧。
这这里大概就是说这个关于这个呃着色频率的一个探讨好吧,那么我们留下了两个问题,对不对,留下了两个问题,什么问题呢,第一我怎么知道逐像素的法线是什么对吧,哎不逐顶点的法线是什么。
我只知道说一个三角形的法线怎么算,哎很简单,就是说呢呃有一个理想化的情况是,首先如果你知道你这个模型我是用一堆这个比如说三角形表示,但其实我是想表示什么对吧,比如说对于这个模型。
假如说我想表示的就是一个球,然后我拿一个三角形来表示,那没关系,那我知道任何一个顶点其实对应的是这个球上面的一些点,那那我自然可以通过呃他所在的这个球的这个位置算出来它的法线,那对于这些不同的顶点。
那它原本表示的是球对吧,那它的法线应该自然是从球星联想这个点这个方向诶,那这是好啊,可是你这个平常不可能有这么好的事情对吧,怎么可能知道说它这个背后视图表示的是什么呢,那么人们发明了一种办法,很简单。
怎么做呢,就是说任何一个顶点,这个肯定它都会和很多个不同的三角形有所关联对吧,就是说这很多三角形在这个例子上,大家可以看到这里有四个三角形,它们都共用这么一个顶点,那么很简单啊。
那我这个顶点的法线我就认为是它这个相邻的这些面的法线,求个平均就可以了,那这个就是大家发现了一个一个这个很不错的一个方法,而直到现在还是这个为大家所用,当然了,这里呢一个简单的平均也许说明不了什么问题。
就比如说这里有一个三角形超级小,有一个三角形超级大诶,那我们就想是不是这个超级大的三角形应该会贡献的更多,也就是说我要把这个四个法线求平均啊,可能做一个加权的平均,这个权可能就是三角形的面积。
会不会得到更好的结果呢,然后答案是是的,就是这么回事,就是说目前来说大家的算法,就是说这是一个诶很简单的一个一个一个算法,就是说这个呃就是把这个顶点所关联的呃面呃,三角形面也好,多边形面也好。
它们的法线求一个平均,不管是这个简单平面还是加权平均,那这就是我们如何去定义这个主顶点的法线好,那咱们这是一个,然后另外一个呢就是说啊这个如何去真正的定义一个逐像素的发现,也就是说在三角形的内部。
假如说我已经知道它的顶点的法线是什么了,那如何得到这个内部一个平滑过渡的一个法线呢,大家可以看这么一个例子对吧,这里这个左边这个法线我知道右边这个点它的法线也知道,那么它中间的法线应该是往这些方向去的。
但是有一点哈,这里要跟大家说清楚,记得法线所有的法线都是方向,所以应该求出来了之后,应该要给他求一个这个这个规划,把它变成这个呃单位向量啊,然后就是说保证它们长度和呃就都是相同的,这些对。
那么呃回到这个问题上来,嗯,给这个顶点的这个法线怎么样,查支书这个中间的一个这个呃发现呢,那这个就需要用到这个呃所谓的重心坐标,重心坐标马上就要给大家说好吧,然后这里啊到此为止。
这个着色频率基本上就已经说明白了好吧,然后啊咱们在讲这个呃渲染管线之前呢,我我正好也停一停,然后看一看大家这个啊回答的问呃,问的问题哈,看一下啊,哎呀呵呵呵呵,诶什么鬼,这个好吧嗯。
ok好好像暂时没有特别那个的问题哈,就是说有同学问这个这个这个这个这个呃怎么得到点所相连的三角形,哦,这个是属于这个模型在定义的情况下是怎么定义的啊,然后这个这个嗯暂时咱们先不说到了几何这里。
我们再说好吗啊,ok好啊,那咱们现在进入这个下一块吧哈那我们现在已经这个回忆一下啊,着色模型说了,然后着色模型怎么用说了,那么现在就是说我们把这些所有的东西都合在一块儿,那就已经可以说给我三维的模型。
给我这个不同的光照条件,我就已经可以得出这个这个呃渲染的结果,那把所有东西都合在一块,得到的东西就叫做图形管线,叫graphics pipeline,当然了,这个说法是以前古老的说法。
我更愿意管它叫做这个实时渲染管线,因为图形学的东西涉及的东西太多,就是说我们说了啊,关于实时渲染方面,就嗯在我们的课程里呃,都只能算上是1/4的内容,当然讲的这个课时数稍微多一些啊。
然后就是说嗯这个嗯对于其他的一些这个渲染方法,他当然不是这么做的哈,我们这里说清楚啊,好那嗯就是说我们要提到的就是图形管线或者实时渲染管线,什么意思啊,大家可以看一下。
就是说啊就是说我如何从这个场景到最后一张图,中间到底经历了一个什么样的过程,这个过程就叫做pipeline,就叫做管线,所以它其实表示的是一系列不同的操作,然后这些东西呢其实已经跟大家说明白了。
然后这个比如说咱们可以看一看它到底经过了什么过程啊,就是说呃大家看到呃从一开始输入呢是一堆这个空间中的点,然后呢并且这个呃经过了这个这个这个第一步之后啊,我们要做一个投影对吧。
我们之前讲了各种各样的这个变化啊,投影啊,我们最终首先是要把这个三维空间上的点,然后投影到这个平面上对吧,投影到屏幕上,然后呢这些点它们会形成三角形,然后形成三角形,我们知道形成三角形。
这个这个我们还要把它画在屏幕上呢,屏幕可是离散的,那怎么办呢,那咱们就通过这个光栅化把它给离散,成为不同的这个所谓fragment,这里借用的是这个open gl里面的一个概念啊。
然后就是说呃其实fragment就是类似类比于像素吧,就是在这个不做这个嗯,这个呃mi sample,anta lion,就m s a a这种呃,我们就可以认为一个fragment就是一个像素。
那咱们就说它是一个像素好吧,那么这个呃当我把这个不为三角形在屏幕上都打散成不同的像素之后,然后我就可以对它这个呃进行着色,然后每一个这个像素我都知道它应该长什么样,这应该是什么样的,最后一个颜色。
最后我就知道整个一个屏幕上应该是一个什么样的颜色了,那如果说我的这个呃这个用了这个,比如说m s a a,那就是指好多个不同的fragment,会形成一个像素的颜色,那如果大家已经做了这次作业对吧。
大家都知道对吧,然后我维护每一个这个fragment,它对应或者说sample啊,对应的它的这个这个深度,然后颜色,然后我最后再把它拼成一个图,我就不会拼出三角形的黑边啊,就是这么个问题好。
那么这一个呃整个一个过程呢,这就是我们处理这个呃,这个嗯从三维场景到最后渲染出二维的一幅图的一个基本操作,而这个操作是已经在硬件里面写好了的,现在的是整个一个这个显卡。
他所做的操作就是基本上是这么一个操作,整个在gpu里进行,然后呢这里有一点啊还没有给大家说啊,这里呢就是就是这个大家可以看到说我们一开始啊,就在说这个三维空间中这个不同的三角形。
然后把它投影到这个屏幕上去,那这里我是这个为什么说我把三维空间中的点投影到屏幕上去,然后再把它连成三角形呢,是这么一个意思啊,其实它没有什么特殊的意义,就是说我们如何定义空间中的一个模型啊。
咱们可以想象一下,我们可以定义它所有的三角形顶点,然后再定义每三个顶点会形成一个三角形对吧,我们把这两部定义给分开,其实一样的,跟我定义所有的三角形是一样的,我先定义所有的顶点。
在定义哪三个顶点会形成一个三角形,定义一系列的这些东西,那然后就是说我只用把三维空间中的这些呃点投影到屏幕上去,变成二维的,变成二维的,然后呢它它们之间的连接关系自然不会变,还是仍然是原来的这三个点呃。
现在投影了之后的三个点形成一个三角形,那所以说呢我只需要对顶点进行操作就可以了,所以说大家可以看到啊,这里面这个呃我们所说的这这三个大的步骤,第一是这个顶点的处理,也就是说这个嗯投影变换啊这一块的东西。
然后第二个步骤就是这里啊这个光栅化涉及到怎么样去采样,然后怎么样去做深度测试,然后把这个呃实际上在屏幕中能显示出来的像素给找到,然后第三块就是我们说的着色,那把这三块都合在一块儿之后呢。
自然最后就可以得到准确的结果,没问题,那咱们看几个例子哈,这个我们之前说这个做model view projection mvp变换,那个变换在哪呢,那就是每一个顶点我做一个变换对吧,没有问题。
那这个我这个涉及到这个对这个屏幕上面这个每一个像素中间采样,然后看是不是在三角形内,这一步是在干什么呢,这不就是在这个光栅化对吧,然后呢这个这个当我光栅化产生了一系列的这些fragment。
或者像素的时候,我要判定啊它是不是这个呃,可见那就是说呃是在这一步发生,当然严格意义上来说也可以把它归为光栅化的一部分吧,就是这里分的比较细啊,就是说z buffer就是我们所说的深度缓存。
就在做这个事情,然后呢我们说shading谁定呢,这里大家会会看到这么一个事情诶,这里是ding是发生在这个顶点和这个像素,这个这个这个都会发生,这是为什么呢。
呃这里呢其实就是说呃考虑到不同的这个着色频率,如果说我们考虑这个着色是这个groo shading,也就是每一个顶点我进行一次着色诶,那我自然就是发生在这个着色,就可以发生在这个顶点的处理上。
顶点可以做这个呃投影也可以做着色,没有任何问题,然后呢如果说我做的风水岭,那自然是得等这个像素都产生了,所以我们在fragment里面做,所以大家可以看到啊,就是说这这里重要的是什么呢,如果想做着色。
重要的就是这个顶点如何着色,或者是像素如何着色,然后在现代现代的gpu里面,然后就是就是这一套渲染管线,它是允许有些部分是可编程的,所谓可编程的就是你说了算,就是你说这个顶点如何去被着色。
然后这个像素如何去被着色,然后就是说你可以定义这个事情,然后定义了之后呢,自然就是说你写一段代码,然后让它能够生成各种各样的这个不同的这个着色的结果,那么这里说的容易就是说整个这个这个实时渲软件啊。
几乎就是在做这么一个事情,就是所谓写这个这个这这部分要如何运行,那什么样的代码来决定这些顶点和这个像素要如何这个呃运作对吧,这个处理如何运作呢,这部分代码我们就管它叫shader,这部分shader呢。
就是说这个是控制说这个顶点和这个呃像素是如何进行着色的,那就是这么个意思行,那咱们这个多说一句,马上就会给大家说这个硬件上的事情好吧,然后嗯这里呢我们有一块呃还没有说,这就是下一个话题。
我们很快就要给大家说呃这么一个事儿啊,什么事情呢,大家看右边这个三角形哈,这个三角形这个显然是说这个我没做任何的什么差值什么东西对吧,我这个这个呃我其实三角形内部它每一个点。
它的应应该是对应的一个这个这个木头纹理的上面的某一个点,对不对,是这么个意思,就是说在三角形内部能够看到一些这样的变化,这是怎么回事对吧,就是说我如何定义这个每一个这个像素,或者说三角形内部不同的点。
它都拥有了一个完全不同的属性,怎么样才能这个让三角形显示出这么一个这个呃,上面有一张图的三角形诶,这个就叫做纹理映射,好,咱们马上就要说好,在这之前我们把这个shader把这个概念完善一下。
刚才我们已经说了,现代的gpu允许大家自己去编程,来解决这个顶点和这个呃和这个呃像素如何去这个呃操作,就是如何做他们的着色,那么正常情况下呢,这个时候需要大家去写这个shader。
如果大家要实现一些复杂的东西,那么这个shader呢它本质上是一些这个呃能在硬件上执行的语言,咱们这里举一个例子,这个open gl这一块呢对吧,open gl是一个这个呃图形学的api。
然后呢你可以用它来写一些这个shader,那么shader首先我们说一下是这个意思,shader是每一个顶点或者是每一个这个呃fragment,或者说像素它的这个呃它会执行一次。
然后就是说你写的这个shader其实是一个通用的,你不用指定说每一个这个fragment,我每一个像素我怎么样去执行,我写一个通用的程序,那么每一个像素都会这么执行,是这个意思好吧。
然后这里先确定就是不需要大家写for循环,在这个shader里面,你就只需要管一个顶点或者一个像素怎么样运作就可以了,好那是第一个事情,第二个事情是这么回事,就是说如果我写的是顶点的操作。
然后这个shader就叫做vertex shader,叫顶点着色器,然后如果说我写的是像素的操作,那这个shader这个叫做fragment或者pixel color。
然后a pipixel shader叫做像素着色器,或者说这个fragment啊,这个其实大家翻译叫片段或者片段着色器或者像素着色器,其实一回事啊,然后就是说呃那就是说这是他们的名字。
然后呢咱们现在看一个具体的例子,那么对于这个呃像素着色器,然后他要干什么呢,他要告诉说这个像素最后的颜色是什么,那也就是说对于一个像素来说,我要写清楚怎么样算它最后的颜色,并且把它输出出去。
那么这里做的事情就是这么一个一个着色的过程,那么呃这里是一个简单的一个这个呃open gl的一个着色语言,让简称gl sl,它的一个这个呃像素着色器的一个小程序,这个着色器说的是什么意思呢,说的是啊。
我这个呃有两个全局变量,全局变量啊,跟c加加里面一个道理,这个uniform指的就是全局变量,而这个全局变量是一个纹理,纹理是什么意思嘛,你再说啊,全局变量里面有一个这个光照方向。
也就是我认为每一个这个像素它都有一个固定的这个光照方向啊,它不会变,然后呢,那么对于不同的像素,在不同在这个三角形内,它可能有一些差值的值对吧,比如说这个我们刚才说这个呃顶点的法线。
咱们这里忽略这个uv啊,然后我们这个看顶点的法线,这个顶点的法线是插值出来的,也就是说对于这个呃这个顶点它可能有三个顶点,有不同的这个呃发现,那么我不用管它,到了这个这个像素里面。
我自然而然这个这个整个一套open gl就替我做好了,我就知道他是这个差值出来,每一个像素它的法线是什么,叫nm这里,然后那么这里呢我们可以看它这个做了件什么事儿,我说了啊。
就是说我们指定的是每个像素都这么执行,所以不需要一个for循环,那每一个像素我可以拿到它一个这个kd就是它的漫反射系数怎么做的,这跟文理相关,咱们忽略它,那就是说呢我这个这个呃慢慢的系数。
如果乘以说这个假如说光照是一个常数啊,这是一个超级简化的版本,我只要乘以它的那个呃l和n的夹角对吧,呃夹角余弦怎么做到这个l的方向,然后和这个法线方向求一个点称它。
这里显然是认为这个方向这个入射方向是向内的哈,在跟我们的规矩是不一样的,我们规矩是这个入射方向本来就是朝外,所以没有这个负号,然后做一个max的零呃,零这么一个处理,当然它结果肯定小于一,没有问题。
就是说这里其实就是最最简单的逢魔型的漫反射的部分,写完了之后,把它给返回到一个这个值,这个值是一个固定的值,叫做gl flag color,就表示说我这个像素或者片段它的颜色是什么。
所以说从这个代码上来看啊,这个核磁加加非常非常非常非常相似对吧,它有全局变量,它有这个差值数的变量,然后中间怎么样计算,还有各种各样提供的方便用函数,比如这个点乘对吧,点成两向量,点乘dt什么什么。
然后这个如果要把它这个值限制在0~1啊,用一个clamp 01,然后中间的值这个就保证了它这个值一定就在零和一里面,然后最后返回这些值,然后呢我们写这个egg对吧,我们在c加里面用egg这个库。
我们写这个向量怎么写啊,bor 3 f对吧,表示一个float型的这个三个数的向量,那这里很简单,vex 3就解决,然后vex 4呃,可以这个比如说前面呃给他输入一个vex 3,后面再跟一个数。
那自然就变成vex长度是四个vector向量对吧,那所以说这个嗯g l s l呢其实很好写的,然后对于这个shader来说,你就可以指定好每一个这个像素如何去着色啊。
这就是说这个这个整个一个这个啊所谓着色器也就是shader啊,他到底在干什么,那咱们把这个事说清楚就可以了,他就是要能够能够定义呃任意的顶点怎么样操作,任意的这个呃像呃呃这个这个像素或者片段如何去操作。
那就是这一点理解到了就没问题,那咱们现在回到第一节课我给大家说的这个事情啊,就是说呃咱们讲到这个为止,其实就把这个整个呃图形管线的部分全部都涵盖到了,如果在这个大家把这个作业做下来,就会发现啊。
这个整个一套这个光栅化,整个一套这个成像这个实时渲染,它的基本思路,我就已经都给这个涵盖到了,那也就是说如果在这个基础上,这一系列图形的api,他们是如何运作的,然后他就会会发现非常简单。
我只需要指定这个场景中的东西,他们怎么样去这个运动,怎么样旋转,怎么样摆放,然后相机怎么样摆放,所谓的这些这些这个呃举证啊,都不用自己来做的,他这个都有这个很好的一些这个api帮你生成他们的举证。
然后如果你想写着色的话,很简单,你就在这个这个顶点,或者说在这个呃像素里面,然后实现这样的着色器,然后他们的语法也都很容易,然后可以可以这个很方便地写出来,那么呃到此为止。
大家就可以通过所学的知识去这个真正的写一些。
实时渲染的这个代码了,然后这里呢我给大家推荐一下这个呃一个网站叫做shader toy,然后这个这个网站是干什么的呢,这个网站就是说你可以自己这个免去你写这些什么open gl啊。
什么direct x啊,这一系列背后的东西,你只用关注这个场景怎么样去渲染,你就是说你只用写所谓的着色器,所谓这个这个呃顶点和这个呃像素他们如何着色就可以了。
那也就是说它是一个这个这个在这个网络上直接可以执行的,一个一个呃在这个网页上直接可以执行的这个程序,然后你把它这个写出来之后,你就可以看到这个结果是什么。
那么shader呢我刚才说这个我每次提到这个事情啊,我觉得这个shader真是千变万化,大家这个可以可以这个这个做的非常非常惊人。
比如说给大家看这个蜗牛的这么一个例子是什么呢,这个呃我们放起来啊,ok这个蜗牛呢它是由各种各样不同的几何形体来定义的。
我们管它叫这个隐式的几何形体,然后这个之后讲几何会说他并没有用任何的三角形啊,然后就是说它的所有的几何形体都是通过数学方法定义的,并且呢呃大家还可以通过shader来不断的来调整这个几何形体。
它就应该长什么样,就是说如何去这个得到这些几何形体的投影,这里和我们三角形的投影不一样啊,这一然后呢当然可以做cad,大家可以看到这个呃,这个壳壳的材质看上去就很像这个这个这些固体对吧。
然后蜗牛本身看起来就像是透明的,这个半透明的这么一种感觉对吧,然后就是说这是非常非常非常厉害的,就是说通过shader可以实现超级多超级多的这个好东西,然后这个呃链接什么的都有。
然后呢大家之后就是说学完这门课啊,或者说到此为止啊,没有什么压力,然后呢然后自己没事去写一写这个shader toy,这上面的这些shader,这是非常非常有趣的事情好吧。
然后呢这个呃这个例子当然了是超级高端的一个例子,然后大家都会觉得这个叹为观止,这个确实是厉害,当然了,这这里就是说这个动画整个的这个形成过程啊,真正如果大家访问这个网站,它会发现这个过年还会动啊。
它这个shader里面还做了动画,这是确实是大神啊,这个大家好好练就没有问题,好,那么这个呃这就是这个例子,那咱们现在说一说啊,这个这个现代图形学的发展很简单。
就是说随着这个gpu这个所谓这个graphics processing unit对吧,然后这个这个gpu的发展,然后我们现在的显卡可以同时在很短的时间内处理大量的几何,然后把它给放在屏幕上。
并且它的着色非常非常的快,高度并行,然后就是说你这个在你这个着色这个像素的时候,有很多其他的像素都在同步的进行着色,那大可以可想而知有多么快,对不对。
然后就是说这个现在的这个这个图形学发展就是往这么一个目标上去,我有一个超级复杂的场景,像这个场景,这个场景呢就是实时渲染的一个场景,是这个unreal,大家听说过吗,叫叫虚幻引擎啊。
这个虚幻引擎非常厉害,然后他们这个就相当于这个引擎啊,比如说我想做一个游戏,但我不需要了解特别多图形学的知识,不需要理解特别多这个人工智能知识,这各方面都已经写好了一些,这个你直接可以拿来用的这些方面。
那当然了,作为游戏引擎,它肯定要把这些方面给做好,特别是图形,那所以说就是他们做了这么一个事情,就是说他他们可以允许这个呃,这个有一些这个经典的算法就已经实现好了,怎么样去做阴影,怎么样去这个呃对吧。
怎么样做这个近似的实施是呃这个这个呃叫什么来着,全局光照也就这些事情,然后把它给放到这个呃一个实时的这个这个画面里面来,然后大家就可以关注游戏的开发,而不用特别关注这个图形图形呃,背后是怎么实现的啊。
那这是好事情,但是对于我们来说,我们希望了解这个事情对吧,然后就是说现在的图形,这些引擎都是可以支持这个呃非常多非常复杂的这个场景,然后也可以做得非常快,然后呃所以当然是一个很好的,对不对。
然后这个我也很期待,看到说之后这个这个游戏引擎应该往什么样的方向发展,能不能做得更好更逼真,对吧好,那这是一个事儿,然后另外一个呢我们刚才提到g p u对吧。
然后g p u自然就是说这个整个一套这个图形管线的这个呃,硬件实现对吧,我们这么理解它就是说嗯它在硬件的层面上就实现了,说比如说三角形怎么样去做这个呃,各种各样不同的这个这个这个这个光栅化。
然后怎么样去实现投影各种各样的东西对,然后呢有一部分是可编程的,就是我们所说的着色器对吧,我们提到了两个顶点着色器和这个呃片段或像素着色器,但其实随着这个gpu的发展。
随着说这个这个呃现在技术越来越进步,有越来越多不同类型的着色器产生,比如说这里给大家举个例子,有一个着色器叫做geometry shader,它算算是几何的着色器,它可以干什么,说是叫着色器啊。
其实相当于是呃某一种操作,你可以定义几何的操作,可以动态产生更多的三角形啊,这有什么好处之后我们会说啊,然后还有一种shader叫做compute shader。
computer shader就更厉害了,这个这个就是说它可以做任何形式的计算,你不用把它给这个呃理解到他只能做这个图形学内部的一些计算,用compute shader它就可以完成各式各样的。
我们管它叫通用的gpu计算,所谓general purpose,gpu叫gp gpu,就是这么个意思好,然后就是说现在这个shader呢是非常非常厉害的,然后大家学这个这个呃新的一些东西呃。
这个比如说direct x 12呃,大会学到很多很多各种各样新的技术,然后这些呢就是说在我们这个传统的这个基础上又有所这个加强,所以说这个是非常值得期待的一个发展啊,那么gpu提到这里啊。
啊说起来说两句啊,第一这个gpu呃分两种,一个叫做集成的显卡,这些大家打游戏都知道哈,这简单给大家提一下,第二呢就是说gpu本身,它这个大家就可以理解成是一个高度并行化的处理器,咱们经常说cpu对吧。
哪个什么i7 i9 ,48核不得了了对吧嗯,然后a amd推出了64核,然后就是说啊这些这个所谓核心的数量,咱们就可以理解成所谓可以并行的线程的数量,那么这个大家如果学过这个高性能计算的话。
还是知道gpu的这个这个呃并行度,也就是说同时进行并行的这个数字是相当相当惊人的,这个数字要远远超过这个cpu的几十,虽然每一个它的这个性能并不是特别的强,但是胜在它这个这个并行度很高。
所以特别适合做这个途径学的这个这个这个项目,就是说我很多这个这个呃像素它的着色方法都是一样的,对不对,然后就是说我们通过这种方法,然后然后就是说我定义一个,然后很多的这些呃像素他们执行的代码基本相同。
这就非常非常利于做这个并行计算,那这就是gpu的另外一个这个特点,那这给大家说明白好吧,然后呃那这里就是这啊,那咱们把这个gpu说好,ok那么咱们图形管线到这告一段落。
那么下一步就要说呃纹理映射的事情了,那么在这儿我先暂停一下啊,看一看大家有没有什么其他的问题哦,这个好诶,ok,好吧,好像这个这块倒是挺容易明白的对吧。
这个基本上来说就是对咱们之前所讲过的这些内容的一个总结,这个这个整个一套图形渲染是一套什么样的一个一个思路,然后每一块都是如何解决,那么咱们现在回过来解决这么一个遗留问题对吧,我希望得到一个三角形。
三角形内部是填充了某一张图的一个一个一个这个这个现象,诶,这个是是是什么意思,我们怎么做对吧,然后这里就要提到纹理映射这么一个概念。
那所谓纹理映射其实我们在做一个什么事情啊,这里这个通过这张图,咱们希望把这个事情给说清楚,那大家可以看到这幅图其实非常简单,两个台灯在照亮一个地板和一个球对吧,然后如果咱们只盯着这个球来看的话。
那其实他的这个着色我们会写对吧,如果我们认为台灯的灯灯光这个光源啊是一个点光源,那这样的话,那无非就是两个点光源,它的贡献都加起来了,如果我们用这个呃这个布林缝这个着色模型,那么大家可以看到。
如果我们只盯着这个漫反射来看啊,那漫反射系数,然后乘以它这个光要考虑一个这个嗯这个光源,然后他的衰减,然后他的接受啊,那没问题,这个是是可以这么做的。
然后但是呢这个球上面诶我可以看到它有不同的这个不同位置,有不同的颜色,大家可以看到诶这里有个五角星,然后这里是黄颜色,这里是蓝颜色,诶他们的基本区别是什么呢,他们基本区别是哦。
他们其实共用同一个着色模型,只是说他们本身的漫反射系数发生了一些改变,也就是说我们希望有一种方法能够定义对于一个物体,它上面的任何一个点,它们的属性,那呃怎么理解呢,对于这个咱们看另外一个例子。
对于这个地板来说也是如此对吧,地板来说,假如说它是漫反射的,那有灯光照亮它,然后它在任何一个地方啊,它其实有自己的漫反射系数,然后它这个慢慢技术反应在它这个呃木头的这个这个纹路对吧。
它也可以看得出来对吧,也就是说啊我们希望定义这个在物体不同位置定义一个不同的属性,那这里其实就是说我们呃引入这个纹理映射的一个最基本的思路,倒不是说我们完全需要用它来定义这个漫法式系数啊。
它可以定义任何任何各种各样不同的东西,就是说它的根本作用是定义任何一个点的不同属性。
那咱们现在继续进展,那么怎么定义一个这个任何一个点它的基本属性对吧,那咱们需要先理解说我们定义在哪,首先第一我们把这个属性定义在物体表面上,当然了。
我们要考虑这个任何物体表面任何一个点应该是什么样的颜色,我们要做着色对吧,那物体表面怎么样去理解,那这里呢首先我做一个这个呃,怎么说呢,声明对吧,任何一个三维物体,它的表面其实都是二维的。
哎这个事情怎么理解呢,这个其实其实很好理解,大家看这个这个地球仪对吧,任何一个地球仪呢显然是个三维物体,三维的球,它的表面,但是呢我们可以把这个必修一的这个这个这个它它上面这个呃,他的这个这个这个图啊。
呃给撕下来,比如说中间给割一道口子,然后把这个整个一张图给拿出来,拿出来之后呢,然后往平面上一放,诶那可不是变成一个平面了,对那这也就是说一个事情啊,就是说哦这个三维物体的表面。
其实呃虽说整个物体是三维的不错,可是对于表面来说,它们其实是二维的,那有同学要抬杠,说明我多个物体,那多个物体,那我可以把它的表面展开成多个平面,再把它放在一块呢,还是一个平面,对不对,就是这个意思。
所以说这个这个嗯就是说啊物体的表面其实通过这种方式呢,我可以和一张图有一个一一对应关系,那么这里我们就定义一个所谓纹理,纹理是什么,纹理就是一张图,这张图我可以任意的把它给比如撕开,用其中一块。
或者说把它给这个这个拉伸啊,压缩呀,或者怎么样,就是认为认为它是一个这个有弹性的这么一张图,我就把它蒙在任何一个三维物体的表面,这个过程就叫做这个这个纹理映射,那映射啊自然是一个一一对应的关系。
那我们就找到了一个这个物体表面,任何一个点和和这个纹理上面任何一个点,它们之间的关系,对不对,那就是这么一个思路,那咱们看一个具体的例子啊,咱们看这个左上角这个独眼巨人啊,这个渲染出来的结果。
这就是我们布林冯能够得到的一个结果,没问题,然后但是呢我想让它上面有一个图出现,那怎么办呢,根据我们刚才的思路,就是说啊,我们要把一张图给贴在这个这个表面上面去,那我们自然要知道怎么填对吧。
那我们想啊三维空间中最基本的东西是什么呢,肯定是一个三角形,那么如果我知道一个三角形,它在这个物体上,比如说这里有一个三角形对吧,在物体上它应该如何映射到一个纹理上,也就是说它在纹理空间上是哪儿就行了。
也就是说呃这个在物体上大家可以看,比如这个三角形哦,这个三角形啊,它在纹理上它对应的是呃在这里,也就是说啊我的任意一个三角形的一个顶点啊,它都都都能找到他在这个呃这个纹理上,它在哪个点上。
大家就有同学会问了,那这个事情我怎么知道嘛,哎这个事情呢就是说这个嗯有两个解决办法,第一就是说呃需要艺术家的这个这个创造,就是说现在这个很多模型都是这么做的啊,他做出一个模型。
然后大家把这个模型通过一种展开的方式,然后把它贴在这个呃放在这个纹理的不同位置吧,这个对应上这些是由这个艺术家们来完成的,或者说美工们完成的,就是说任何一个三角形它会被映射到哪儿,我们就认为已经知道了。
可是对于美工来说是一开发是一个非常繁重的过程,第二呢是一个自动化的过程,这个自动化的过程怎么做呃,就是说啊给你任何一个模型,然后我有一个我可以把它给展开成一个平面,然后展开成一个平面。
并且我还希望啊各个就是说这个产生的三角形尽可能的少扭曲,就比如说我原本三角形挺小,那我希望它这个展开到平面上啊,它还是挺小,然后这个这个这个三角形原本挺大的,还是应该挺大啊,那如果能保证这种性质。
那就更好了,那么如果还能保证说比如说我这个整个一个物体啊,它是一个完整的一个物体,它是个处都是无缝衔接的,那我如果说把它映射到这个纹理上面,它还能保证说他这个纹理上面,它对应的颜色也是无缝衔接的啊。
那就非常好的,那这个很难,这个是一个重大的研究的方向,叫做parameterization或者叫参数化,这块在几何上是一个非常非常这个厉害的研究,好吧,那咱们把这两个事儿说明白。
就是说啊怎么把这个空间中一个三角形映射到一个纹理上,我们不管,我们就认为已经有了这么一个映射关系,我们知道这个纹理要如何贴到这个三角,在三不同三角形上,是因为我们在三角形上的任何一个顶点。
我们都已经规定了它在纹理上的一个坐标,好吧,那么我们既然提到纹理上的一个坐标,那也就是说我在文理应该把它哦说起来哈,呃呃这样吧,这个稍微拖延一点点时间,这个应该很快啊,很快,那是这样哈。
就是说呃我们刚才既然提到纹理上面的一个坐标,那我们就应该在纹理上定义一个坐标系,然后真正能指定说文理上面任何一个点的坐标,那么文理上是有坐标系的,比如说这里啊,大家看得清楚,文理呢是右边这么一幅图。
这幅图其实相当于是给大家这个就是显示了一下啊,比如说这个红颜色这里就表示这个呃这个在u方向很大,然后这个绿颜色表示在v方向很大,那么整个这张图它就形成了一个颜色。
然后不同颜色就表示不同的这个uv就是纹理上的坐标,那么我可以把这个任何一个这个这个物体,它的一个三角形如何映射到这个呃这个呃纹理上,然后可以把它显示出来啊,那就可以看到哦,左边是这么一个模型。
右边是它的展开映射到这个纹理上的一个一个做法诶,所以是这么做的,那么定义一个uv,然后呢这里多说一个uv的范围,通常大家认为对于一张纹理来说,不管你这个纹理是不是方块啊,就是说即使它是矩形的。
长方形的也没关系,他都认为纹理的这个范围是u在01之内,也在01之内方便处理,那有同学问为什么这个也是一个约定俗成的一个事情啊,这算是相对简单的一个处理方法,不管它的分辨率是多少。
不管它的这个长宽比是多少,我都认为u沿一个方向01,另外一个方向01没问题好,那这里就是说这个呃嘿嘿呃uv好吧,然后纹理上有坐标的没问题,然后你看这个对于实际的纹理来说对吧,也是同样可以定义。
那么我们就知道啊,三角形三个顶点啊,每一个顶点都对应一个uv对吧,这就是纹理映射呃,还是一样哈,怎么知道的,我们就认为已经知道啊,然后呢纹理就是说可以应用在不同各种各样不同的物体表面。
而且啊这个大家可以看到,比如说对于这个例子来说,这是早期的一个渲染图啊,挺难看的,但是如果我们把它的这个任何一个点,它的纹理坐标可以显示出来,大家会看到是这样的,就是说大家可以看到哦。
这个呃有一块纹理在在在这里啊,这0~10到一啊,假如是这样的,然后我不断地重复它,不断的重复它,就好像贴瓷砖业啊,我把这个这个给给贴上对吧,这这里对应一块这个地板,这个石头的这个这个地板或者是墙面诶。
我把它贴上,然后不断地重复它,诶我就可以把整个一个物体给贴满,哎所以说啊这就告诉我们,谁也没说纹理映射,我说我纹理只能被用一次,我不同的位置我当然可以映射到相同的纹理的这个这个位置上。
也就是说呃比如说大家看这个位置跟这个位置,它映射到了纹理,其实同一个地方没有任何问题,也就是对应了纹理,我重复多次就是了对吧,那么这里其实有同学可以看到另外一个事情哈。
就是说诶我这个纹理我左右这么一重复,我很明显能看到诶这里有条缝,这上面有道缝,实际上对于我这个场景来说,回到这个场景上来说,我发现没有缝。
这个就说明很很有意思,这说明什么呢,这说明我们这个纹理本身设计的好,使得这个纹理它往上往下各复制自己重复的时候啊,这个这个会无缝衔接,也就是说这个纹理的右边自然而然会接上这个纹理自己的左边哎。
这上下也是这样,那这这就非常好了对吧,那那这个自然而然就有同学说,那我如何去设计这样的纹理,这是不是很难是很难对,然后这里呢就是说我们所设计的就是呃这个纹理。
在这个呃图形学里面就叫做table texture,tie,tie是一块啊,tiable就是table,然后然后这种纹理这种纹理的设计是需要各种各样不同算法的,其中有一种算法叫one tiling。
然后就是就是这个王这个这个姓氏的名字,然后这个one tile,然后现在是借这个,这是大家在使用的其中一种哈,就关于这个纹理的这种无缝衔接的合成,这是非常非常这个呃值得研究的一个事情啊。
那这里就给大家这个这个简单说一下,是有这么回事儿,然后呃呃关于纹理呢,那咱们就说到这儿下一个问题,下一个问题很自然而然的事情,对不对,如果说我知道三角形三个顶点对应的纹理坐标u和v诶。
那我如何知道三角形内部任何一个点,它对应的这个呃纹理坐标uv对吧,那也就是说这里又涉及涉及到这个差值问题了,那咱们今天这个讲的算是快的啊,这个前面文理已经提到了。
那么咱们从下一节课开始给大家着重说这个差值,所谓差值什么意思,这个这个通用性的来说,就是说三个三个呃三角形的三个顶点有各自不同的属性,那么我如何在把这个属性在三角形内部做一个平滑的过渡给我。
任何一个三角形内部的点,我都可以立刻知道啊,它应该是这个差值之后,它这个点上对应的属性是多少,那这就是我们要解决的问题,这里我们用的东西叫重心坐标,下节课再给大家说,那这节课就简单稍微拖点。
他就是说说到这儿就够了,那么呃我这个时候再看一下啊,有同学问问题,你好,没问题,你看啊,哇哇哇这个嗯纹理和着色的区别和关系啊,纹理是用来定义这个这个嗯着色的时候,需要的这个这个嗯各个不同点的属性啊。
就是这个意思就是说我不希望它着色的时候,每个顶点都以一种相同的方式来着色每一个点啊,然后我就用纹理的方式来改变一些主点的属性,就是这么一个意思,就是说嗯ok没问题,那看一下哈,其他应该没什么。
基本上来说应该说差不多有同学问作业跑出来的帧率很低,正常吗,正常没问题啊,因为我们用cpu模拟gpu的这个过程没问题好,然后行,那既然是这样的话,那我觉得啊ok那那如果没有其他什么问题的话。
那我觉得差不多啊,呃着色和材质有什么区别啊,基本没什么区别,不同的材质就是不同的着色方法,可以这么理解好吧,然后那行,那咱们今天这个就说到这儿好吧,然后这个呃下节课,然后我们给大家说这个怎么样做差值。
并且把这个呃着色这部分说完,就整个shading部分,然后咱们再看看有没有时间说一些稍微复杂一点的话题,那么今天大家可以看到啊东西多一点,但是相对简单啊,总结起来这个这个啊。
估计回去看一眼这个这个对应的这个课程课件就差不多了,好吧好吧,ok那我这就下了啊,这个把时间交还给我们的技术秘书同学。
然后同学们咱们下次再见。
GAMES101-现代计算机图形学入门-闫令琪 - P9:Lecture 09 Shading 3 (Texture Mapping Cont.) - GAMES-Webinar - BV1X7411F744
感谢大家一如既往的支持,咱们今天开始说这个啊,现代计算机图形学入门的第九讲,然后我们今天会把这个着色部分这个说完,说起来这部分啊其实和这个着色本身已经没有太大关系了,着色的基本原理咱们已经说清楚了。
那这一段节课咱们主要说的就是这个关于纹理的一些这个应用好吧,呃那么在课程之前还是一样,咱们这个有一些事情说一说,这次呢主要就是关于这个作业,然后呢呃有同学反映这个作业已经收到批改的结果了。
有同学说还没有没错,现在我们正在这个这个批改中啊,然后这个请大家稍微耐心一点,然后然后啊这个呃作业二目前这个收到了271份,其实一个小时之前了,估计大家这个应该跟我一样,赶deadline。
赶的都比较厉害对吧,然后我怀疑现在应该已经300了,然后这个这个这个这个不错啊,然后嗯嗯这个希望之后大家都是这么一个这个这个提交数量吧,这应该非常好啊,然后我们的这个作业三很快就要放出来。
然后关于这个这个呃着色这一块的内容,好吧啊,那这一次主要就是说一下这个跟作业相关的问题,那咱们继续啊好嗯,经过前面两节课,咱们已经说清楚了,这个关于嗯着色的主要内容,主要呢咱们从着色模型开始说。
特别的我们我们提到了一个这个布林缝着色模型对吧,我们还这个手推了一下,这个漫反射高光和这个环境光下对吧,然后把都合在一块,我们就可以得到一个这个看起来很像塑料的一种材质,然后我们的结论是什么呢。
就是说这个我们如何去定义不同的这个材质或者表面,与这个光线如何作用,呃,我们就可以得到怎样的一个这个这个这个看上去的一种外观对吧,所以说最重要就是研究清楚这个光线与材质如何作用。
这个呢我们在之后讲完这个光线追踪部分之后,还会给大家这个更详细的说好,然后呢我们提到说这个着色可以应用在不同的这个地方对吧,如果我们应用在这个表面上,这就是这个flat shading。
然后如果应用在这个呃顶点上,这叫gotiating,然后这个应用在像素上嗯,这个就叫做呃风险点,然后我们都提到说这个中间涉涉及到大量的差值对吧,如果我们要用grow shading。
我们可以算出在三个顶点它的这个着色的结果,并且在三角形内我们需要进行一个差值,然后如果做缝制定呢,我们需要这个呃三角形三个顶点上,他们的这个三个法线方向。
然后呢我们先把它对这个三角形内部的任何一个像素做一个差值,然后求出对应的像素它的法线,然后我们再做一次设定,是这么这么做对吧,但不管怎么样,我们会用到很多的这个这个差值的这些方法。
所以今天我们主要就是说这个事情好吧,然后呢我们提到了说在硬件中是如何实现的对吧,这个这个图形整个的一套光栅化的一个走为图形管线,或者说实时渲染管线就是最重要的事情,我们提到两点。
第一这个顶点呃的变换或者处理,然后另外一个是这个呃像素的,或者说这个片段的这个呃处理啊,然后这两个呢分别现在是都是可以编程的,然后我们如果要对顶点的操作进行编程。
那么我们写的东西就是叫做这个vertex shader,顶点这个呃着色器,然后呃相应的如果我们写的是像素,那这个就叫做呃像素着色器对吧,然后这个呢我们今天也会体现在这个体验到它的一个应用好吧。
然后我们提到了一个最简单的这个纹理映射的知识,其实呢就是把三维空间中实际上是二维的物体表面,然后贴上一张图,所以纹理其实就是图,然后我们这个提前会得到这个呃物体上各个不同的这个表面上。
各个不同的位置如何去映射到这个纹理的不同的地方对吧,那咱们就说了这么些内容,然后呢这个呃咱们今天就是沿着这个思想,咱们把这个呃着色部分讲完,如果咱们有时间,咱们会讲这个这个关于这个阴影的事情。
怎么样生生成阴影,然后我觉得今天应该没时间啊,那咱们就这个安心把这个着色部分说完,那咱们就要说这个三个部分,第一是这个嗯重心坐标,然后我们用重心坐标是为了做差值。
然后呢这个我们提到说这个纹理是可以贴在物体表面的对吧,这不能一句话就解决了,怎么贴,咱们要研究这个事情对,然后呢最后就说一下纹理的一些其他应用,它可以不是只单单去这个指定一些颜色。
它还有很多非常非常强大的这个应用,那咱们今天就从这里开始说,那么第一个话题,咱们今天要说这个如何在三角形内部进行任何属性的差值,然后为了做这一点呢,然后呃我们引入的一个概念就叫做重心坐标。
那么咱们先说这个事情啊,所谓重心坐标,大家看到英文啊,barry centric coordinates,然后这个重心坐标是为了做什么呢,是为了做这个三角形内的差值,那咱们首先啊在做差值之前。
先把这几个问题搞清楚对吧,首先我们为什么要在三角形内部进行插值,那刚才其实通过对上节课内容的回忆,咱们已经知道呃,我们要做的事情呃,有很多操作是在三角形的顶点上完成或者说计算的,然后在三角形内部。
我们希望它得到一个这个平滑的一个过渡对吧,就是为了做这么一个操作,所以说当我知道顶点的属性的时候,我希望在三角形内部的任何一个点得到一个这个值,并且这个呃如果每一个值点的值我都知道。
那其实是一个平滑的过渡,从一个顶点过渡到另外一个任何一个顶点对吧,然后是这么一个意思,这就是说我们需要差值,然后呢另外一点就是我们差值什么内容,这是一个这是另外一个事情对吧。
就是说这个定义在三角形的顶点上呃,可以定义各种各样不同的属性,比如说我们之前提到说这个啊这个这个在不同的顶点,我们可以定义任何一个顶点映射到纹理的哪一个部分对吧,就是空间中的一个三角形。
应该对应这个纹理上的哪一个三角形,这就是说把这个三角形贴过去对吧,那我知道说三角形三个顶点分别映射到这个纹理上面的呃,这些哪些uv,那么在三角形这个内部的这些地方呢对吧,然后这是一个啊。
另外呢也可以定义这些竹顶点的其他属性,比如说颜色对吧,一个三角形假设它的三个顶点是红绿和蓝,那么它的在中间应该有一个自然的过渡对吧,所以这个也可以插值,那么我们既然提到呃,逢shading同时定的话。
他这个一肯定是呃每一个顶点自己都有一个法线,然后在这个三角形内部要先把法线插值出来,那么这个法线的差值,这个就是就是呃我们呃差值的内容,就是定义在三角形顶点的这些呃法线,那大家从这一点上可以看出来呃。
这个差值啊,基本上来说可以对三角形顶点上的任意的这种属性进行差值,事实上也就是这样的呃,也就是说那在我们进行这个实际的这个差值过程之前,先把这个了解清楚好吧,然后呢怎么做差值对吧。
然后这个就是说我们了解清楚后,我们要插值某种属性,然后我们要得到中间的一个平滑的过渡,那么怎么做呢,我们就引入这么一个概念,叫重心坐标好,那我们提了那么多次重心坐标了对吧。
然后我们先看一看这个重心坐标到底是什么意思对吧,那咱们看这么一个例子,大家现在在看一个三角形,首先呢我们说重心坐标是定义在一个三角形上的好吧,就是说给你一个三角形,你定义一套重心坐标,换了一个三角形。
那是另外一套,是这么个意思好吧,然后首先你有一个三角形abc,那么呃重心坐标所告诉我们的事情,就是说在这个三角形a b c所形成的这个平面内,任何一个点x y都可以表示表示成这三个顶点a b c。
他们坐标的线性组合,什么叫线性组合呢,大家看这里这个这个阿尔法乘以a加上贝塔乘以b加上伽马乘以c,这些a b c指的都是坐标,就是它是x a y a就是这个意思,b的坐标就是x b y b道理是一样的。
那么呃我们回到这个定义上来,就是说啊这个空间啊不这个三角形所在平面上的任意一个点x y啊,都可以用这个呃三个顶点他们的坐标的线性组合来表示,只要满足一个条件就可以,什么条件呢。
就是说它的这个线性组合的系数alpha和贝塔和伽马加起来要等于一,在这种情况下,我们就管这个alpha贝塔伽马,也就是这三个数合在一起作为一个坐标,用来描述这么一个点x y啊,是这么一个意思。
也就是说啊,这里就是就是说我为了描述一个点的位置,我再也不需要知道什么这个这个什么直角坐标系啊之类,这些坐标系就是只要给我任意三个点,我不管它这三个点a b c是在什么样一个坐标系里面。
表示只要有一个点在三角形abc所在的平面上,我都可以通过阿尔法加贝塔加伽马等于一这么三个数,然后对这个阿尔法贝塔伽马做一个线性的这个呃平均嗯,然后我们就可以得到一个这个呃。
嗯这个任意点他在重心坐标下的表示alpha贝塔伽马,那么有同学要问这么一个问题,这个阿尔法加贝塔加伽马等于一嗯,那我有ala有贝塔,我不就知道伽马是多少了吗,对吧,它它是一减阿尔法在减肥的啊。
没有任何问题,就是这样,也就是说啊,实际上来说,这个重心坐标虽然是三个数,但由于这么一个条件的限制呃,那么其实它就是两个数,然后这个其实是有道理的,对不对,三角形所在平面自然是二维的,二维的。
我当时用两个数就可以表示了,为什么要三个呢,对吧,所以这样想有道理,那么我刚才没说完哈,我刚才说这个三角形所在平面上,任何一个点都可以通过a b c的线性组合来表示。
但是如果这个点在三角形内还需要满足另外一个条件,什么条件呢,就是说这个这三个系数就是alpha贝塔和伽马都必须是非负的,也就是说alpha大于等于零,贝塔大于等于零,伽马大于等于零,没问题。
然后就是说这个当这三个条件都满足的时候,然后我们就知道这个点在三角形内啊,这个是两个事啊,如果不满足这个非负的条件,这个点只要它阿尔法加贝塔加伽马等于一,这个点一定是在三角形所在平面内。
有可能在三角形外啊,但如果说满足了这三个呃,系数都是非负的,那这个点一定在三角形内,这就是中心坐标好吧,那咱们这个呃先说明白,然后咱们现在就可以利用这些这个重心坐标做一些事情,然后比如说我现在说呃。
那我问在这种定义下,这个a点自己它的重心坐标是什么,这里呢我这个摄像头稍微挡一点啊,那没关系,这是a点,a点他自己的重心坐标是什么,诶,那我当然知道这个a点可以写成一乘以a加上零乘以b,加上零乘以c啊。
没问题,然后呢这个这个也就是说这个呃a点所在的重心坐标呃,那就是alpha贝塔伽马等于什么呢,等于100,所以这个a点的重心坐标就是100,那如果b点呢自然是010,c是001,没问题吧。
哎这就是我们直接从它的定义,我们就可以知道这些呃这个a abc 3个点所所在的这个呃坐标好啊,刚才有同学问我说,为什么这个alpha加贝塔加伽马等于一哈,这个是这个重心坐标轴这个自己要求的一个事情啊。
如果这三个条件不满足的话,那么你得到的这个点不在三角形所在的平面内啊,这个我不再呃这个多解释,这个解释起来这个相对复杂一些啊,然后然后这个就是alpha贝塔伽马之和等于一。
是为了限制这个呃你所要的那个点在三角形所在的平面内啊,这是这是呃结论好吧,然后呢呃我们现在回到这个话题上来,我们刚才知道哈,从这个重心坐标的定义我就已经知道啊,好这个a b和c它们的坐标是多少了。
那么如果我要求任意一个点它的坐标,比如说像这里我给出任意一个点,它的重心坐标是多少呢,这里其实重心坐标给出了另外一个定义,什么定义呢,就是说啊这个点的重心坐标其实是可以通过面积比求出来的,什么面积比呢。
就是这么回事,比如说啊大家看这个点三角形内的任意一个点,我可以和ab和c都连上线对吧,连上线之后呢,我会我可以发现哦一个顶点它对面一定会有一个三角形,什么叫对面啊,就是大家看这个a。a点。
它对面的三角形就就是和它不相邻的这个小三角形,那就是这个三角形啊,这是a点对应的这个三角形,同样道理,b点对应的三角形也是在它对面和它不相邻的这个三角形,c点也一样,然后我们定义这么三个三角形。
然后我们就可以通过面积比什么面积呢,就是说这个这个阿尔法贝塔伽马,咱们以这个alpha为例哈,alpha乘以a加贝塔乘以b加伽马乘以c对吧,alpha呢就跟a相关,跟a相关,那它的这个重心坐标是多少呢。
就是这个a点对应的这个这个三角形的面积除以总总的三角形的面积,就是整个三角形abc的面积,大家可以看到就是呃我要求阿尔法,那我就找到a找到它对面的三角形,求出来它的面积去除以总三角形的面积。
这就是阿尔法,那同样道理,我要求比如说伽马,大家都会都知道,根据刚才定义哈伽马乘以c对吧,也是要跟c这个再在一起运用的,那咱们就找找到这个c点,找到这个c点,它对应的这个三角形,它的面积叫ac对吧。
它对面的三角形ac然后再除以整个的三角形的面积a a b c啊,那这样的话就可以求出这三个这个不同的重心坐标,这同样也是这个重心坐标本身这个它它们的这个定义,当然这个也可以推得出来哈。
这里就不用这个多给大家说了,这是我们如何去求这个呃,阿尔法贝塔伽马就是重心坐标,那么大家想象一下啊,就是说如果我给了任何一个点,那我又知道原本a b c3 个点在哪,那我就知道所有点在哪。
那比如说以这个aa为例哈,这个三角形小三角形为例,那我知道这三个点的位置,那我当然可以把这个三角形的面积算出来,没问题吧对吧,所以说这个呃没有任何问题,然后这就是这么一个定义方法,那从这个定义方法啊。
我们立刻可以得到一个非常特殊的点,它的重心坐标是多少,这个点是什么呢,这个点就是三角形自己的重心,这个三角形的这个这个重心呃,xy对吧,大家可以看到这个红点在这个a abc上。
然后这个三角形的重心它有一个非常好的性质,什么性质呢,如果你把这个重心和a b c非常这个联系起来之后,你会发现他把这个这个大三角形abc均等的分成了三份,然后分成了三个等面积的三角形。
那既然都是等面积的三角形,根据刚才的公式直接一算就可以算出来哦,这个重心它的重心坐标就是13/3分之一,1/3,没有任何问题好吧,这就是通过刚才一个定义,我们就可以拿到这个这个呃另外一个点。
那当然对于任意的一个点怎么计算呢,我们刚才说可以算面积对吧,算面积,但是呃这个有一个这个更简化一点的方法,这已经可以给出来嗯对吧,就是说呃大家可以去真正的算一下面积没有问题。
利用我们所这个教的这个这个差成,然后如果我们就这么做的话,其实也是可以推出来这个式子的,就是说啊任意一个点xy,然后他这个给定这个a abc的坐标。
这个对x a y a c l这个这个x b y b这些这些坐标,然后呢我怎么算出来这个任意一个点x y它的重心坐标呢,它的公式就在这里,大家会发现啊,同样它就算了,alpha和beta。
由于规定了这个他们这个alpha贝塔伽马的和是一,所以伽马不用算,直接剪辑出来,那这个道理就在这儿好,那么这个这就是我们说的这个重心坐标,它的一个一般的表达式。
那么这个表达式当然没有任何必要去记忆它对吧,就是说它的定义我们都已经清楚了,然后对于任何的一点,我们知道我们都可以算它的中心坐标,那就可以了,那么咱们就可以用重心坐标做一点事情,什么呢。
我们就可以直接应用这个这个重心坐标呀,去去这个做任何一个点,在三角形内部的点,它的颜色的差值,那么怎么做呢,呃是这样哈,大家知道任何一个点,比如说这个点是p点。
那我可以写成alpha加上贝塔b加上伽马c这么一种组合的形式,同样重心坐标所告诉我们的事情,就是说如果要做差值,那么我要差值的属性,同样也应该用重心坐标去把它给线性的组合出来,那么是什么意思呢。
假如说我这三个顶点有三个属性,va vb和vc,然后呢我这个我就可以通过任何一个三角形内部的点,它的重心坐标alpha的伽马,然后我把这些属性线性的组合起来,然后得到任意一个点,这个它的属性v这里。
所以这个属性可以是任何的属性,比如说位置,比如说这个这个纹理坐标,或者说我们说uv,然后说或者颜色像这里就是颜色对吧,然后这个呃或者是我们说的这个呃发现。
或者说我们之前提到说我们我们在做这个光栅化的时候对吧,三角形打散成这个这个这个像素,然后一个像素的中心它对应的位置它的深度是多少呢,当然也是通过这个在三角形和三个顶点定义深度,然后把它插值出来,没问题。
也就是说啊,重心坐标就允许我们说先算出它的这个位置的重心坐标在哪儿,然后我们在这个用重心坐标做差值好,那没问题,就是说这就是这么用的啊,然后呢这个有一点。
这里就是说如果大家这个读其他的这些这些open gl一些文章或者干什么,然后可能会涉及这么一个问题啊,就是说这里给大家说一下这个事情,就是说重心坐标虽然不错,大家看这个应用非常简单对吧。
任何一个点只要有中心坐标,我就可以插值任何的这个这个属性没问题,那么中心坐标有一个问题,也就是说啊他在投影下,在投影的变换下是不能够保证重心坐标不变的,是什么意思呢,就比如说大家现在看到这个三角形啊。
假如说是一个这个空间中的一个三角形,然后呢,它这个呃我可以算出这个点,这个v它对应的这个这个这个重心坐标在哪,那如果我把它投影到某一个平面上去,这个三角形形状会发生变化吗对吧。
然后我这个这个a abc和中间这个点呃,这个我都可以算出来它投影之后的这个坐标吧,那投影之后我再从这个投影之后的三角形,我再算一遍这个呃这个点的中心坐标,我会发现诶得到了一个不一样的中心坐标。
这个是很有可能的事情对吧,然后然后这个这个就是说啊重心坐标它并没有一个好的性质,就是说它在投影下不变,没有这么一个性质,就是说呃如果有个三维空间中的三角形,然后你这个有一个点投影了之后。
它的重心坐标就不一样了,那么也这个事情也就是告诉我们,如果我们想插值一些三维空间中的属性,我们就应该这个取这个三维空间中的坐标,就是这个a abc,然后这个取它的三维空间中的坐标。
然后取这个这个找的这一个点,比如说这个p中间某一个点,它的坐标也是三维的空间中中中的坐标,然后呢我来算它的这个这个呃重心坐标是多少,然后呃我再去做差值,而我不能在投影之后的三角形里面做。
哎这一点是呃专门为了说一个什么问题呢,我想说的就是深度,大家想象一下啊,呃我们之前说光山话三角形呢都已经投影到这个屏幕上去了,然后它会覆盖很多的像素,然后像素都有中心,然后像素的中心的这些点呢。
然后这个呃我可以知道它的投影了的三角形的哪里没错吧,然后我可以说在投影的三角形里面,对这三个顶点的这个深度的差值可以这么算吗,其实是不对的,是怎么应该怎么算呢,应该是这个呃,找到你这个像素中心点呃。
对应这个三角形位置,它的三维空间中的坐标,然后我在三维空间中,然后把这个a abc它的深度差值好放回来,是这么一个做法,这样才是对的,那至于怎么样把这个已经投影到屏幕上,在投影回去。
我们应用逆变换就可以了,这个没问题,这个大家在这个专业中会稍微碰到一点点,但不要求大家去做哈,然后这里是这个呃,我要说的一个事情好吧,这就是说在三维空间中的属性,建议是在三维空间中这里做差值。
然后这个这个这个呃,在这个把这个值对应到这个二维的这个结果上面去,好吧,是这么一个事情好,那这个这里把这个事情说明白,这个根本原因啊,就是重心坐标它本身在投影操作下会发生变化啊。
好那么重心坐标的差值很简单,咱们已经说完了,咱们下面一步就要说这个怎么把纹理给给应用在这个这个这个这个啊,实际的这个渲染中好吧,那么怎么应用呢,我们之前其实在提这个shadder的时候啊。
我们已经说了这个事情呃,什么呢,就是说我这个屏幕上的任何一个采样点啊,不管是像素还是说我这个呃用m s a a它代表一个采样点吧,反正就是说他自己肯定有一个位置,它有一个位置。
然后呢我就知道这个呃他嗯在这个位置上插值出来的uv,或者说纹理的坐标在哪里对吧,原来纹理的坐标都定义在三角形的顶点上,现在对于任何一个点我都知道它的三角形哪儿,然后做一个差值。
就用咱们刚才说的重心坐标可以算出这一个点,它的uv好没问题,它的uv算出来之后怎么办呢,在纹理上去查询一下这个uv的值,我就知道了,好没问题,我就知道这个对应的纹理呃,是这么个颜色。
那么我们就可以拿来用这个颜色,这个颜色可以怎么用呢,呃我们可以认为哦这个纹理定义的就是这个漫反射的系数,然后这个这个这个漫反射技术,这个大家还记得在这个不联防模型里面,它就定义这个kd。
然后我就可以直接用我取到的这个test color纹理上的这个值去代替这个kd,那不就等于是把这张图给贴在了这个这个这个这个呃物体上嘛对吧,并且这个物体还有这个这个风水岭能够带来的这个呃就是明暗的变化。
高光这一系列的东西对吧,就是这么个意思,那这就是我们怎么样去用这个纹理映射,太简单了,任何一个点找到这个屏幕上点啊,找到文理在哪儿,然后直接查怎么用,随便对吧,那行没问题,那这就是我们说到这里。
这这这就这就可以了,然后呢,那咱们这个呃进继续进展,下一步下一步是什么呢,我们看它到底出了什么问题,如果这么简单做会出什么问题好吧,咱们先看第一个问题,第一个问题我们管这个问题叫做这个呃纹理的放大。
什么叫纹理的放大呢,大家可以看这里有一个问题啊,就是说哈呃如果这个纹理太小了怎么办,什么叫纹理太小了怎么办哈,假设说我们有一个三维场景,我们把它渲染出来,然后我们对着一堵墙来看,这个墙上有一幅贴画啊。
然后然后就是就是这么回事,我们知道这幅墙这个墙上如果我要应用这个一个一个贴画,很简单啊,用到一张图上就好了,唉现在我问的问题是说啊,假如说我们看着一个一堵墙。
然后整个分辨率我们定义这个呃渲染出来分辨率是这个4k好,没问题吧,然后这是非常高的分辨率,但是我们的纹理只有256x256,唉这个怎么办,这也就是说啊,那我们看一个这个很高分辨率的强。
然后这个任意一个点,他去查这个纹理的时候,他会查到一些非整数的值,对不对,也就是说啊纹理太小了,纹理就会被拉大,被拉大了,自然就会看到这样的现象,就是说啊这个呃纹理本身太小,首先呢它是一个问题。
正常情况下,如果大家涉及到打游戏啊或者干什么,大家都会避免这个问题,就是说这些游戏的制作者,他不可能会让你说这个这个有一些很重要的一些地方,然后他用了一个很低分辨率的纹理。
但是啊这种情况普遍意义上还是会发生的,也就是说这个嗯嗯就是我刚才说的例子啊,看着一个高清的一个奖,但是它上面贴的这张图却很低级,那怎么办呢,那很简单,对于任何的这个这个呃墙上的一个点对吧。
一个像素这一个点我都可以找到它对应的这个纹理上的一个位置,然后这个位置可能不是整数,不是整数,怎么办呢,那咱们就把它给这个这个around成整数,就四舍五入成整数好吧,我把它给这个,比如说零点点四。
我认为是零啊,0。6我认为是一,那这样的话呢就相当于是呃在一定的范围内,就是我们要查找的是呃一个相同的这个纹理上的像素,然后纹理上的像素它是有个名字的,叫taxi,然后中文叫文理元素或者文素啊。
反正这个挺别扭,然后我就管它叫pixel和txo,这样来说吧,pixel呢就是我的这个生成的这个画面上面的一个像素,然后text就是纹理上的一个像素,那么我们现在可以看到啊,一个pixel一个像素。
它可能说在一定的范围内,然后呃然后就是说它周围的很多像素吧,比如说3x3或者5x5,很很多像素它都会被映射到同一个这个呃txt上去,这是因为纹理太小了对吧,所以如果我们去做一个简单的四舍五入。
我们会得到这么一张图,然后呢我我们不希望这样对吧,这看上去一个一个格子很难看诶,我希望说能得到这个这个中间或者右边这样的一种效果,也就是说我引入点模糊没什么问题,但我希望最起码得到结果是稍微连续一点。
这也就是说明什么呢,这就是说我这个当我在查询啊,查询这个纹理的时候,如果你给我一个非整数的坐标,那我应该如何得到它的值,对不对,这就是我们要说的这个呃这个双线性差值它的概念呃,所谓双线性插值。
咱们看一看啊,我我刚才说这个呃我们的一个高分辨率的这个这个屏幕,它上面一个像素里面的中心呃,它映射到了一个非整数的这个位置上,而我们现在看到的这个4x4的格子是taxo,就是像就是那个那个纹理啊。
然后它映射到这个位置,那我想知道好纹理在这个红点处它的值是多少,那么我刚才说啊,有一个最简单的办法找离它最近的嘛,就找这个点,那么说如果这个红点在这里,那也会找到这个点。
那整个这一块可不就显示相同的颜色了嘛对吧,然后然后就会形成形成一块一块,现在我不想,现在我想怎么做呢,我想这么做诶,我想知道这个这个像素的中心会映射到这儿,我可以找他临近的这么四个点对吧。
临近的四个点我总可以找得到,然后临近四个点找到了之后呢,然后我们还怎么办呢,我们在做这么一个操作,就是说啊呃我们知道这个屏幕空间我们定义过了对吧,从左下角开始向右向上对吧,然后同样道理。
这个四个点它总有个左下角,然后你的这个红点你可以找到说这个离左下角,它的水平距离和竖直距离啊,大家看这个水平距离,我们管它叫s,然后竖直距离管它叫t,这个s和t肯定都是0~1之间的,为什么呢。
因为这两个像素或者两个txt之间,两个txt之间它的距离是一,如果这样认为的话,那这个呃这里没考虑那个叫什么uv,它的定义是0~1哈,咱们就以这个呃一个一个像素这个单位为一好,那也就是说这个长度是一。
那么对于它投影出来的这个分量水平的这么一个距离呃,就管它叫s一定是在0~1之间,t也一样好,咱们现在找到周围四个点投影出这么两个这个长度好,下面一步怎么办呢,下面一步啊,我们定义一个操作叫做线性差值。
线性差值太简单了,什么意思呢,就比如说这个有两个,你有两个不同的值吧,在定义在两个位置上,然后呢如果我定义一个x是0~1,我认为这个这个x等于零的时候,x在这里,x等于一的时候,它在这里。
那么我问x等于0。5的时候在哪啊,它应该在中间对吧,x等于0。9的时候在哪啊,应该靠近这个这个这边对吧,然后这就是这个这个线性差值,然后大家看这个例子啊。
linear interpolation就是它的定义简称lp就是linear interpolation的意思,线性差值,线性差值什么差值,这个v0 和v一分别定义在位置零和位置一上。
所以x是一个0~1之间的值,那么咱们看看x等于零的时候,然后我们可以看到这个值等于v0 ,没问题,x等于一的时候,然后这个定义啊就是v0 加v一到v0 ,那就是唯一,所以x等于一的时候是呃只是为一。
那x等于0。5的时候,大家可以发现啊,正好是两者中间,所以他就做了一个这么一个线性差值,如果咱们定义这么一个操作的话,那行咱们现在就已经不用关心具体线性差值的这个公式怎么做了。
咱们就直接可以做一个差值什么呢,大家可以看到这两条线水平的这两条线啊,就是左下角右下角,然后我用x可以做一个线性差值,然后左下角这个点有一个颜色呃,这个点有一个颜色,然后呢它这个中间的位置。
这个我就知道它离左边距离是s,然后我就可以用这个s来对这两个点它的颜色进行一个差值,好,我得到一个这个黑点,同样道理,我对上面这条边对左上角和右上角这两个点,这两个既然定义在这个纹理上。
这两个有两个不同的颜色,然后呢我也知道哦,它水平距离离左边s,然后我就用这个s去插值这个左边和右边诶,我得到另外一个差值出来的值,诶,那我现在把这两个这个这个差值完成了之后怎么办呢。
我最后想得到这个红点处的值啊,那大家可以看到这个应该已经可以想象的出来了,对不对,然后这个我再做一次数值的差值就可以了,我把这个竖线上,我因为这两个黑点的值我已经算出来了对吧,我数值这个方向上我可以看。
比如说这这一个点,然后这一个点,然后我要插值出在t这个距离上的点,为什么是这个这个t呢,是在这儿啊,t这个数值的距离呃,这是这段距离是t然后我就用t来差值这个点和上面这个点,就刚才差值出来的两个点好。
我再用t把这两个值插值出来好,那么大家就会看到好,这里我做的呃两两种吧,差值第一种叫做这个水平方向的这这两个点,两对点分别进行一个差值,然后我得到两个点,然后我在竖直方向再进行一个差值。
那我就可以得到竖直方向这一个值没问题,那大家可以看到这个点的颜色,现在就综合考虑了它周围的四个点的颜色,并且呢咱们假设一下这个红点啊,如果非常靠近这个u00 ,你得到的结果就应该和这个u00 很像。
那如果说这个这个红点它在正中间,它就应该是这四个点的这个平均值没问题,这里就是说这两个通过这两步水平和数值的这个差值诶,我就可以得到一个平夸的过渡,在这个在这么四个点围城这个区域内。
就可以得到任意一个点,它的平滑过渡的颜色是多少,哎所以说这是一个不错的做法,所以呃这个就是说我做了两趟差值对吧,水平一趟,数值一趟,然后我们就管这个方法叫做双线性插值,因为做了两趟线性。
当然我没说两次哈,大家知道这个水平上做了两次,是不是让他做一次啊,就是指水平和数值都要差值,我们就管它叫双线性差值,当然有同学问这里这方向能不能反过来,能没任何问题啊,这个大家可以这个手推一推这个公式。
你就会发现先数值在水平一样的,没什么问题好吧,那道理就在这儿哈,咱咱们把这个这个这个呃思路先先这个搞清楚对吧,我们有一个很小的图,然后呢这个我要把它放大。
我要查询它在任何一个这个非整形位置上的这个值是多少对吧,我希望它平滑过度,平滑过度怎么办,找连续的,找这个最近的四个点,做一个这个双线性差值,就可以得到平滑过渡的结果。
那么这里中间这幅图呢就是大家看到的这个呃双线性插值的结果,而双线性差值大家可以看到啊,效果挺不错的对吧,然后呢这个比这个我就什么也不考虑,我直接把这个四舍五入坐标做这个。
弄到这个整形的这个这个txt的坐标上,然后我就这个直接找他,我就会发现很多像素都会被映射到同一个txo上去,然后就会出现格子,现在没有对吧,没有挺好的。
但是呢就是说啊这个这个双线性差值它当然也有它的问题,就是说它的质量和一些更高级的方法,它有这个呃这个还是差一些,比如说大家看右边这幅图,右边这幅图呢叫做这个这个这个这应该怎么说呢,这是嗯我想了想哈。
这个英文好吧,我们就管它叫白cubic吧,就应该是双向,这个这个三次的差值,咱们只能这么翻译啊,就是这这翻译不好,那咱们就用英文吧好吧,双线性叫白linear,然后这个叫做叫做by cubic。
by cubic呢,其实其实这个道理也好理解,他取的不是周围的这个临近的四个哈,他取的是这个你任意一个点取周围临近的16个,然后这16个也是做这个数值的和水平的这个差值。
只不过每次用四个做一个这个三次的这个差值,不是用线性的这个差值好吧,这里简单给大家提一下,那么这个这个by cubic这个这个大家可以想象,它肯定比把linear的运算量要大,它取周围的16个嘛。
把linear我只用周围的这个四个嘛,然后它它这个运算量大,但是它带来更好的结果,不知道大家这个图里面啊,这个经过了这个直播之后还看得清楚,比如说大家看这个眼角这段这段看得特别清楚。
就是说双线性插值在这里还可以看到一定的锯齿状啊,然后但是在这个by cubic差值这块,大家就看不到什么太那个这个这个差值了对吧,然后这个好吧,咱们呃大概就是这么个意思啊。
然后大家这个又一次体会到这个事情,在这个图形学里啊,呃我们频繁遇到这样一个问题,对就是说这个好的质量的东西往往都伴随着这个更高的这个开销,然后呢这个大家通常会提出这么一个东西,后来再去这个再去想说。
我怎么样把这个开销降下去,我又能得到好质量,这是基本上一个这个这个提高的一个思路哈,这个呃就简单跟大家说一说,这是关于这个纹理的放大问题好吧,这就说到这儿好啊,ok然后呢这个啊看不清问题也不大啊。
基本上来说这个双线性效果已经不错了,然后这里呢呃我们刚才已经提到了,说如果这个纹理挺小,那我看着一个这个很大的一个平面,然后这个图这个纹理肯定要被拉大,会出问题对吧,那么我们现在想另外一个事情。
如果这个纹理太大了会怎么样对吧,这是另外一个问题,但是大家这个这个想一想,这个这个纹理大了有什么问题吗,小了我当然需要这个差值出来,大了我不需要啊,到了怎么会有问题呢。
答案是这个纹理大陆的话反而会引起更严重的问题,而这个就是就是说和这个这个嗯这个这个这个第一想法不太一致,对不对,这个大家会觉得文理大的话什么信息都有啊。
这怎么会引起什么问题呢,啊咱们来看一看好吧,就比如说啊大家现在看这么一个这个平面,这个平面呢往这个远处延伸,大家可以看到前面这个地平线对吧,然后这个这个平面呢上面贴了一张图,这个纹理纹理是什么呢。
是一个格子,是这个格子水平竖直的啊,这样这样贴上的,然后咱们从某个角度上看过去诶,我们会发现啊,这个近处看到格子挺大的,然后远处这东西挺小的,没问题,我们做透视投影嘛对吧,这个肯定是这样的。
远处的格子会挺小,那么大家可以想象一下,如果我还照之前的操作啊,简单的这个应用纹理怎么应用来着,像素的中心对吧,找这个纹理坐标,然后求出这个纹理坐标上的这个值是多少,我们已经知道怎么差值了对吧。
所以任意的坐标都知道,然后然后它的值啊,然后我们把这个值写回这个像素,那如果说我们要做这个这个简单的操作会得到一个什么东西呢。
我们会得到这么一个这个这个呃,看上去非常非常不对的一个一个东西对吧,然后大家看到什么了呢,大家看到了很熟悉的东西叫摩尔纹啊,远处摩尔纹,然后近处当然大家看到了很严重的锯齿。
所以说大家这个从这个纹理上大家就会看出呃,和之前的一个现象完全完全一样的问题对吧,就是走样这个走样问题,那咱们这个又遇到他了,那么这个问题到底是怎么来的呢对吧,然后这我们怎么解决呢。
这就是我们下面要探讨的问题好吧,然后这个呃大家可以看到这个原处这个是越来越差越来越差。
从这进出多少还能看到远处越来越差好呃,然后这里问题在哪儿,那咱们分析一下,为什么呢,因为近处其实一个像素来说啊,它这个覆盖的这个呃这个纹理上的一个区域其实相对较小,就比如说像这里。
就像这里覆盖纹理上的区域相对较小,然后在远处那一个像素,它其实这个覆盖了一片纹理,覆盖了一个很大的一个区域对吧,那也就是说啊,这告诉我们屏幕上的这些像素,它们覆盖的这个纹理上的区域大小是各不相同的。
那如果说对于一个这个像素,它覆盖纹理上的一个区域挺小好,我用这个像素的中心查询一下它的值啊,我知道啊,这就是这个像素所覆盖区域的这个纹理的值,我可以近似的这么认为,没问题,可是如果一个像素。
就比如说以刚才为例,那些像素覆盖了纹理上面的很大一块区域,现在我还用它的中心,我去查这块区域,我说好,我就看这一个点,这个点的值我就认为是整个这一块区域它的平均值,那这个呃听上去就首先就不对对吧。
就是说我用这一个点如何能代表这么大一个区域,它的这里面这些不同的这些点,这些颜色的变化对吧,这是代表不了的,就是说当这个像素覆盖的这个纹理的区域大的时候,我们就不能这么简单的去采药了对吧。
就是说中间用用它的这个这个像素中心去采样了。
那这就是我们遇到的问题,那么这个大家自然而然就会问这么一个问题对吧,之前我们解决这个这个锯齿怎么解决的来着,我们做这个抗锯齿对吧,我们引入了这个这个这个呃这个m s a a。
或者说我们说超采样的都是差不多一个一个概念,怎么做的呢,其实就是说我一个像素,我用更多的这个呃样本对吧,不同的位置像在相同内对吧,我去感知这么一个变化的函数,没问题,这里我们同样也可以这么做。
比如说大家现在看到右边这幅图哦,如果我这个每一个像素里面我用512个点呃,这个这个采样点,然后我把这些点都给这个呃对应的位置,在这个管理上算出来,然后取出的值,然后对于远处的一个像素,比如这个像素。
它里面有512个点,我取它们的值的平均,然后就可以得到一个不错的这个结果,没有问题,说这个超采样能得到一个很好的结果,没问题,但是同样道理对吧,我们用很多的这些这个采样点。
肯定会让这个呃整个算法变得特别慢,那咱们不希望这么做对吧好。
那咱们回来看这个理论上到底我们应该如何分析这个问题,那首先我们遇到的是一个这个这个走样的问题,那走样是怎么来的呢,这个大家还记得吧对吧,就是呃信号变化过快,我们的采样的速度跟不上它或者采样频率对吧。
那么这个在这个问题上如何体现,就是说我们在这个纹理过大这个问题上如何体现这个采样这个概念呢,很简单,什么呢,就是说当这个纹理特别大的时候,你的一个像素里面像素内部哈,这块纹理它是在一直在变化。
然后也就是说在一个像素内,它的频率很高,可是你只用了一个采样采样点去采样,它那肯定是不行对吧,那么我们回到之前我们说的这个信号的这个概念上来,这个不需要任何公式。
咱们想就能想明白一个像素内它有着非常高频的信息,我希望把这个像素内的值给这个这个重构出来对吧,那我就应该需要一个更高频的采样方法,这就是为什么说我们需要这个这个非常多的这个这个这个采样点。
在一个像素内对吧,我们用这个超采样的方法对吧,然后我们一个像素内取好多个点采样这个这个纹理上的这个知识,并且平均起来,这就是我们要做的对吧,然后然后就是说这个这是一个这个沿着以前的这个方法。
然后咱们做了一个一个呃简单的一个思路分析对吧,那当然我们不想用这么多这个这个太阳点,那怎么办呢对吧,因为我如果一个像素真的就用512个采样点的太多了,咱们怎么办呢,我们这里提供另外一个完全不一样的思路。
什么思路啊,行采样会引起怎样,对不对,那咱们不采样怎么样对吧,如果我们可以避免采样,那什么叫避免采样啊,我原本说啊,这个大家还记得刚才那些这个像素会在这个纹理上覆盖,很这个很大的一块区域。
那如果我立刻就可以知道这个区域里面它的值的平均是多少,我我不采用,我如果立刻可以知道这个平均值是多少,那就很好了,对不对,诶,那如如何我们才能知道这个给你任何一个这个呃这个区域,比如说咱们看这里啊。
还是刚才这一页,任何一个区域你立刻可以得到它的平均值对吧,我们要解决这么一个问题,那这就是我们之后要说的这个所谓mile map这么一个概念,当然在这之前我们先在这儿停一下啊,这里就是说我想这个说一点。
就是这个问题其实是一个算法问题,这是在这个数据结构啊,在这个计算几何啊,在这个呃很多领域上都得到了一个应用,那那就是说啊这个是什么问题,就是说点查询问题和范围查询问题,然后点查询很好理解。
比如说这个以这个texture纹理为例,给你一个点,它的值是多少,咱们刚才说双线性差值,说什么都是这个这个道理,这叫点查询,另外一个呢咱们所说的是咱们不做采样对吧,给你任何一个区域。
你立刻可以得到它里面内部的平均值,这个就叫做范围查询,叫range query,range query是一个这个是一个这个呃经典问题,然后呢就是说在这个算法上,这个呃有各种不同的这个方法去研究它。
当然在图形学上大家找了一个非常非常近似的,但是很快的方法来做这个范围查询,另外多说一句啊,范围查询可不只是我们用的这一种应用叫平均查询,我们要求这个范围内的平均值,这是我们要的结果对吧。
也有些范围查询是要查范围内的最大值和最小值,这个问题就完全不一样好吧,然后然后就是说有很多不同种类的范围查询啊,那咱们这里就就说到这儿,那说白了就是说现在给你这个这个呃一个图上面任何一个区域。
你能不能快速地告诉我它的平均值是多少,这就是我们要的这个这个结果,然后呢我们以这个实际的渲染的这幅这幅图为例,比如说我们想渲染这幅图,那大家知道这块比如说这个窗台这块啊,离大家挺近的。
那也就是说这块一个像素覆盖的区域,这个范围相对较小对吧,在这个纹理上覆盖的区域相对较小,那么这块区域离我们很远,那这一个像素其实它覆盖在纹理上,它应该覆盖的非常大对吧,然后假设说我们用的同一个纹理哈。
然后好,那么就是说这个不同的像素有不同的这个呃在纹理上覆盖的大小,那所以我这个范围查询应该能够查询任意不同的大小对吧,那也就是说呃对这就是刚才说这两个区域上啊会有各种不同,然后呢这里我们引入了一个概念。
就叫做mp map,map,map是一个在图形学上得到一个广泛应用的经典概念,那么他能干什么,这里现在就可以告诉大家,它允许大家做范围查询,这正是我们要的东西,对不对,诶,但是我这里有三个这个不同的词。
这里啊第一范围查询做的快fast,然后第二是approximate,也就是说他做的范围查询是不准的啊,首先来说做的范围查询是不准的,它中间涉及到近似,但是因为它快对吧。
大家希望的东西能够跑得越这个越快越好,然后另外一个它可以做什么,它它可以做的是仅仅是方形,特别只有是正方形的范围查询,这点跟大家说清楚啊,就是说mile map是可以做范围查询。
但只能做近似的正方形的范围查询好吧,那咱们把这个事情说明白,然后其他要不是正方形不行,那是用什么呢,马上马上咱们再说好吧,咱们回到mile map这个概念上来。
那什么叫mile map,maple map非常简单啊,这个mirap大家可以看它这个拉丁语里来的这个东西啊,然后就是说这个mp的概念,其实就是说这个这个这个很多不同的小的东西对吧,这个合在一块儿。
那这个对应到咱们图上,其实mapmap呢就是从一张图生成一系列图嗯,那咱们看看什么意思啊,比如说大家有张纹理,这张纹理呢假如说原始的这个纹理,我们管它叫做这个第零层纹理,使得每一层都是这个上一层。
这个呃都都都是这个这个呃比如说第i层啊,都是第i减一层,它这个图缩小一倍,就是分辨率缩一倍呃,呃其实应该说是缩小到一半啊,这样说的比较明确一点啊,就比如说这个大家之前拿到的一个这个纹理。
它的分辨率是128x128对吧,那么呃这这是第零层,那第一层怎么办呢,把这个图分辨率缩小一半,那也就是说我要我把这个图重新表示成,这64x64的一个一个图,大家可以看到啊。
已经可以看到这个不同的这些这些像素被拉大了,对没问题没问题,然后这分辨率低了嘛对吧,这是为了显示哈,就是说大家看到这里它们的大小还长得一样,这只是为了显示告诉大家说现在它的分辨率是多少。
其实分辨率已经小了一半了啊,然后第二层在第一层的基础上再砍一半,就变成32x32,第三层在这个这个第二层基础上再小一半,然后这个这个这个呃16x16,那做到什么时候呢,做到最后还剩一个。
还剩这个这个这个一个点对吧,那大家知道这个总共有多少层呢,既然每一次把一条边砍了一半,那它的层数就是log 2这个呃这个这个分辨率对吧,那就总共有那么多层,就是log层好,那没问题。
那我们这个可以提前计算它,这就是关键,就是说大家拿到了一个这个纹理之后,那我先把这个纹理处理一遍对吧,在渲染之前,我先花点时间把这些生成,把这些对应的mmap都生成。
那么对应到mini map里面呢,然后这个这个我们生成的是什么,这个生成的是这么一个东西,就是第零层是原始的图像,然后上面这个小小了一倍,小了一半,然后这个又小了一半,然后一直到上面。
所以呢在这个计算机视觉界啊,大家不管这个叫mile map,管它叫image pyramid,叫叫这个图像金字塔啊,一模一样的概念啊,没有任何问题,就是说这个呃这块儿这个这个就是就是说给你一张图。
你要生成更多的图对吧,然后这个每一层我这个比如说第零层,第一层,第二层我管它叫d等于零,d等于d2 啊,就这么一个安排方法,那么现在呢我有一个问题对吧,在这个在这个应用map map之前。
先问大家一个概念,诶,我们原本有这么一张图。
然后他占据了一定的存储量,那咱们生成了那么多其他的这些图,那么总共我们引入了多大的这个额外存储量呢,就是说就是相比于原本的这个,如果认为原本的这个存储是一,那么我们算出来那么多不同的层数。
我们引入了总共引入了这个多大的这个额外存储量,就是说比原来多多少对吧,是多少呢,哈哈哈哈,这里大家可以猜一猜对吧,这个很显然不是八倍对吧,嗯比如说这里这个这张图,因为其他图都是越来越小,越来越小对吧。
然后我这里有一张图,我不能说我的这些图,其他图都跟他存储量一模一样对吧,就是log它的这个边长数倍,那肯定是不对的对吧,肯定比那个小小多少呢,大家可以算,这是一个级数求和的问题,对不对啊,大家想一想啊。
这每每次边长砍一半,也就是说每次存储量是原本的1/4,那就是1+1/4,加上这个1/16,再加上这个1/16x1/4,比1/64,再加上一直把它加上去,得到的结果是多少,43/3分之四是什么概念。
就是说原本的图存储量是一,我只是多了1/3的存储水源,也就是说啊所有这些其他的层这个把它们都给加起来,它们的存储量都加起来,唉我只是原来的存储量的1/3,这个事情很不可思议,对不对。
然后就是说这个这是这是一个这个很有意思的一个一个事情啊,这个当然等比数列这个都好算啊,没什么问题,这里呢这个嗯我想一想哈,其实有一个更简单的办法算这个我这里简单给大家提一句吧,如果大家有兴趣的话。
大家看这张图啊,看这张图,但是我这个这个怎么理解呢,就说我假设说我把我原原本的这个图啊复制三份,我们不是想说这个这个总共的存储量,额外存储量是多少嘛对吧,额外存储量是多少。
呃也就是说啊这个如果我把所有的每一层的这个存储都乘以三,那肯定不影响最后结果对吧,我要的只是一个比例好,那没问题,那咱们假设说我把原原图放在左上,右上左下,也就是说这三个都是第零层啊。
这三个第一个第二个,第三个,这三个都是第零层,那么我剩下右下角这一块,我知道我可以把第一层也复制了三份给填在这,这和这个位置好吧,然后又缺了一个右下角。
这个右下角我又可以把第二层这个左上右上左下填上去诶,然后我就可以一直填一直填一直填,我不管多少层,我最后得到一个极限是什么呢,得到极限就是整个这个块儿大小,那么咱们回到这个之前的这个概念上来啊。
这个每个图我都复制了三份对吧,第零层,第零层,第零层,其他全都不是第零层,也就是说额外的存储是多少呢,就是原本的1/3,对不对啊,这是一个这个很很很精妙的一个算法,这个当然了。
前提是你要是不知道这个额外存储是1/3,你也构造不出这种这种这种这个理解方式,对吧啊,这个方便大家理解啊,这也就是说呃对的没问题啊。
就是说mmap仅仅是额外的1/3存储,所以非常好,那么我们mile map刚才说什么来着,我们要用mp map做一个近似的,在一个正方形区域内做范围查询,我立刻要得到这个这个区域内的这个呃平均值是多少。
诶那这个这个就有同学问了对吧,那我怎么知道我上来要查询的区域,这个事有多大对吧,它长什么样,它是不是这个都可以映射到一个这个这个这个这个纹理上的一个区域,对吧,那这个区域我怎么得到呢,那是这样哈。
就是说有一个近似的办法很简单,大家可以看这里哈,就是说我们认为一个三角形它覆盖了一堆这个采样点,然后这些采样点呢比如说我们看这个蓝色点,它有一些它的这个邻居,红色点呢也有一些它的邻居,那很简单。
我想我想算啊,这一个像素就是说比如说这个红点它所占据的这个像素,它的覆盖面积,那我怎么算呢,我可以取他的这个他自己的中心和他邻居的中心,分别都投影到这个呃纹理上n去对吧。
那我就是说你看这个红点那会映射到这个红点,然后这个上面这个红点会映射到这个红点,然后右边的红点会映射到这个红点,那然后呢我就可以做一个近似,做什么近似呢,大家可以看啊,大家可以看这个点到它上面这个点。
它的距离其实差不多,这就是一个像素,没问题,然后这个点到它右边的这个距离,这是在屏幕上啊,这是pk总,这是像素,然后它到它右边距离也是一个像素,那么我就知道哦,他们这三个点分别映射到纹理上去。
它会占据多多长的这个距离啊,这个会占据多长的距离,然后就是说这个是可以求出来的,然后这里公式这也也已经写的清楚了,没问题啊,这里看着很复杂,其实完全不是这么复杂啊,这个这个呃其实目的就是为了求说。
这个我把这个这个它上面一个点扔到这个这个呃纹理上,然后它会在哪个位置,然后我我这个比如它右边这个点呃,扔到纹理上会是哪个位置,求它们的长度,求它们的长度之后,大家会发现啊。
这个长度或者说这个是这个这个点到它上面这个映射过去的点,它这个长度其实就能够基本上来说近似这个像素,也就是说这个粉红的这个这个区域,它那个所在这个纹理上,它的边长好吧,然后这是什么意思呢。
这个这个大家看这么一个框对吧,也就是说我可以用这么一个正方形框,来近似这么一个这个不规则的区域对吧,然后这里呢大家可以想象成什么呢。
就是说这里相当于再做一个这个这个这个finite difference啊,就是相当于在做一个这个这个怎么说来着,就是说我要算出来这个他们的微分。
就是就是就是说呃如果我在这个像素上这一个呃就是屏幕上一个点吧,呃移动某一个距离,往哪个方向移动某个距离,我要知道他在这个这个呃纹理这种空间上,它要移动多少距离,就是这么一个概念。
它算了其实相当于一个简单的一个微分啊,但是我们刚才说就完全没按微分这个理解,咱们就把这个对应的这个右边和上面的点给投影到这个纹理空间上,求他们对应的这个这个长度是多少。
然后这两个长度呢当然会可能会有所不同对吧,呃简单起见,咱们就取最大的就可以了,比如这样两个这段叫l1 ,就是这个这个点和它右边这个点他们映射的这个呃纹理空间上的距离。
那么这个点和上面这点映射的纹理空间距离叫l2 ,那么两个取一个最大值,我就可以近似的得出啊,如果我假设在纹理空间上仍然是一个这个一个像素,仍然会映射到一个这个这个这个这个呃矩形区域和正方形区域。
那它的边长应该是多少啊,就是这么个意思好,那么这就是这个这个这个正方形区域,咱们怎么近似得到哈,当然有同学说,那我能不能拿这个正方形的,这不就是说这个像素啊,他不是有四个顶点吗,我把四个顶点都扔过去。
然后我在这个用这个映射过去的四个顶点,然后我来算出四个边长,我在算这个这个这个它这个边长的最大值可以绝对可以没问题,反正都是进四对吧,就是说我们用这种方法也是进四,那么这里不是关键。
这里的关键是当我们可以把任何一个这个像素覆盖的区域,近似成为一个正方形的时候,那这个正方形它的查询我要怎么做,我如何去根据我的这个之前预计算好了的mmap对吧,我来查询说这个这个像素哦,不这个区域呃。
边长是l的区域,它的值的平均值是多少,那这里就是说这个mp map聪明的地方了,比如说啊我问大家这么一个问题,如果这个区域的大小就是1x1,就是一个像素,那我是不是就可以在最原始的这个这个图。
没有做过mapmap的最原始的那张那张纹理上找对应的这个像素,然后这是它的值对不对,那如果说我这个区域它的大小是4x4,那我就知道这个区域一定在第二层上会变成一个像素,为什么呢。
大家可以想象这个区域的大小是4x4,那么这个是是指是指在它这个最这个原始的那个那张图,它上面是4x4,那么如果经过第一层map map之后,这个区域会变成2x2,然后经过第二层之后。
它会变成这个这个1x1,也就是说这个区域l乘l这么个大小,它在这个d等于log 2 l在这一层上一定会对应到一个像素去,也就是说我要通过这个区域我求出它在第几层会变成一个像素的大小。
然后我就可以去查那个像素,我就可以立刻得出这个区域内的平均值是多少了啊,就是这么一个意思对吧,然后然后就是说我们是这么做的,这就是为什么啊,就是说我们在第几层去查询它呢,是在d log 2 l层对吧。
然后就是这么一个一个概念,那么大家可以看到啊,我们这个如果说我对于每个像素我都算它会投影到这个呃纹理上,对应一个多大区域,然后我把它这个这个多大区域给这个计算成。
我要在第几层me map上去找这个这个平均值诶,那我就可以做一个这个可视化,大家可以看到哦,这里离我们非常近非常近,然后这里颜色就非常非常深啊,然后这个就是说我要在很低的层去查询它,没问题对吧。
因为这里这个离我们近,能看到很多细节,我就应该在最低层去看看,然后这个这个地方呢大家可以看离离我们特别远,离我们特别远,为什么呢,因为这个地方一个像素覆盖的区域就非常大,一个像素才可能会近似这一个区域。
对不对,那我们这样想,然后这里呢大家会看到呃,基本上来说它是颜色有一个渐变,但大家会发现一个问题,这个变化好像不怎么连续啊,就是说我在第零层差,然后我突然发现a我到这儿,a我应该在第一层差。
然后我突然发现到这儿唉,我应该在第二层差,对不对,因为怎么算的呢,因为我们之前只算了离散的若干层啊,对不对,我们只算了这个第零层,第一层,第二层我们可没算1。5层是什么,那怎么办,对不对。
那我们肯定不希望说它这个在不同这个这种不连续的层上查询,那这样的话查询到的结果保不准在这个地方就形成了一道缝,不连续,那么不希望这样怎么办呢,我希望它真正的就能查询,比如说第一连八层是什么东西,怎么办。
那大家有第零层,大家有第一层,那怎么做,第1。8层呢,哎1。8哈,有第一层和第二层啊,然后你要查第1。8层对吧,那怎么做呢,很显然大家又想到这个概念了。
差值对吧,差值就行了,那比如说我这个我要查这个1。8层,那没关系,我先找第一层,我再找第二层,然后这两层内部我分别用这个双线性差值,把这个我对应的这个这个在这两层上的这个查询,我先把它做出来。
做出来之后怎么带对吧,做出来我们把这两个双线性差值的值合在一块儿,我就可以这个在这个层与层之间再做一次差值,然后然后这个差值就是就是说大家可以看到又不是水平,又不是数值,它是层与层之间的诶。
那我做了这个,这可不是第三这个这个这个不同的差值嘛,也就是说我总共做了三三步差值,对不对,然后也就是说这个呃双线性的,然后在上面再加一个这个线性差值,我们管它叫三线性差值哦,这里就是说我这个纹理。
这样一来我就可以呃计算离散的这个maple map层,不管它是整数还是还是浮点数,我都可以查他这个值是多少,那么现在大家可以想啊,在这个纹理的内部,我不管它是整数坐标还是非整数坐标。
我都可以这个双线性插值出来的一个平滑过渡的值,在层与层之间也可以说是也可以插值出来一些这个这个这个连续的值,那这样一来就没有任何死角了,对不对,对于任何的这个查询的区域。
然后我都可以这个呃通过三线性差值,然后做一次查询就可以得到这个区域,它所覆盖的这整个一个这个这个这个面积呃对吧,是这么一个意思呃,覆盖的这个这个这个面积内的平均啊,这个意思好,这就是三线性插值。
那么这里呢呃首先是这样啊,先给大家说一下,这个今天看来又没办法了,这个我们还有一块内容没说呢,然后这个我尽快我尽快啊,这么回事,这个三线性差值呢,它这个非常有用,这就是为什么在这个各种各样的这个游戏啊。
或者各种各样实时渲染中间的应用,它得到了一个非常非常广泛的应用,这个这就是这个这个因为呢因为他可以得到一个完全连续的一个表达,对吧,在这个层层与层之间和层内部都是连续的,没问题。
然后三线性差值这里面呢这个这个嗯嗯这个叫什么本身的开销呢,无非就是说这个呃做两次查询,然后做一次这个差值,所以说本身开销挺小,这就是为什么说这个现在游戏或者什么东西,默认都是有这么一项这个选择的。
然后呢大家可以在这个呃可以试一试打任何的游戏吧,然后都可以试着把这个呃这个差值给关掉,然后再打开对吧,然后比较一下效果对吧,然后呃那这里就先说到这儿,马上再给大家继续这个话题啊。
我们把3d应用差值就这么说完了好,那么三线性差值得到的结果是什么,那太漂亮了,对不对,就像这里大家可以看到哦,这里原本说是黑了一片对吧,这里黑的和红的有了一个过度了对吧,然后就是说这个在不同的区域。
比如这里黄的和绿的有一个过渡了,这里就是说不同的区域,它就确实有了一个这个不同的这个这个这个有一个连续变化的结果,当然大家会注意到柱子上有些问题啊,这是几何本身的问题,这个咱们暂时不说啊。
就是说这个就是基本上来说通过三线性差值,我就可以知道它在哪一层差呢,在某一个浮点型的连续的一个书上差好。
那这就是这个mp好,那么大家可以看到me map效果挺好的,可是me map是否真能完全解决问题,这是一个我们要思考的事情对吧,然后我们可以看一看这个,比如说我们认为哈。
如果一个像素我用这个512个这个这个采样点应该已经够了,那么咱们假设这个是一个准确的结果,就是说假设这个512倍的这个这个超采样,能够给我们准确的结果啊,也差不多,这如果是准确的。
那如果咱们看mile map,我们就会看到有区别什么呢,我们可以看大家可以看到这里发现mmap啊,不太对,mei map到了远处的地方,他会把所有的细节什么东西全部都给糊掉,大家会发现这么一个问题。
对不对,会发现这么一个一个一个一个情况,在远处出现了,这个我完完全全不应该糊掉的东西,然后这种我们就管它叫over ber,很简单模糊的过分了对吧,over不乐,然后为什么会出现这种情况对吧。
这就是我们要思考的问题,那么从什么地方可以来解解决这个问题呢,那就是说如果mmap是对的,那一定不会有这个问题,那他肯定哪儿不对,那不对,在哪儿,其实咱们一开始已经说过了对吧。
我说它首先它只能查询一个方块的区域内,然后然后就是正方形区域内它的这个范围查询它的平均值对吧,那那那如果不是,那就没办法对吧,然后它这个其他各种各样的近似涉及到它三线性差值本身,它也是近似差值嘛对吧。
毕竟不是说真正能算出来对吧,那咱们就先从这个方块的这个查询这个这个上面来说好吧,然后然后我们提到mmap会有这么一个问题,咱们马上再具体分析,但是有一个办法可以解决部分解决啊。
部分解决这个呃这个三线性差值所产生的问题,那么是用什么是什么办法来解决呢,这个东西叫做各项异性过滤,这个我相信大家这个要是打游戏打的多,估计也接触过对吧,这个各项异性过滤它的效果会比三线性差值要好。
然后再从这个例子上也可以明显的看出来对吧,远处的话已经明显可以看到细节了,不是完全糊掉的。
那么这是怎么回事呢,那咱们分析一下啊,就是说啊mmp map本身他做了一个什么事情,他做了这么一个事情,就是说啊给你一个原始的一张图,然后你把它长宽各缩小一半,缩小一半,缩小一半。
也就是说啊反映在这么一张图上,大家可以看到mile map计算的其实是这个对角线上的这么一些图片,然后呢就是有一些图就是说我这个长宽我不同的这个长宽比,做这个预计算诶,这个是弥补map没有的。
比如说像这里还是这么一个卫星的这个图啊,大家可以看到这个沿着这个水平方向,第一行大家可以看到这个这个图是这么回事,它的竖直方向没有发生这个长度变化,只是水平方向被压缩了一下。
哎然后这个每一行其实都是这么做的,大家看每一行都是水平方向,如果我看每一列的话,那就是每一列的话,它宽度都不变,它的高度会发生变化,也就是说它比这个mp map的结构要多了一些东西,多的是什么呢。
那么我这里问一个这个事情,就比如说啊在这这一幅图上,大家可以看到它已经被这个这个数值方面压缩的非常厉害了,那在这张图的一个像素上,如果我把它给回到这个这个原始的一张图上,就说这个图上的一张像素。
这个第三张图它的一个像素对应到原始图上是一个什么区域呢,大家可以想象得到是一个这个数值的拉伸了的区域对吧,也就是说是一个矩形的区域,然后也就是说通过我们这样一种方式的预计算。
我就可以查询任何一个被压扁了的图,任何一个位置我可以查到原始的对应到原始的图上的一个矩形的区域,而不用限制在一个正方形区域上,诶这样的话那效果就不错嗯。
那为什么会这样呢,是因为我们看这里这里像素上面的任何一,也就就是说唉屏幕上面有一个像素映射到这个纹理上,可不一定都是一个规律的形状,很有可能会出现这种超级斜着的这种这种气的啊,这些地方对不对。
那就非常不好对吧,那那这这种情况下,我要把它近似成一个框,那还得了,咱们把这个框给框起来,你会发现哦,那我可不是求了一个更大的区域的平均嘛,也就是说这就会造成over blog,对不对。
那也就是说如果我们引入了各项异性过滤的话,对于这种结果,对于这种基本长条形的这种这种问题就可以得到一个完美的解决,就是说这个各项异性过滤,允许我们对这个长条形的这种区域做一个快速的范围查询。
也不用限制在一个这个正方形区域内了,那自然得到的结果就会好很多,那么大家就会问了,那各项异性过滤,我对于这个生成的这这这些新的图啊,任意一个像素它都对应了一个矩形区域。
那倘若的我的我的查询范围查询真的特别坑,就像这样,它它它是一个斜着的一个区域,那你说你要拿一个这个矩形区域去框,它也不是特别好,对不对,也就是说各项异性过滤仍然没能解决问题对吧。
各各项异性过滤咱们咱们总结一下啊,解决了一部分问题,对于矩形的查询可以可以得到一个更准确的结果,比这个正方形的mmap差距要好,但是对于斜着的这种区域不行,没有办法。
那怎么办呢,人们就发明了一些这个另外的一些方法,这些这个给给大家举一个例子,这里叫做e w a这个过滤e wa过滤是什么意思呢,其实很简单,你有一个任意的不规则的形状,不规则的形状。
它都可以把它给拆成这个这个很多不同的原型去覆盖这个不规则形状,比如像这里它是一个这个这个这个一个椭圆吧,它可以把它拆成比如说三个不同的圆形去覆盖这个椭圆,然后每一次我就去查询一个圆形,然后我多次查询。
我自然就可以去覆盖这么一个这个不规则的形状,那当然可以,但是造成代价是什么呢,大家可以已经听出来了,对不对,多次查询嘛对吧,你查询肯定是要耗时的嘛对吧,所以说这个又一次大家体验到这个事情质量越好。
代价越大一定对,然后呢咱们回到刚才我说的这个各项异性过滤啥啊,各项异性过滤它本身生成了这些这个这个呃那么多其他的图啊,然后对于这个图来说,大家可以利用刚才mp map的分析方法,大家可以看到。
如果我要生成各项异性过滤的这个这个呃,那么些中间的这些这些图啊,压扁的这些图啊,然后总共的开销是原本的三倍,大家可以看到原本的这个开销是左上角嘛,现在这个总共的开销变成了原来的三倍。
大家对比一下mp map map map呢只是开销只是原本的1/3额外的开销啊,然后这就是这个代价对吧,然后当然了,各项异性过滤就是这种水平数值压扁的,它本身还有名字叫rap map生成的这个东西。
当然平常大家这个很少提这个概念,但是没有关系,就反正就是说这就是这个各项异性过滤的这个这个呃概念,当然这里多说一句,什么叫各项异性,各项异性就是说在不同的方向上,它的这个表现各不相同啊。
就是说我们原本认为这个这个矩形它的水平和数值上的表现完全相同,这种就叫各项同性,但是如果有同学硬要说,比如在各个方向上,它一个矩形它还是不一样的,对吧,呃确实是这样。
但是基本上还是我们认为呢是各项同性的,然后这个呢就是各项异性就是指这个意思,他可以考虑不同的所谓方向性,就这个意思好吧,也就是说通过这种方式,然后我们就可以把这个这个嗯最后的结果给给给做得更好好吧。
然后这一块就是整个的这个呃me map这块涉及的问题,然后呢我觉得唉呀好吧,这里这里要不这样吧,要不这样吧,这个纹理这块呢,我觉得我留到留到下节课再给大家说吧,然后就是说文里还有一些其他的这些应用。
然后这些应该花不了太多时间,然后这里在多说一句,给大家说完这个这个各项异性过滤吧,就更加异性过滤,大家如果打游戏的话,还会接触到一个概念多少x对吧,那其实意思就是说你计算多少层。
比如说这个这个2x各项异性过滤就基本上计算到这儿,就是只是方向上这个压缩了一次,你会看到这左上角的这么一个区域啊,呃这个区域我现在鼠标框的这个区域,左上角2x2的图的区域,然后如果说是4x呢。
它就是就是说在这个竖直方向上又压缩了一倍,压缩到这里会形成这水平方向上也是一样,生成这么一个区域,左上角啊,然后这个8x 16 x一样,大家会发现这个随着这多少x逐渐往上增加。
这个最后的结果会逐渐收敛到总存储的三倍,也就是说各项异性过滤它的存储量,其实来说你开多少x这个其实关系不大,这也就是为什么说这个用应用各项异性过滤,只要你的显卡显存足够,这里和计算力基本没有关系啊。
就是显存足够的话,这个尽量都开各项异性过滤,开到最高就好了,这个对这个对对对,就比如打游戏,它们的性能几乎不会有任何影响啊,他这个只是对显存的这个开销有一点这个这个要求而已,其实也没有多少对吧。
多那么一点点好,那那这里呢就是就是说这个这个啊差不多就到这儿吧,今天然后咱们这个下节课,我们再把这个剩下的这个纹理的高级应用说明白,然后再有空在这个继续说这个啊这个这个这个这个啊阴影。
如果说嗯不这么安排的话,那咱们就开始进行下一个环节了,就是几何了,也就是说到此为止啊,咱们可以简单做一个总结,到目前为止,除了阴影这块的技术没有说以外,整个的光栅化的一个过程,基本上咱们都已经涵盖到了。
就是说整个硬件上在做什么,然后就是说同行,现在现在大家这个在这个编程这个这个这个啊实时的这个渲染的项目,然后再做哪些内容,基本上来说就都在这儿了好吧,然后咱们课程总共大家这会注意到是四块。
然后咱们很快就要进入第二话,开始说几何好吧,然后那这个呃今天就说到这儿,这个背后呢就给大家解释了好多这个这个这个背后的原理,但是这应该不需要说这么细啊,大家这个能理解,那是最好理解不了,没有什么关系。
好吧啊,这个这个这个那就那我们今天就说到这儿,然后如果大家有什么其他问题的话,这个我看到大家确实有问题啊,今天可能不太来得及,然后这个呃有问题大家就欢迎到这个bbs上多问好吧,我有时间我也看一下。
然后我也这个督促一下助教同学们多给大家回答问题,好,那咱们今天就说到这儿。
然后我们把时间在这个教会给技术秘书同学,然后各位同学感谢大家支持。
咱们这个下节课再见啊。