11.物理系统:高级应用 | GAMES104-现代游戏引擎:从入门到实践 - P1:GAMES104_Lecture11 - GAMES-Webinar - BV1Ya411j7ds
Hello,大家好,我是广西,欢迎大家回到games104,现代游戏引擎的理论与实践,又到了一周一次和大家见面的时候了,我们这一节课讲完之后,后面又可以休息一周,想到这一点的话。
整个课课程组就特别的开心,因为我每一周准备课程的时候,大家都非常的那个压力很大,那么我们压力很大,我怀疑我们同学们现在压力也很大,因为现在是不是考试季啊,我看到好多小伙伴在那个那个在弹幕里面说。
这个考试考的怎么样,还有我们好多同学现在毕业,我觉得大家应该都是在为了自己的未来在努力,所以一起加油吧,然后呢在开始我们今天的课程之前的话呢,我先那个回答一下来自于我们社区的一些问题,那其实挺好玩的。
真的每次我们的课程视频上上B站之后,那个后面的那个回复,就会有很多很有意思的东西,比如说有同学在问我们说,在哪可以问到我们游戏的那个,关于回答各种各样的问题啊,那么其实的话呢就是说在GITHUB上的话。
还是要有discussion panel,那大家可以在里面的话,自由的去交流各种各样对小引擎的看法,或者我们关于引擎的问题,然后呢我们也拉了各种各样的微信群,然后呢我们有好几个微信群了。
大家可以加到我们的微信群里面,这个微信群的话呢,在我们的课程官网上大家也能找到,因为在这些群里面呀,在这个就是群里面,我们的那个课程组的小伙伴都在里面,就是大家有什么问题的话,艾特他们。
他们会尽可能就最快的速度,会转给我们这个课程组,还有各位技术的小伙伴,然后给大家尽可能尽快的回答,那么还有同学就问我们说,诶这个小引擎什么时候集成这个物理引擎,这个问题问的非常的到到到到位啊。
因为其实我们这一趴是讲物理嘛,结果我们的小引擎没有物理引擎,所以呢我们在这个明天的更新中,我们会把物理引擎集成进去,这是一个我认为这还是很重大,很开心的一件事情,然后呢还有同学问我们说。
希望我们提供更多的参考资料,比如说我们看的论文哪,看的这些这个代码这些讲座啊,这个问题提的我觉得这个需求提的特别的好,我们自己也在检讨,说我们只顾去准备课程啊,其实我自己有一个文件夹。
里面快有100多篇论文了吧,就是因为在准备课课程的时候,我们的小伙伴就去找各种各样的资料,然后我还有自己要去看这些资料,那么所以呢在今天的课程中,我们专门在课件中留了大概4~5页,就把我们这一节课件的。
所有的参考资料都放上去了,所以等同小伙伴们下载这个这节课程的,PDF的时候,就可以找到所有的论文和资料啊,非常谢谢小伙伴们给我的反馈啊,因为真的大家不提的话,我们完全意识不到这个需求。
那么还有小伙伴问我们说,诶我每次听你们讲课程,然后的话呢就是说只是讲到一个一个的知识点,但是我不知道这一个个知识点是用什么道理,把它串起来的,我我需要把它编理解成一个故事,一个有逻辑的故事。
才能方便我能理解这些知识点,其实这个问题问的其实蛮难的,因为我们在准备课程的时候呢,是花了很多时间去想我们讲什么,那个不讲什么,包括我们讲的顺序,先讲什么,后讲什么,最简单的去解释一下。
就是说呃在整个课程准备过程中的话呢,我们一直在模拟一件事情,就是说假设我来需要写一个哎,能够做得出来游戏的这样一个游戏引擎啊,因为游戏引擎的知识点特别多,但是我们只挑说我做出一个基本的这样的一个。
A功能齐全的游戏,我需要知道哪些知识,然后呢我们就按照这个flow,把整个知识点串到一起去了,然后呢这里面的话每个知识点的话,因为我们在课程中的话也在不断的调整,就是说尽量的避免讲到非常低调的一些算法。
因为非常低调的算法,它讲解来是特别的细,一个个公式的推导,所以其实我们花了很多的时间,干一件什么事情呢,就是说把每一个知识点,我们提取它最难懂或者最核心的那一个点,我把那个点点通,因为我们的假设就是说。
如果你真的要去实现这个东西的时候,你一定要去看他的原文,看看原文的时候,你会发现一上来很容易很容易看不明白,就像我上次讲课,说有同学看小引擎的时候看我们耀对吧,我就说你知道他的要点之后,你多看几遍。
可能有一下子你突然就明白了,那这个东西你就get到了,所以呢课程上我们讲什么呢,我们就讲那个像衣服的领子一样,我就把那个领子那个地方把它拎出来,像今天我们要讲一个比较复杂的技术。
像PPT其实它非常的复杂,而且数学上也很抽象,我其实我们是花了很久,我们写了大概有三四十页的PPT,然后最后凝凝练起来就这十页左右,但是实验的话呢,我们自己认为是把它最核心的思想给讲出来了。
那么还有最后一个的话,就同学们问我们说诶,有同学问我这个很专业的问题,他就说哎我用了一个模拟擎,然后这个引擎在比如说移动端啊,PC上console上跑出来的结果都是不一样的,那么他想很想知道。
说真实的这个游戏引擎里面的物理引擎,它到底在设备上怎么运行的,其实这个问题问的就很很有意思了,因为我们上一节课里面讲了一个概念,叫deterministic,实际上这个deterministic。
就是同学的这个问题的一个答案,就是说其实就算是现在商业级的游戏引擎,它都没有办法保证在不同的硬件平台上,它跑出的结果是一样的,比如说因为你的iteration就迭代的不长。
你的这个浮点数的精精度它都会有很大的差别,所以的话呢就是同一个引擎写出来的产品,在移动端就是我们的那个IPAD,那个IPHONE上面,比如说在我们的PC上面,在我们的那个XBOX上面跑出来的。
演算出来的结果应该是不一样的,这个地方的话就是说我们需要做大量的处理,才能保证这个逻辑的一致性,所以呢这些就是对我们社区同学们的问题,的一个简要的回答,好那么在开讲课之前,第二件事情。
也是这个也是给大家告诉一个好消息,就是明天5月31号,我们的最新的版本0。06版本也要上线了,那这个版本第一个呢就是刚才我已经剧透了,我认为是一个big move,就是说我们的joy我们接入了物理引擎。
我们进入了一个比较简单轻量的物理引擎,叫joy,这个引擎虽然是很简单很清淡,我们挑了半天,我们觉得他足够的干净,足够的好理解,那么大家千万不要小看这个引擎啊,你们知道有一款大作就是这个啊。
horizon就地平线,他用的就是这个物理引擎,所以你看看我们虽然写的是个小引擎,但我们跟3A大作用的是同一个物理引擎,大家是不是觉得很有牌面对吧,那么接下来的话呢这个是我个人的心愿,就是一我。
我我上次看过我们小引擎的第一版的时候,我我就我自己苦恼了半天,我说哎呀,我们的这个rendering那一层做的太抽象了,然后就是绕来绕去绕来绕去,然后我们的课程组的小伙伴。
这将近有花了两到三个星期的时间,认认真真的把我们的小引擎的rendering那一层,把它给清理的尽可能的干净了,那么那个后面的话呢,其实最新的代码我也没看到,但是的话呢就是等这个明天上线之后。
我跟大家一起来看,然后我们看这个小引擎的这个新的代码,是不是更简单更好懂了,那么同时的话呢我们还修了一些bug,也非常感谢,就是我们社区的小伙伴,还有我们课程组的小伙伴一起做了满足的工作。
其实在最近的这一个多月的话,其实我们课程组是花了蛮多时间去进行这种,就是我们的代码的优化的,因为我们现在因为一边在准备课程,其实没有时间去拍那个就是啊小引擎的讲解啊,或者准备这些更多的资料。
所以我们就会对自己提个要求,就是尽可能的让小引擎就是让大家好懂,那这里面的话呢跟大家说一点,就是说我们大概把小引擎做到一个,功能基本齐全,然后的话呢代码足够清晰的时候,我们对它的更新会暂时告一。
就是暂时缓一缓,因为我们不想把这个系统做的过于复杂,因为好多同学都是第一次接触,这么复杂的这个系统,所以如果我们功能堆得太多,搞得过于复杂的话,又会像我们一开始犯的错误样。
就让同学们学习和进入起来就很难,所以也非常感谢就是大家给我们的反馈,因为没有大家的反馈的话,我们有的时候自己做错了都不知道,然后现在我们的课程开了将近两三个月了,大家给了我们很多反馈之后。
我们慢慢慢慢的就课程也好呀,还有小引擎也好,市区也好,我们有点感觉了,知道怎么跟大家去互动啊,好,那最后就是正式的宣布,他在我们的这个小引擎的命名,这个活动终于告一段落了,那其实经过大家审慎的投票。
那目前看到我们这个得票第一的名字是PICO,对吧,这个单词其实我也不知道,你看我我在美国呆了那么多年,居然这个单词我也不知道,后来那个课程组告诉我说哦,这个叫短笛的意思,就代表我们的引擎短小精悍。
然后我觉得这个名字挺可爱的,比如说PICO,Pico low low low low low,我可以搭很多漏,而且更好的一点是,他可以重用我们以前设计的那个P的,那个那个icon。
我不知道那个P的icon会不会给别人撞啊,反正anyway就是既然是落子无悔了,社区的同学们已经选了这个名字,我管它是什么名字,我们就用了吧,那那就是说啊,如果大家没有反对的意见的话。
那我们就把我们的小引擎升级成PICO,但是可能有些东西在那个重命名啊,特别是代码重命名可能需要花一点时间,我不知道GITHUB上能不能remake啊,说不定不能ren anyway。
就是说啊至少我们有一个名字了,这是根news好,这些就是今天和大家,那个就是我们我们一些反馈,那我们接下来就开始我们今天正式的课程,就是物理引擎的第2part,今天呢讲的是物理引擎的应用。
其实呢也是很多很高级的一些应用,就是物理引擎到底怎么样子,在游戏的这个场景里面实战起来,那么上一节课呢,我们讲了物理引擎的很基础的一些概念对吧,告诉大家了什么,就是说哎read the body。
动力学是什么,怎么怎么做的,我们知道CLICHINTECTION怎么算呢对吧,其实到这个地方是有点高能的,我知道那像SHRESOLUTION的话呢,实际上我只是点了一下,根本没有展开那个算法。
那个算法其实非常的dirty,有很多的细节在里面,那么像SQUIRY啊,像其他的一些物理的东西的话呢,我们都点到了,那其实最核心的就是大家知道,就是说那个牛顿力学simulation的基础算法。
几个欧拉的显那个显影视积分对吧,欧拉的这个这个这个就是说显示积分,欧拉的半隐式积分,这些东西都是非常重要的一些概念,包括那个刚体动力学的旋转对吧,我们还记得例句对吧,我们知道它的转动惯量。
知道他的这个角角动量,那个动量这些概念,这些概念其实非常的重要,那么我们有了这些基础的概念,我们有了这些基础的server之后,实际上接下来的话呢我们就看怎么去应用它,所以今天的话呢给大家讲一些。
我们的应用的场景,那首先第一趴呢就是这个character controller,就在这个物理世界里面,我们的角色到底是怎么动的,大家会觉得很简单,角色不是就是我自己动一动就可以了嘛对吧。
然后但是问题是你是在一个物理的世界里面,你的运动和这个世界到底什么关系呢,那首先大家想到动的话,我们首先想到的是什么呢,哎dynamic object,动态物体,对不对。
我这个我我在physical engine里面有动态的东西,那我就放个动态的东西嘛,但事实上的话呢,character control它不是这个概念。
就是说如果我放了一个dynamic object的话呢,它实际上是有它的质量,它有它的摩擦力,虽然他非常的真实,但是呢它和人的控制的直觉,是有很大的不一样的,就是你站在地上。
你不会意识到说我在地面上是有是有摩擦力的,你会觉得我我想站哪,我就站在那儿对吧,所以在我的认知世界里面,我们认为我们和地面的摩擦力几乎是无限的,而且呢我们也不认为我们自己是个弹性体对吧。
我们认为我永远是紧贴着地面,而且呢我们的加速转向,甚至我希望有teleport,teleport的意思是什么呢,我是一个魔法,打个响,指从A点到B点。
所以其实呢character control它是一个反物理系统,而不是一个真实的物理系统,所以还记得上一节课我们讲的就是说actor,有一种叫做叫做topic actor,对不对。
那condemic action的话呢,实际上character control,就是他一个很典型的一个应用,在这里面它是反物理的,你看到这里面那个小绿人站在这,无论什么东西撞它,它都会把它弹开。
这就是我们的character control好,那么为什么会有这个东西呢,其实最早啊,其实早期的游戏没有真正的物理引擎,那我们作为game developer,我发现一件事情。
就是说我们如何去让这个游戏里面角色的行为,符合我的认知的时候,其实我写了大量的hack的代码,比如说多少度坡你能爬的上去啊,我当我开始起跑的时候,我的加速度应该什么样子,我停下来应该是一种感觉啊。
我撞到墙之后,这个人应该是什么反应啊,这些大家会觉得诶这不是很简单吗,就比如在真实世界里面,我们和世界的交互就是这样的,但是呢在游戏世界里,你会发现这些东西,每一个细节你都会去需要单独处理。
在这里面呢我就不展开,待会儿我给大家讲CTRL的时候,你会发现讲完一个最简单的control的概念,但是你会发现有很多种特殊的情况需要处理,这些情况你不处理的话,当你做成一个游戏的时候。
你玩起来就会觉得很奇怪,所以这节课这一趴的话呢,讲的是一个非常时尚的,只要你作为一个游戏,只要游戏里没有主角的话,你基本上就需要知道这些概念,那么好,首先我们讲这个control怎么去构建。
实际上也比较简单对吧,我们就用一个刚才讲的CONNEC的一个actor,我构建了一个一个一个东西,把我自己包起来,那一般做什么形状呢,我们知道可以用一个box,我们也可以用一个图包对吧。
但实际上呢至少在我看到很多产品里面,大家用的比较多的是什么,是个胶囊诶,这个胶囊就很有意思了,你仔细看那个胶囊啊,它有两层,一层是外面一点的,稍微肥那么一点,一层呢是小一点的,小一点点的干什么事情呢。
就是我真的跟别人去撞了,就是我撞到,那而那个外面那一圈是什么呢,你可以认为它是一层保护膜,它防止你去离别人的东西太近,当你高速移动的时候对吧,如果我那个胶囊一不小心就卡进去了,我就卡住了,这是一个用处。
其实还有一个用处是什么呢,就是如果你想想看我们的游戏,就是大家如果学过图形学的话,知道我们的相机有个什么东西叫做镜平面对吧,那么当我做第一人称射击的时候,如果我的角色撞了离那个平面太近的时候。
是不是会出现你看到墙背后的东西的,这样的一个bug,我不知道大家有没有玩早期的一些游戏啊,你经常会发现就当你的脸贴墙足够近的时候,你看到墙背后的东西了,实际上这一层保护呢,它也是防止就是角色离墙太近。
这样的话很多时候相机也会产生的bug,但相机其实更复杂了,有时候我们相机会做一些叫相机碰撞,那么我有了这个东西之后,这个角色可以在环境里移动了,对不对,但实际上它一个比较复杂的东西是什么呢。
就是我在运动中,我当前的位置是X对吧,我变成X加一的时候,哎我实际上可能被一个东西撞着,撞住之后呢,我们天然的想法是阻挡就停在那儿,对不对,但实际上人人的perception。
或者我们人的天然认知是什么,你应该沿着墙去划一下,这个时候你要去写一个叫sliding的一个算法,在这里面你看这个角色他已经走到墙上的人,你会发现他虽然脚往前迈,但整个人横移。
如果你们现在玩几乎所有的这个游戏的话,无论是3A还是一般的游戏,基本上都会做这个系统,所以说大家如果实现自己的character controller的话,诶这是你必须要写的一个东西。
我记得我在第一趴讲课那个小引擎的时候,我就想哎我们一开始没有做物理,所以我们的人到了墙上的时候,它还不能sliding,其实就是这个功能我们还没有实现,那么第二个的话呢,就是说其实在真实的环境中。
我没有办法保证整个游戏环境,它都是那个连续的,我们会最经常遇到的东西是什么呢,是台阶,那么我们就要让这个角色他不会,比如说有一个几厘米高的一个障碍物,我一个半2米高的人走不过去,这是很不科学的,对不对。
所以呢stepping,其实也是一个非常重要的一个角色系统,那这个东西怎么做的呢,其实就是当我每一次每一帧,我要移动这个角色的时候,我就会尝试把这个controller诶,往高台那么一点点往前走。
那这里面就会产生一些很有意思的bug了,我不知道大家以前在游戏游戏里没有遇到,就是如果设计师没有设计好,他那个屋顶设计的稍微矮那么一点点的话,我们就会把角色卡进去,我记得我以前在做这个halo的时候。
我刚去的时候,我的设计师就会告诉我们的设计师,就会告诉我说,我们在做所有的门的时候,都比正常人要通过的门要大大一点,大大概大概30%到40左右吧,他就为了防止这个这个角色被卡在,那个门的入口的地方了。
所以其实这个地方的话就是刚才我刚才讲的,这里面有很多的这个HARDCODE,但这个东西非常的重要,因为你其实当我们在做一个游戏的时候,我们是希望用户的体验非常的自然和流畅。
所以out stepping的话呢,也是一个非常重要的一个系统,一个一个也不叫系统,就是非常重要的一个feature,你必须在你的control里面去实现,还有一个是什么呢,就是说哎我们看到一个斜坡。
我们下意识的反应是什么,我要冲上去,所以呢当你去设计这个control的时候,一般我们都会设设定一个叫做你的MAXIPHONE的,这个这个slope的角度,就是当你的角,当这个slope。
就是这个这个坡度大于某个角的时候,他就开始滑了,哎注意啊,他不是上不去,它是你可以跳上去冲上去,它还给它滑下来,所以这里面其实是蛮有点就是很有意思,就是说他又有那么一点点物理的感觉,它又不完全物理。
如果我们在动画系统做的更加的精细的话,大家还记得上次我们在讲动画系统讲课,说动画系统有个叫ASM对吧,就animation machine,那么大家仔细想想,一个人如果冲上土坡的时候。
他的那个脚的动作其实做的精细的话,不应该是用走路的动作,对不对,他有一种尝试往上去攀岩,然后呢当它往下滑步的时候,他要尝试去那个就踹两下,保证自己不要这个这个这个摔下来,所以其实啊,大家如果想表现一个。
非常活灵活现的一个人类角色的话,你会发现无论是这个物理系统还是动画系统,有很多的细节在做,所以呢这个slope也是一个非常重要的设置,如果电动用不设置,会发生什么情况呢,你会发现这个人会飞檐走壁了。
在游戏世界里面,它就可以沿着那个沿着一个你看起来80度,90度的悬崖,他就一路就蹭上去了,我相信这个东西的话呢,在其实在就算是3A游戏里面,也是个非常常见的一个bug。
我知道很多的B站上的视频都是给你展示说,如何利用这个物理的bug,沿着墙一路就跑到地图边界之外对吧,或者爬到一个极高的地方,那个地方本来我们都不应该爬得上去的,实际上这也说明就是说。
其实你想做好一个好的control的话,事实上还是蛮复杂的,所以当我们去写我们的这个小的游戏的时候,我们的引擎一定要提供,这个就是slope limit的设置的功能好。
那其实呢这里面还有一个很重要的细节,就是说这不叫细节,其实我认为也是很重要的,一个一个一个在我们实现character controller,要注意的东西,这个地方其实我自己当年都写出很多的bug。
就是说当角色他有很多姿态,比如说大家如果玩一个射击游戏,我们的角色有多少姿态,比如说站着射击,对不对,还有什么呢,还有我半蹲着设计对吧,还有什么,还有最猥琐的,比如说我要当一个这个这个狙击手的话对吧。
我们叫做老鹰对吧,我们就趴在地上,我们就那个时候你的controller,它其实形状是要发生变化的,否则的话它会就会出现叫做诶,你明明觉得我能通过,但是你就是过不去的情况。
那这个时候呢有一个很重要的实施方式,就是比如说一个人在通过管道的时候,他蹲在那儿对吧,他这时候突然发出来一个站起来的指令,那个时候你千万不能一上来就把他的control更新了,因为你一旦更新之后。
物理他很多运算实际上它是瞬间的嘛,那你在做下一步迭代的时候,他会认为你的controller就已经卡在这个管子的,比如像刚才那个tunnel,那个隧道的不上不下的地方,你就动不了,你就说你收也收不回来。
你往前往后,他的认为物理计算机都认为你被卡死了,其实在很多的游戏中,我们会出现角色做一些动作被卡死的情况,其实就是在这些时序上出了问题,所以character controller。
他讲的所有的东西都非常的简单,但是的话呢如果你不仔细的去做它,当你面对一个非常复杂的这个,游戏的environment的时候,你就会产生无数的bug,这也就是为什么游戏QA压力很大,也是个原因。
就是因为它实际上基础原理讲起来都非常简单,但是的话呢在游戏的世界里面,各种各样的情况非常的多,那接下来再讲一个这个大家啊,这个还比较简单,就是说其实character controller呢。
它实际上和环境还是有互动的,比如说我们碰到那种各种dynamic的物体的话,我们实际上是把它推开,那怎么推开呢,其实很简单,就是character controln呢,一般来讲如果你用的是物理引擎。
它会告诉你一些回调函数,说哎不好意思,我抓了某某某,这个时候呢你可以根据自己的速度,根据自己的这个字,你觉得我的重量输出去一个冲量,这个冲量的话呢,apply到这个物体上去,那其他的物体就能被推动。
这个其实是我跟环境的互动,但这里面环境互动一个,我认为比较容易出问题的地方是什么,就是如果你的controller是站在一个动的东西上,因为刚才我们所有的demo它的环境都是静态的,对不对。
但如果环境本身是动的呢,比如说一个platform,大家想想看,我们在一个物理的解散环境里面,我放个control下面的平台,在动的时候,我们好像没有什么约束约束,他不会维持自己的状态。
所以说如果你不去做特殊处理的话,那个角色他就会当那个台子冻掉之后,诶这个角色就掉下来了,其实我以前在做很多游戏,比如说我们做一个巨大的飞船对吧,那个飞船的话他要往前飞或者往上下飞,其实上下也是一样的。
就是上下的时候呢,你会觉得诶动的时候,上面的这个角色因为物理的约束它会比较顶,对不对,但是你会发现它这个物理的结算,它是有一个就一帧左右的这样的一个波动的,你会发现那个角色就会一直这样,当当当当当。
就是说台子深一点啊,他被顶上来,台子上来他就被顶上来,它之间总是有一帧的这种误差,所以实际上像这种情况下,我们要用recast,就是我们要检测说你到底是站在哪一个平台,那个平台如果是动的话。
大概率也是个物体好,你说我现在就站在这个物体上了,那这个时候呢,我们一般就会把它两个逻辑上绑在一起,所以除非你有更多的就你有新的移动的输出,那我就会是head cut code。
保证这个control和这个被就是你step on的这个物体的,相对关系不会发生变化,所以这个地方是个完全的hack,但是的话呢这件事情对物理引擎其实蛮重要的,当然有同学会讲说这个好耶,听上去很粗暴啊。
比如说我的一个台子突然加速对吧,我这个人好像站立不稳,会摔倒,甚至会掉下来,这种情况也是合理的,你说的没错,这种情况确实是合理的,但是呢如果我们要做到这种精细度的话呢,我们需要专门的去写,专门的去处理。
所以其实我觉得对control这个东西的总结是什么呢,就是它没有什么特别难的技术,但是呢它有无数的小细节,而且呢每个小细节你都是通过各种各样,你自己认为这个角色该怎么运动的一个处理。
所以我认为它是cut code,但是呢你会发现他又和用户的这种感受,是直接相关的,所以一个游戏,比如说我们经常讲的它的操作感对吧,它的移动感其实就已经被定制在这儿,比如说你去玩一个魂系列游戏对吧。
那你们角色的移动,和你玩一个像那个荒野大镖客,那种很写实的游戏,那个角色的移动和环境的感觉对吧,和你玩一个像SUPERMARIA或者sonic,这种非常快速的游戏,那种角色的感觉是完全不一样的。
而这种difference的话呢,其实有很大一部分是来自于我们在control上的,实现了不同,所以当我们做个引擎的时候呢,我们需要把这些接口都开放给我们的开发者。
让他们来去TK他自己想要的这个角色的style,所以这是control,这也是我们真正用起来,物理世界的这个第一趴好,那么第2part是什么,也是大家经常会遇到的东西,就是RAGDO。
翻译成中文叫什么叫布娃娃系统对吧,我一直觉得这个名字翻译的特别的萌,就是让我觉得啊,我我总是我脑子中,总是想象一个这个五颜六色的,彩色的一个布娃娃,然后就在这个游戏室里搬来搬去对吧。
但anyway这个没关系,这个反正我们知道RAGDOLL是什么就可以了,这只是我刚刚学这个概念的时候,我脑子里出现了一个很奇怪的幻想,那这个RT系统啊,其实对物理引擎对这个游戏世界非常的重要,为什么呢。
因为其实我们很多动画都是假设环境是预定的,但真实的在游戏的environment里面的话呢,它的环境是很复杂的,那这时候你会发现说,如果我只是播放动画的话,这个角色他的行为。
它实际上跟环境是没有一个互动关系,就像这个face里面,就是说假设我们做了一个就是啊2assassinate,就是说刺杀的这样的一个动画组,一般来讲这种动画呢是是双人动画,就是说两个人在同时播一个动画。
当我的攻击者的动画播完没关系,他站在那儿对吧,但是我被攻击者,他被assassin玩,就是被刺杀完之后呢,他应该会失去意识,这个时候他如果只是播放他的,这个就是被机动画的最后一帧的话。
当你在一个悬崖边或者在一个斜坡上的话,他整个人就僵在那儿,就会如果这个斜坡啊,这个情况会更糟糕,你会发现他整个人斜插在那个那个坡上,感觉非常的违和,而这个时候你就需要RAGDOLL系统接管。
让这个人像真的一个失去意识的肢体一样,自己就摔下去了,那这样看上去很真实,讲解一下我们的最右边的这个动图,大家看到的东西,那么瑞克多怎么做呢,其实大家学完了动画那一趴。
rock door其实也并不是特别难理解,就是说哦那我明白了,我不是有很多的join吗,join之间那个有很多的骨骼对吧,那好我呢就是把这些关键性的joint。
用一个大的这个ragile body把它连起来,注意啊,这里面比如说我一个角色身上的骨骼,可能有三四十个,甚至是七八十个,但是呢我们因为RAGDOLL的做的时候呢,我要让它的计算不要过度复杂。
所以rog do一般不会太多,最多也就十几个吧,也就这么多了,所以呢它基本上是一个比较模糊的,这样的一个表达关系,就这里面的话蓝色的区域就是大家看到的,就是说一个个的RT body是最右边的话。
那一个蓝色区域,那个红色的点就是我们选中挂RAGDOLL,就是其实我们一般用两个joint之间连了一个,就是reheal body,看这些register body通过那些join连在一起的话。
诶就是我们的这个那个RAGDOLL的整个的核心,计算的这个物理对象,那么在这里面的话呢,其实哎我们复习一下,在上一节课应该是上上节课讲动画技术的时候,我们就讲到就是说joint每个joint啊。
它实际上是有一个constrained,那为什么有constrained,这符合人体的解剖学原理对吧,比如说像我们的手,我们是只能这样运动,这是HG对吧,但是呢实际上我们好像还可以这样移动对吧。
这个这个移动好像是用这块的技术,还是谷歌,Anyway,就是说其实我们每一个joint它的类型,它的自由度实际上并不是完全的六自由度,实际上很多时候连三自由度都达不到,它是严格的被约束住的。
那这件事情呢对于rua do来讲解非常的重要,因为动画师啊,他去首K的时候,他脑子中是有一个人体的动力学意识的,他不会乱做的对吧,但是你当你把这东西交给我们的,物理引擎的时候,物理琴说我才不知道呢。
你如果告诉我说这只是一群被关节连,就被一些胶链连接在一起的这些沙袋的话,那我可以给你冻出各种很妖娆的姿势出来,那这里面就有一个example,你们可以看到就是说,当我们用一个点拎着一个角色的时候。
左边的这个他是设置了正确的,符合人体解剖学的join,你看到他的他这个动作看上去还是比较自然,Huali,对不对,右边那个就是OK你们都是链接连在一起了,你看这个动作看上去就比较妖娆了,对不对。
如果大家如果回想一下,很早期的一些低成本的游戏的时候,你们会经常看到这种很有趣的这个人体的行为,不过说实话我个人还是蛮喜欢这个设计的,因为这让我想起了一个我很喜欢玩的游戏,大家能回想起来吗。
人类一败涂地对吧,他那个joy就是很灵活的把joy设置了一遍,结果让我得到了一种前所未有的一种喜感,但anyway,但是我们今天讲的是正经的啊,我们讲的是正经的3A游戏的这个jolt怎么做。
所以呢咱们就得学一些正经的这个joint,怎么去加他的约束,那么其实join的约束呢,大家也不要特别担心,实际上在现在的这个所有的DCC工具里面,以及设计设置rock豆的每个join的时候呢。
它实际上把全部的六个自由度全部开放给你了,但是呢你可以在里面通过约束的方式实现,就是你各种想要的说我,我限制他只能做这个轴向的旋转,或者只能做HG的这样的一个一个翻转,或者像一个那个。
就是比如说像那个那个那个什么B的那种方式,只能去旋转,其实实际上的话呢,就是他现在的很多设置都是全部开放给你,你自己来约束它,但这个东西的话呢,实际上就是在我们真实的这个游戏引擎里面。
特别是我们这些joint的约束,我们尽量不会让所有的美术同学去做,因为很多时候对他们来讲太抽象了,我们一般会交给谁呢,大家可能听说过这个工种叫做技术美术工种,这帮都是一个又懂比较懂技术。
同时呢在美术方面经验也比较比较,那个就是啊比较久的同学,它能够细条,根据我们对人体结构的理解,细条每一个rag dog join的约束,那这个时候其实调的好啊,调得不好,其实差别还是挺大的。
这里面就有个例子,其实无论是左边右边啊,这两个约束条的都还OK,但是呢当你细看的时候,你会发现如果调的不够准的话,这个人在地上就会有各种各样很奇怪的东西,就是要么这个胳膊就钻到地下去了。
要么就这个人的姿态看着非常的不能贴地吧,我们就不能贴地,所以说呢其实rag doll的话呢,一般来讲你设定好绑定好这些joint的约束,做好之后呢,在整个游戏生命周期里面,我们一般是不会动它的。
就是把它放在那儿了,好那这里面其实就讲一个很有意思的事情啊,就是说大家刚才看的就是RAGDOLL,实际上我们大概只有,比如说十根不到的这个这个register body对吧,去动我整个body。
当我身体上有几十根的这种骨骼,那我因为我的skinny animation,是基于我的skeleton去做的,对不对,所以其实这里面还有一部反向的映射,就是说我怎么把布克多的这个动作。
映射到我的skeleton上去,大家还记得我们在上一节课讲animation的时候,我们曾经讲了一个概念,我不知道大家还记不记得,叫做animation retargeting。
就是说我把两个骨架不同的动画互相映射,大家想想看,其实我从一个reactor算出来的结果,反向的去驱动一个skeleton的话,是不是一个animation retargeting的问题。
其实他用的思路就是这样一个思路,就比如说我们去看人体这个这个角色身上,完整的skeleton里面的骨骼的话,有些骨骼呢实际上是和RAGDOLL完全重合的,我们叫做active jolt对吧。
他就是参与了我的整个actor的那个那个,RAGDOLL的这个运算,还有一些是什么呢,就是是在我最后一根那个RKO的那个,那个骨骼之外往外延伸的,比如说我们用rock do做到这个手的胳膊这个地方。
那手掌之外的这些骨骼,像这些骨骼,你原来是什么pose,我就放在什么的,我就不动你了,反正就是你这个动了,我就跟着动对吧,我就这些这些这些东西叫什么呢,我们叫做leaf joints。
那就继续进行延伸就好了,但是呢比较麻烦的是什么呢,诶在两个就是在一个就是那个RAGDOLL,richard body里面的话呢,它中间还有很多跟过渡性骨骼,大家还记得我们在讲那个animation。
RETARGETING的时候,其实我们有很多方法对吧,就是说诶我可以根据你的动作,我把这个动画呢这个这个pose,这两个pose之间一路的差值过去,然后均匀地分散到各个谷歌上去,实际上在这个地方的话。
那么ary targeting,就是一个非常重要的这个应用场景,所以中间那些joint我们叫做intermedia joint,那么它的pose实际上是同前后两根REACD的。
那个pose之间的差值出来的,这个方法的话呢,就能够把整个skeleton由rad来驱动,所以这个就大家刚才看到所有的demo,他就是用这个体系做的,那么RAGDO呢在真实的引擎实现中啊。
有一个细节就是说,其实呢他不可能永远是rock door的,我们看到的角色大部分都是什么呢,都是动画驱动的,所以它从动画到rock dog之间是有一个过渡的,大家仔细看一下这个case里面。
其实他前面可能百分之就是之前那个动画,大概播到70%到80的时候,诶我们一般不会到最后一帧,我们说哦这个人已经这个失去这个角色,已经失去知觉了,哎我们开始慢慢慢慢的可能到最后一帧。
最后一帧前把整个动画全部切到RAGDOLL,所以刚才你发现就当这个骨骼变成红色的时候,就是我们开始把整个运算交给了物理运算,那么这里面其实就引入了一个,非常有意思的概念。
就是动画和物理仿真之间的边界在哪里,其实这也是现代游戏引擎啊,特别注重的一些一个实现的一个细节,这个细节的话直接影响了你的角色活灵活现。
所以这里面的话呢,今天我给大家就点一个概念,就是power record,就是说,实际上刚才像刚才那个刺杀那个例子里面,其实在RAGDOLL和animation,之间有一个很明显的分界线,对不对。
但实际上在我们的现代游戏中啊,很多时候我们是把动画和物理混合在一起用了,为什么呢,因为举荐里面的一个例子,就这个主角他抱着一个小女生,这个小女生晕倒了,那么这个小女生晕倒呢,如果我完全的交给物理去做。
大家想想看小女生晕倒,他是不是那个没有意思的对吧,当你移动的时候呢,这个小女生的手就开始各种甩,但是你会发现他甩的特别像,很很不真实,因为那时候是个小女生,只是昏倒了。
所以你看这个中间那个结果看上去就很奇怪,那么如果呢我用二,我要我让那个artist,去专门做一个小女生的这样的一个动画,那个动画里面的话呢,你会发现就是说他的pattern是非常repeat的。
就是说虽然你做的很有表现力,很符合那个就是半昏迷状态的一个女孩子,但是他整个过程中,实际上这个这个这个角色看上去就是看久了,就会觉得很重复,所以这个时候啊,实际上我们是会把物理的输出和动画的输出。
之间作为一个互相的一个blending,这个讲解起来就比较复杂了,其实我们可以认为就是我们要动画输出,作为他一个初始状态,把它作为一个数,因为动画不仅提供了一个pose,还提供了什么,提供它的速度。
它的转动惯量,我们把这些东西呢放到我的物理结算里面去,再结合它整个这个角色在空间上的这个位移,哎我再给它产生一个新的光亮和角动量对吧,这个时候我物理算出个结果,然后呢我在物理和动画之间再进行一个差值。
这样我一帧帧的动画播放,我在一帧帧的物理模拟,这样我能产生一个看上去又像一个人类的行为,但又符合又有点物理的失控的感觉,这个例子呢还有更好的一个例子是什么,我不知道大家以前有没有玩过那个新战。
就是33A大作版的那个就是主机版的性价,中间有一种东西,就是你把那个你用超能力把一个人给举起来,你领的那个那个就是,比如说帝国战士的那个脖子,那个帝国克隆战士的话,他就会开始就各种挣扎。
你可以把他这样拿到左边,拉到右边,你会发现这个角色他自身的也有自我的意识,但是当你去把它往左边去移动的时候,他的身体会不由自主地往另外一个方向去甩,而这个时候如果完全用动画去做的话,那动画是会累死。
那怎么办,诶,我这里面就是用这种power recordo,在动画和物理之间来回的去去去blending去过渡,所以这个其实也是我自己个人还蛮看好的,一个就是在引擎里面的一个实现。
因为随着我们对游戏品质要求越来越高,我们越来越不满足于就是说动画是预先设好的,这个循环的animation loop,我们更希望就是环境用户的输入,给角色的行为带来更多的随机性和多样性,所以的话呢。
rag doll是一个很重要的一个基础系统,但是在他之上的话,有很多很有意思的东西可以去衍生,那RAGDOLL的话呢,我们就讲到这儿,那接下来的话呢也是我们的物理系统,最重要的一个大客户啊。
这真这真真实实是我们物理系统的大客户,就是我们的医疗系统,因为其实怎么说呢,就是现代游戏这个对于人物的,其实我们今天讲的虽然是意料,但是大家如果想了解一下,比如人物的毛发对吧,然后跟这个东西很接近。
但毛发比它更复杂,毛发是一丝一丝的,我我在一开始讲课就毛发,我们我们在课程中不展开讲了,因为那玩意儿讲起来又是又是一堆东西,但意料的话呢跟他有一些异曲同工之妙,那么实际上我在我看认为啊就是一个角色。
你去看他怎么样真实,他其实整个角色你把它建模做得非常的细,做得非常的真实,但它是静态的,你怎么觉得他是活的呢,我觉得第一个是他的表情对吧,他的表情让你觉得很真实,第二个呢就是哎她的头发,当她回眸一笑。
他的左摇,他的头发微微动,那个一个小刘海的波动文化,你觉得哇这个角色很可爱对吧。
那这里面二次元的这个同学们应该很懂,我在讲什么,还有一个是什么呢,就是医疗,因为医疗太实在是太重要了,就是你这个小姐姐的衣服好不好看,实际上就是在看你在游戏中的这个角色的衣,衣服模拟的是不是足够灵动。
那么其实医疗呢从最早期的做法,其实想象的非常的简单,什么呢,哎我们就用动画去做对吧,你不就是这个走走,让他一些东西飘一飘嘛,我在里面买几根骨骼,还大家还记得我在讲动画,一开始就讲课,就是说其实很多游戏。
特别是早期的游戏啊,他给标准的角色上埋了很多骨骼,有些谷歌就是用来做衣料的飘动的,比如说以前大家会觉得诶,我的游戏里面有那种披风对吧,那披风怎么动的,1000就是放了三条骨骼,然后呢衣料往上一放。
诶这个衣料动画是做好了,当我跑走的时候,这个衣料比如比如说你往左边跑,往右边跑,诶这个骨骼相应的就变一变,然后你动画反正是差值的嘛,你看上去其实也挺像那么回事,这个方法呢实际上还是非常实用的。
它在什么地方特别有用的,就是比如说在移动端的游戏中,其实很多移动端的游戏,到现在它的布料系统并不是真实的物理模拟,原因很简单,谁都跑不动,真实的物理server很费,那。
诶我用这个简单的动画系统就可以做出,我们想要的医疗系统,其实也还是蛮好看的,那么第二种呢,刚才我们不是讲了ROG多吗,对不对,唉我把这个东西交给物理系统的这个结算。
那这样的话我做几根就是register body的,这样的一个RAGDOLL的骨骼,然后呢这样的话才能实现什么呢,就当我这个角色走来走去,甚至我风给他吹一个力的时候,诶这个衣料好像也能飘了起来。
就是这个叫什么呢,叫dynamic bone,动力学骨骼,实际上如果刚才讲的是那个那个那个,Kandemic bone,就是说ANIMANIMATED这个BB的话,那这个呢就是dynamic bone。
动力学谱的方法做医疗,实际上呢这个在早期的PC游戏中,也是非常常见的,因为那个时候我们已经有了基础的物理,计算机了,但是呢我们又舍不得上,那么expensive的布料模拟。
那我们用几根动力学给我放在这儿,那基本上也能实现整个衣服非常灵动的效果,但是呢今天的课程我们给大家讲的就是,稍微有意思一点,这也是现在游戏引擎发展的一个主流趋势。
就是说我们用mesh base的方法去进行COSIMULATION,这样在这里面的话,你看见所有几乎所有动物的东西啊,它都是布料啊,这些布料的话呢,它实际上都是用网格的方法。
就是一个顶点一个点的做物理学的解释动出来,那这里面大家看到颜色的不同的,但是我们会解释为什么每个颜色不同,那么其实这种mesh based cost simulation的话,第一步就是说。
我得把我要做的这个物体的这个mesh找到,那这个物体的mesh呢真实渲染用的mesh啊,一般都会非常的细腻,非常的detail,你如果真的把这个几千个点,上万个点交给这个simulation。
simulator去做simulation的话,大部分的物理引擎会当场死给你看,所以呢我们一般会对医疗,每个东西我们会做一个就是physical mass,就会相对来讲它的这个密度啊。
会比原来大概小一个四五倍,是很正常,甚至是十倍以上,比如说你本来这个布料是4000个面的,但是呢我在做模拟的时候,可能是四五百个面,基本上效果就可以了,因为其实他也是有点像那个呃。
就是vertex animation一样的,就是有些vertex其实可以通过那个,比如大家还记得我们前面讲过很多白,虽然这个那个把CENTRIC那个TEMPLATION吗,方法我就可以把一些洞。
把他的一些运动,可以插值到那些其他的顶点里面去,当我们有了这样的一个一个一个,一个physical mesh的时候呢,我们一般会做一个权重的刷,大家想想看,很少有意料,真的是飘在空中的风吹得满地跑了。
大部分的衣料是不是穿在人的身上面,对不对,那我这个衣服穿在这个角色上面,我们大家是不是不能接受,说比如一个披风对吧,走两步,这个披风布料一模拟它就飞了对吧,那衣服要废了,这肯定就有问题了,那怎么办呢。
我们就会在每一个这个physics smash上面的话,画出它可以移动的范围,那一般来讲越靠近身体,越靠近固定固定点的地方呢,我们会把他的那个就是约束权重给它降下去,就是让他就是位置不要动。
特别是比如说做披风的时候,沿着脖子的这一圈,我们会说你的flexibility,你或者是你的freedom就是零,你就在那别动了,但是越往下我会给你的空间就越大。
但这里面有一个general practice,就是说我们在靠近身体的地方的话呢,会允许它动一动,但是呢也会不让它的幅度太大,为什么呢,因为幅度太大之后,他就特别容易和这个角色穿模,其实衣料穿模。
我可以认为在目前的游戏引擎中,都很难解决的问题,但是现在越好的引擎啊,解决的越好,但这里面是有很多的挑战和问题在里面的。
那么其实呢接下来的话呢作为artist来讲,它就比较简单了,它就可以设置很多,比如说我的意料的硬度啊,我的音意料的这个切向的,这种这种韧劲是多少呀,我能不能那个ANTIBAND啊。
能不能阻碍这种这种这种折叠啊,这种能力对吧,那作为artist来讲,它就设置参数,但这件事情它就能够让我们生产出各种各样的,比如说丝绸质感的皮革质感的衣料,对吧,当然我们要结合我们的rendering。
那一趴讲的PB2,我让他才是看的更正常,讲到这一趴,大家是不是觉得都很简单,都比较好懂对吧,但事实上我们作为引擎的开发者的话,我们的世界不是这样的,我们看到的世界是什么呢,首先衣料怎么模拟。
这个时候我们会发现,就是说我们能用的工具居然是我们那个,这应该是初中物理的这个课程了吧,弹簧质点模型,我们只能把这个意料想象成无数的弹簧支点,就是我自己也有很深的感受。
就是经常我们的artist会跟我们狂喷,说你的衣料做的不好啦,又穿了,怎么做都不像了,但是我们真的在写这些底层算法的人,我们就知道哥哥,你不知道我们有多痛苦啊,因为你今天看到这么漂亮的这些衣料的话。
实际上是由无数个无数个质点和弹簧,模拟出来的,然后呢每一帧我都要做大量的结算,那先先讲它最简单的结算,就是一个弹簧上面的质点,它受到的力是怎么怎么来的,第一种力是什么呢,就是我们叫做行便利。
就是说你拉开离开他的那个recipes,就是说他的那个就是这个这个零张力的那个位,置的时候,只根据你的位移,你无论是正向的负向,它就会得到一个相反方向的这个弹性力对吧,这个用胡克定理讲。
就是你的位移乘上你的这个弹簧系数非常简单,另外一个还有什么呢,这个是大家很多时候会忽略掉的,就是说这个系统它是有一个叫dumpling的力,dumpling的力叫这个dumpling这个词是什么意思呢。
就是衰减,其实我们在做真正的物理系统的时候,dumpling是非常重要的,那在这里面的话,你首先能看到的一个衰减是什么,我这个质点在移动的时候,我会受到空气的阻力对吧,实际上在这个医疗里面。
这个空气阻力是非常重要的,为什么呢,因为我们虽然用的是弹簧质点模型,但是大家仔细想想,我们的衣服可是不是一个个的质点,它实际上每一个每一个质点和弹簧之间,表达的是一小块的面积啊。
所以那一小块面积所受到的空气阻力,其实并不低的对吧,而且dumpling为什么很重要呢,这个但这一边是荡开一笔了,就是说无论我们去做什么样的一个物理模,模拟系统,如果你不去设置一个dumpling啊。
它很可能因为有大量的数值迭代计算,包括公式上可能有些不准确的地方,包括浮点算运算的这个这样的一个一个误差,它的能量可能会爆炸,因为大家想象一下,我做过浮点运算,我一直做加法乘法除法。
然后呢每次都溢出那么一点点,当你迭代个几千次,几万次的时候,最后的结果是什么,实际上你是不知道,而dumpling呢,它会让你的迭代稳定性提高特别多,所以这是一个绝对的黑科技,大家一定要用好。
那我现在有了一个弹簧,一个支点,这个问题好解决,对吧好,那我接下来我要做个医疗,我怎么去构建我的弹簧质点模型呢,那实际上的话呢大家现在的做法是A,我去做很多的这种一把衣料,均匀地看成一个个的支点。
然后呢我在它的横向纵向加上很多弹簧,你这样加行不行,其实也还可以,但是呢你会发现,这个时候当你去ban的这个弹簧的时候,它几乎是没有什么这个阻阻挠力的,所以我们一般有的时候会加他的。
在cross里面会加个弹簧,实际上有的时候我们会专门加一些弹簧,横跨几个支点,就是比如说我要表,表现一种非常硬的这种布料的时候,我对他的单子的惩罚就会很大,那这个时候我会比如说横跨两三个支点。
加一根弹簧,就是不让你折来折去,如果这个弹簧系统构建的就是过于稀疏的话,你做出的布料给人的感觉是什么呢,就是特别的吸软软的,都不太真实了,但是你说这东西对不对呢,我个人觉得对于某些某些布料举个例子啊。
比如说像丝绸这种感觉还是挺挺有感觉的,所以其实我认为就是这个做医疗的,这个这个力学模型啊,很多时候它就是一个经验经验,一个hack,你自己构建一个模型,那么在这个里面的好像是行业用的比较多的。
那好我们完整的讲一下,说诶,这里面,当我把我的一个质点放到一个完整的布料里面,我们会受到哪些力呢,哎这个时候就比较复杂了,就是对于中间的那个红色的点来讲,我们会收到哪些礼,第一个大家很容易忘记的。
我们是生活在地球上的,地球上有什么有重力,对其实在做所有的衣料模拟的时候,你千万不要忘了重力,为什么呢,因为你如果没有重力的话,这个衣料飘起来之后,它就永远飞掉了,它不会落下来的对吧。
必须要重力把所有人就落下来,那么第二个是什么呢,就是风为什么风是单独的呢,因为大家想想看啊,当我穿着这个这个披风,我这个像风一样的男子这样跑起来对吧,飞起来从悬崖上跳下来,那实际上你包括其他风了吧。
那个时候这个风啊,它是一个consistent apply到你身上的一个力,这个风力其实非常的重要,所以呢这也是让我们大部分游戏,如果没有风力的话,那个斗篷都是耷拉下来的,虽然角色动的时候动两下。
但是你只要一停,它就耷拉下来,只有有风的时候,才让这个角色看上去就那么的有个性对吧,其实如果大家玩一些二次元游戏的时候,你就知道那个角色的披风,永远是和他的身体形成一个完美的一个家教。
让你觉得这个角色看上去,总是那么的膨胀和有立体感,也是这个道理,那么好,接下来呢就是我刚才提到的就是空气阻力对吧,这个空气阻力呢取决于你当前的速度,所以刚才这个就是一般来讲,我们用个最简单的公式。
就是它跟速度成一个线性比值,其实这个是这个东西,基本是啊,怎么说呢,其实如果严格的讲的话,它应该是速度的平方,但是我们这边不要去纠结这个细节了,在低速情况下,我就用线性简单的模拟一下。
而接下来就是说你周边所有的弹簧,从各个方向对你施展的力,注意弹簧给你施展,你是有两种的,一个是胡克定理决定的弹力,对不对,还有一个是什么,大家很容易忽忽略了,叫dumpling。
就是说弹簧它也不是一直能动的,就是如果你只有虎颗粒的话,大家想想看这个弹簧会怎么样,它会永远的做简谐振动对吧,如果你现在做过医疗模拟的话,你只要扰动它一个顶点一下,如果按照这个理论模型的话。
他会不会永远的来回答,哒哒哒哒哒,这样动,对不对,这是你想要的结果吗,不是大家想要的结果,所以我们一定要加个dumpling,就是弹簧,你虽然给了他一个初始的输出之后,它动了动了动了。
因为内部的摩擦力啊,就是把你的机械能变成热能之后,哎它就能停得下来,所以这是一个真正的当我们做医疗的时候,我们看到的这个物理世界的模型好,那我们怎么去积分它,我有了这个模型之后。
其实这里面的每一每式子的每一项,并不那么难算,那这里面的话呢,我们要给大家讲一个非常有意思的积分,叫word的积分,它它的积分的巧妙的地方是什么呢,就是如果这里面我们用到了,比如说你在空间上的位置对吧。
还取决于你的速度,那么位置和速度之间又是一个相互反向,积分的这个关系其实是有点小复杂的,但我们真正的医疗模拟的时候,我记得我们在上节课我们讲过,叫半隐式欧拉积分,我也跟大家分析过。
就是说半影视欧拉积分的话呢,它既具有很方便的计算,它与影视欧拉积分其实算起来更方便,而且呢他更加的收敛,但是的话呢后面的数学大牛就是VLAD,他提出了一个方法,就是说诶既然半影是很好的话。
那我可以把你的这个积分呢变成只跟速度有关,而且呢更加的稳顶,我这边重点给大家讲一下这个积分的思想啊,就是首先大家想想办饮食积分是什么概念,就是说我首先我的在德尔塔T时间之后。
我的速度是不是有我当前的速度,再加上一个我的加速度乘上一个时间对吧,那么我新的位移就是X的T加德尔塔T的时候,是不是你当前的位置加上V的,就是德尔塔T后的速度,就是未来的这个速度乘上了德尔塔T,对不对。
这里面的话呢,它就有一个很有趣的一个observation,是这样的,就是你的速度,比如说你当前的速度是什么,是由什么决定,实际上是你当前的位置,应该有你上一个德尔塔T时间的位置。
加上的你当前的速度乘上个德尔塔T,为什么呢,因为你当前的速度也是由你上一帧半音时,而来的,这个这个方法是很巧妙的,这个SERVATION,那这样的话呢,你当你把这个公式放到一起去整理的时候啊。
你就会发现,其实VT你可以用这个上一帧的位置,和德尔塔T的关系就能表达出来,所以他把这两个式子一整理,你就会发现啊,就是他最后得出的结论就是XT加德尔塔T呢,它是等于是个指东西,叫做两倍的XT。
就是当前的这个位置减下去上一帧的位置,然后再乘上你的AAHA值,有什么唯一动决定就是你的受的力决定,对不对,再乘上一个德尔塔T的平方,就是时间的平方,那么这个公式它为什么很巧妙的。
大家会觉得这不是数学上是等价的吗,你有什么好说的,但是大家仔细想想,当我们在做这个就是模拟的时候,我们每一帧每一个tick tick tick,我模拟的最准确的是什么,是你的位置。
其实你的速度是用我的位置反推过来的,而且呢我有当前帧的位置,其实我在cash一下上一帧的位置也不难对吧,那我下一帧的位置的话呢,他就把这个事情简化成了,叫做上一帧的位置和这一帧的位置,再加上我受到的力。
我用这个简单的方程,我就能算出来你的这个下一站的位置在哪里,我指那么这个积分,你在数学上看上去是等价的对吧,但实际上它是一个非常好的一个平衡,为什么呢,因为如果你老是用未。
就是那个就是用那个速度去算速度,在某一个瞬间的时候,可能会变得非常大或者是不稳定,一旦你某些速度不稳定之后,你这个积分本身就会变得这个integration,就会变得非常的不稳定,而VT的话呢。
它就非常巧妙的把这种不稳定的,因此给它去掉了,而且word积分实际上也是更快的,所以在我们的布料模拟之后的话呢,我们很多时候用VERTT积分,这个来取代半隐式欧拉积分,大大大家注意一个细节。
就是说实际上从思想上是和半隐式的欧拉积分,是等价的,那这一趴的数学呢实际上大家后面仔细看,其实并不是特别的难理解,而且我个人觉得是蛮巧妙的一个方法好,那么其实呢我在这一盘还不展开。
但是后面我给大家提一下,其实布料模拟啊,现在最主流的方法实际上是PPT,就是position based dynamics,就是基于位置的动力学模拟,它的好处是什么呢,就是它的简单的思想。
我在这边只提一句,就是说如果刚才我教我教给大家的方法,它是一个很标准的一个经典力学的方法,就是牛顿力学的方法,就是说根据约束,我可以算出它的力,根据力我算出它的速度,根据它的速我算出它的位移对吧。
这个是一个非常合理的一个因果关系,但是呢有一套另外一套的数学,就是我们以前讲的拉格朗日数学,他把所有的力学关系描述成了一堆数学的,叫约束,他认为所有的力学过程,必须要符合我的数学约束。
我是直接用constrain约束,直接解除你的位置,而我不再去关心你的速度,这个非常的巧妙,那么这种解法它的好处是什么呢,就是它能处理一些非常复杂的情况,同时呢它这个server本身是非常的稳定的。
就其实复不复杂呢,我觉得仁者见仁智者见智,但是他的server第一个是会比较快,第二个呢它能够在一些非常复杂的,非常的就是说精度敏感的情况,讲解的非常的稳定,像这里面这一条几万个面的龙。
我用一块布料从头上划过去,其实这个case大家如果真的学过物理模拟的话,就知道这个case非常的难,其实到现在这个这个视频我拿过来的话,我一直在跟课程组的小伙伴上在讨论。
说这个demo它到底是real time还是not real time,其实我们知道就算不是real time的话,这个demo也是非常复杂,很难写的好,所以的话呢pd呢我在后面会单独去讲。
但是大家知道就是说在现代的游戏引擎啊,引擎中,越来越多的布料模拟,使用的其实不是刚才那个简单的弹簧支顶,我他用的还是弹簧质点模型,但是呢不再是用简单的速度加速度方法去解,而是用PPT的思想去解好。
关于布料这一趴呢,我们算法server讲到这儿,但是布料里面一个特别特别恶心的东西,是什么呢,叫自穿插SOLICATION对吧,像这边的,像我们的那个左边的这个布料,大家看。
如果我们把SELFICATION关掉之后,它的布料之间就会互相穿插,然后那么薄的东西一穿插之后,你基本上没法看,就这里面的例子,就是它两面用了两个不同的颜色嘛,就算两边的颜色一样。
比如说里面的衣服和外面的衣服花纹不一样,当它动起来的时候,两个布料在在一起是会经常打架的,特别在取色身上哦,我们今天课程组还在商量,就大家都说这个布料的CLICHEN,这个其实挺讲解的,我说是。
而且现在是越来越重要,因为我们现在在表达一个角色的时候,他的衣服都要穿好几层,那每一层布料都在做自我的模拟,刚才大家看了已经觉得有点高能了,对不对,但是大家想想看,当我这么多层布料在一起模拟的时候。
怎么办对吧,那万一穿插了,比如说一个这个这个这个比如说一个小的,这个里面的T恤甲是蓝色的,外面罩了一件外套,比如说是白色的,好那个蓝色的外那个T恤老是穿透出来,出现在白色的外套上面,大家一看哇。
这个游戏很渣渣,很这个质量不行,其实这就是我们真实的在做游戏引擎,特别是做物理引擎的时候,我们所面临的一个巨大的一个挑战,那这里面的话呢我就给大家简单的去点一下,现在的一些常用的方法。
比如说最土的方法怎么样,我把布料的这个这个物理模拟模型把它加厚,就意思意思就是说你虽然是穿过去了,但是呢你只要穿的不够深,我还是不让你去透出来对吧,但这个就很土了,还有呢。
就是说我把布料的物理仿真的步伐变得更细,拆成很多subs step,这样的话当我就能够保证在我server去解的时候呢,我不会过深的穿透过你的这个布料,这个也是一个,就是我们认为。
用计算复杂度来换这个稳定性的问题,那么还有一种方法呢,就是我们叫做maximum velocity,就刚才我提到,就是说其实真正在布料模拟的时候,有的时候速度这一项它其实是不稳定的。
所以呢很多时候的穿插,就是说你就是大家如果真的解那个物理server,你会发现一个问题是,当一个东西它穿过去之后,他不除非你专门处理它,否则是弹不回来的,他就真的穿过去了。
因为他会认为那个状态又是一个物理的稳定态,大家仔细想想,就是说你把一个一个一个缸,一个缸体击穿到另一个缸体,是不是,击穿之后他如果能穿得了,它在里面停下来,其实也是个稳定的状态,对不对。
它也符合我们的物理学的约束,那这个时候呢他就设置了一个maximum speed,就保证在每个subs step上的话,你不会把它穿得过深,这样你还能弹回来,那么一个更精更精确的做法呢,他就加一个立场。
这个立场呢它一般会设置在布布布料的里面,就是说当你穿过去之后,那个立场它能检测出来那个立场全是负向立场,他就把你的东西往回往往回顶,就是我在讲图形学的时候。
讲过一个叫sdf sin distance field对吧,其实它就相当于在布料里面建了一层,这个负向的sign sdf的这个distance field,当我有一个模拟simulation。
有一块布料它穿到我的里面去之后,我这个SDF就起作用了,就会给你产生一个反向的impulse管理,在提听出来,反正anyway,这里面的话,其实真正的实施和骇客其实是非常非常多的。
那为什么这里面我给大家点一下呢,我只是想让大家知道,就是说其实classsimulation self collision detection的话呢,实际上是一个非常重要的一个model。
也是很重要的一个课题,其实不止布料自己之间了,还包括就是布料和缸体之间,因为我们在角色,比如特别是角色在动的时候啊,我们的物理的这个body,实际上是比真实的角色要要简单的对吧,它并不完全重合。
但是呢你的布料一旦跟这个这个,比如说你的大腿表达,用SELENDER去碰撞的时候,它会碰撞出一个不正确的一个结果,那么如果我的这个钢铁在某个角度的话呢,它占用的体积是比真实的,我的这个体积要小的话。
就会出现叫做我的物理系统,认为我已经把你顶出去了,但是呢诶你当我去渲染的时候,我那个地方的皮肤又露出来了,这个时候就很尴尬,就所以大家以前在看很多的早期游戏的时候,这种布料模拟的话。
很容易出过你单身的大部分早期游戏的时候,是不会用真实的物理去进行布料模拟,他很多时候就像我刚才讲了一个动画的方法,用这个其他的方法来实现,所以呢还好,所以这也是在未来,大家实现这种高品质游戏的时候。
其实是也是一个必须要解决的一个问题,其实实话实说,我到现在也没认为我知道一个很好的解,我这个还是一个非常前沿的,大家都在研究的一个领域,那么好,讲完这么难的数学的布料,接下来讲一个比较有意思的系统。
就是这个破坏系统的,破坏系统在我们的游戏引擎中是由来已久了,而且我觉得这也是属于大家特别喜闻乐见的一,个东西对吧,就是从超级马里奥时代,我觉得最大的乐趣就是把人家强撞的一塌糊涂,你就觉得哇。
我这个我感觉我是在创造这个世界的玩法,那么其实呢就是破坏系统呢,对于现代游戏引擎来讲是非常重要的,因为它实际上它不仅是一种视觉表现,更到现在已经越来越变成一种,可以跟play的东西了。
比如像我们大名鼎鼎的彩六对吧,那你在墙上打洞,在什么地方打洞,用什么枪打洞,这可就是你最核心的一个战术了,所以实际上我个人,就像上次我记得我在讲那个graphics的时候。
我讲过一个就是walker base的这个turn的表达,我就想为什么我会对那个东西个人很感兴趣,因为我一直在幻想,就是有一个游戏,我能够自由的去挖战壕,自由的去挖地道,自由的去拆掉别人墙。
构筑各种我想要的公式,那样的游戏是我觉得那是游戏的本身,所以我认为destruction的这个系统的话,实际上就是给用户了这样的一种自由,那么好,那么destruction怎么实现的呢。
其实他想起来也并不简单,就是并不复杂,就是说当我给你一个没有被破坏的物体的时候,其实啊你用一种hierarchy的方法,你可以把这个物体分成一节一节一节的碎片,那么这一节的碎片的话呢。
我们一般会用HT的方法把它组织起来,这样会让你的这个破坏,这个碎片看上去更有结构感,其实我们看见就是说当我打一个东西的时候,他不是你打在他不同的地方,它不会一下子全部碎掉了对吧。
你会感觉有些地方A打掉了一大片,有的地方就掉了一点点,那这个碎片的话呢,我是用自动生成的方法把它生生成出来,形成一个树状的结构,当我有了这样的一个树状结构之后呢,我接下来建立一个什么呢,它它的连接关系。
就是你可以理解成,就是碎片A和碎片B之间的话,它的连接到底有多牢固对吧,这个地方我就形成了很多的H,大家想想这里面的一个DEFGH,这些碎片的话,实际上它们就会有相应的连接线。
这也是一个游戏引擎里面一个标准的一个课件,告诉你说你怎么去做一个可以破坏的物体,那么每一个connection,实际上它都有一个就是它的权重叫value,这个value就表示它能够承受的多大的冲击。
或者多大的这个力,那这个这个数值呢其实表达的是什么呢,就是它的这个我们叫做印度,那么这个印度怎么起作用呢,很简单,当我来了一个东西撞我的时候,大家还记得我们在物理引擎里面讲的是什么,是一个冲量对吧。
Impulse,那么这个印度呢就会说,OK你冲量和我的impulse之间算出了一个值,就是你的冲量和我的硬度之间形成一个值,这个值就是你对我是真实形成的一个damage,当你这个damage。
这个值超过我一开始设定的那个阈值的话,那我这个东西就断了就对吧,他是这么一个简单段,但这里面其实有非常多的问题的,因为我个人虽然说,这也是游戏引擎里面经常的一个时间,但我一直在思考的一个问题。
就是说首先impulse是有量纲的对吧,但印度这个量纲的话呢,和我们真实在物理学上的量纲是不太一致的,大家知道物理学的印度是有什么十级对吧,大家记得金刚石石,对不对。
然后他讲的那个硬度指的是两个东西摁在一起,我多大了,尽力下去之后,它不炸掉和你这种在冲击力之下,他不会去炸掉这个硬度,我个人认为他在物理学上是有不一样的表达了,因为物理学上你真的一个东西能打断的话。
还有什么,除了印度还有什么,还有它的韧度,就是它的任力,包括就是说他之所以产生那个折断效应,实际上是在那个点上产生的应力,超过了我的阈值,但是呢当这个当这个artist。
我让他去标识这里面的23是100的时候,实际上artist是完全没有概念的,他就会觉得哦,那我标个300吧,标个100吧,好像就像那么回事,但实际上它的物理学意义鬼才知道,没人知道对吧。
然后呢我们还假模假样的搞了个这么个公式,就是说当我有一个球打中一个点的时候,哎我们会把它所有的这个damage,以一个一个同心圆的方法分散出去,这个这个公式看上去特别高大上,实际上非常的简单。
就是我装的这个点在一个相对小的范围里面,所有人受到的damage都是一样的,就是你的impulse都是一样的,然后呢当这个就是这个点的话呢,就是足够的,就是扩散的时候,他逐渐就从这个百分之百的这个冲击。
到0%的冲击,然后做个做个差值,但是特别honest,我觉得这全是hack,就是说我不认为,今天我们在做这个destruction系统的时候,这个问题有个很好的讲解,因为我今天跟我们课程组合在一起。
举个例子,比如说我们我很难跟artist讲,就说你拿一个步枪子弹,你去打一颗子弹,大家知道一个步枪子弹所射出去的这个冲,这个冲力啊是非常大的,可以达到几千焦耳的这样的一个能量对吧。
但是的话呢我们比如说啊我们一个人,他用很大的力气去撞一个墙,你所产生的冲量大概也就几十焦耳对吧,但是你如果我真的做一个东西的时候,我artist说诶这个这一面墙我用子弹一打,这个墙就掉掉了对吧。
但是呢我用人撞这个墙总是撞不开,其实有的时候你会觉得有一点奇怪,所以这个呢也是我认为就是说只是在引擎中,大家会这么做,但其实我相信在未来一个更加的物理追问的,这样一个游戏世界里面的话呢。
我相信他有一些更好的一个表达,那这里面的话呢就是说当我这样的一个物体,我已经把他的这个CHK,就是这种destruction的唱K分好了之后呢,我就会把它放在这个世界里面。
一般我们会做这个supporting graph,就是说他会这个东西会挂在某个地方,比如他一个窗子就挂在窗子frame里面对吧,他如果是在墙上的一个突出部,那就挂在墙上了。
这样的好处就是说当他产生了这种破坏的时候,它实际上只会对那个区域会产生一个破坏效果,而不会把整个这个就是东西给破坏掉,那么这个东西唱K到底怎么生成的,这个图好像有点问题,实际上那个我们这个图是要展示的。
就是你在那个角受了力之后,他就那一那一侧掉下来了,但我相信同学们学到这一趴的时候,应该都已经知道自己怎么会想,因为我们前面讲的东西比这个要复杂得多,这个地方是非常的直觉,那怎么样的自动生成唱歌呢。
因为你不能老是让人家美术去帮你,把这个东西分割好吧,但其实有的时候我们还真的让美术分割,因为美术分割有时候它会形成我们想要的结果,那这里面最常用的算法就是大名鼎鼎的vi算法,我相信上次我们上节课。
我们在讲那个语音的时候,讲noise生成的,好像就提到过大名鼎鼎的模拟算法。
它简单来讲就是你在空间上随机撒一些种子,然后呢,你把这个空间分割成一个到每一个种子的距离,都对等的这个边界,这个东西在生物学上是很有用的,其实你们小时候如果看过那个生物课。
你们那个细胞你看到那个细胞核对吧,特别是植物细胞,细胞和细胞壁形成的那个划分,就是一个标准的warning划分,哎我这个很有意思,我其实整个细胞的生长,它是非常符合这个数学规律的。
那么就是我现在给你一个形体的时候,比如说一个2D的mesh,实际上我就给他,我算他一个绑定,然后呢我就随机的产生一些种子点,然后呢形成的纹理划分之后诶,我就能形成这样的一个碎片。
大家看看这个碎片看上去是不是就很很自然,很真实,所以其实数学是非常简单的,那么如果你是个3D,实际上我也是用这个类似的算法,但是呢我RONI对空间形成划分之后呢,我还得用一个就是那个DERISE的算法。
把它就是空间进行三角化,这个DRUNNING算法化简化三角化呢稍微有点复杂,但其实也不难,大家如果想查就可以查得到它,简单来讲就是我可以把空间划分成无数个,就TJHEER,就是说这个就是四面体。
就四面体的话完成一个对空间的划分,因为你本身的形体是各种各样的,所以说你用这些台式,黑色角去划分的空间的时候,你会得到一些看上去非常有意思的这些碎片,就像这个雕像一样的对吧,你给他算出一个绑定,你。
然后呢用那个那个那个DCT的那个DERIA的算法,把它分成这个四边形的,就是四面体的空间,提速的时候,再配合上它本来的形状,就看上去就很很真实,很自然。
但是to be honest这个东西看上去还是比较粗糙,但这里面有一个非常有意思的一个细节,这也是我特别想让大家注意到的,就是当一个形体,比如说我们建一个模的时候,我给它形成一个贴图对吧。
那这个贴图看上去就很好看,但是当我把这个花瓶打碎的时候,你会发现最难的一件事情啊,实际上我要生成一个就是volin texture,就是说因为比如说一棵树啊,树可能不大,树不太容易打碎啊。
比如说一个大理石,你把它打碎的时候,你在断痕处看到的是很多大理石的花纹,对不对,那个花纹实际上是有一个分布的,那个切口处的纹理啊,其实生成是比较复杂的,而这种东西的话呢。
一般当我们做真的做3D破碎的时候,特别是这种大体量的3D破碎,比如说一个雕像的破碎对吧,比如说一个砖墙的破碎的时候,我们就会要处理这个断口处的纹理生成的问题,那这里面一般有两个流派了,一个流派。
就是说哎我干脆就是有一套procedure的方法,生成3D的涡轮texture,你这样用的时候就直接去我的VOLTEXTURE的事,但是大家知道3D的texture,无论从生成到采样都很复杂对吧。
还有一种方法的话呢,就是我离线把这些texture uv都给你算好,所以一旦你碎了之后,哎我就把你的渲染切过去,所以这个东西其实蛮复杂的,而且它在一瞬间啊,那个破坏的一瞬间。
它就要为每一个碎片生成一个它的rigid body,因为碎片之间最复杂的是什么,他们彼此之间还要碰撞,所以destruction啊,在很多游戏中是一个非常expensive的一个东西。
比如说在我们的很多游戏实践中啊,就这些DEBRICK就是我打出来的这些碎片,一般来讲不不要不要让他去参加物理逻呃,游戏逻辑的结算,其实在我们在座很多游戏的时候,很多人都说我特别希望有一炮把那个墙给轰塌。
然后墙掉下来的石头把这个角色给砸死,对这件事情我们都觉得很好玩,但实际上你会发现除了单机游戏之外,大部分的网游他都不敢这么做,为什么呢,因为我们讲过那个deterministic对吧。
同一个物理事件在不同的玩家的终端上,它模拟出来的结果都是不一样的,那如果不一样的话,他那个轨迹砸下来的弹道,包括角色的位置同步都不一样,所以很很可能在你的世界里面,你认为那个石头把一个人砸死了。
但是呢在另外一个时间点,他看起来完全没有砸到,所以呢这也是就是destruction系统,它在未来一个非常大的一个挑战,当然我们也知道有些物理引擎也在client,他说他能解决这个问题。
那么这个destruction的这个这个CHK生成啊,实际上是有很多的更多的细节了,比如说在一些比较好的引擎里面,这里面我举了的例子,就是,实际上你可以指定说我生成的这个这个。
这个fracture的这个pattern是什么,比如说它更均匀地碎掉,还是说它更结构化一点,就是有大大小小,还有可能比如像玻璃这种,它是沿着一个方向快速的就是极化掉。
那这个的话呢就会给我们的artist更大的空间,去表达他要表达的世界,那么所以呢其实我们在整个物理引擎来讲的话,destruction是一个很重要的环节,一般来讲的话。
我们是把它放在collision之后,就是因为很多的destruction事件,都是在clean社会发生的,比如说一个东西掉下来了,或者说我射出去了一个子弹,但是这个这个可能更像是SQUIRY了对吧。
或者我砸出去的一个一个一个球,这个球最后撞到一个东西,或者我我一个一个character,他撞到一个东西之后,哎我们会发生这种就是说那个destruction的事件。
然后我们去update它所有的这个这个碎片,其实更复杂的情况是什么,就是我一个东西它已经碎了诶,我我害怕跟碎片再进行一些互动,实际上的话呢,这个就是物理引擎写下来就很麻烦,但是确实要写,那么其实的话呢。
就是在真实的物理引擎和游戏引擎里面的,distraction啊,我们一般会加很多的回调事件,它要配合相应的就是这种生效或者是效果,因为你的这个破坏,一旦没有了这些生效和party系统的话。
你会觉得它的真实感有很多的问题,简单来讲,比如说我一个破坏生成了一些比较大的碎片,当这些碎片落到地上的时候,你是不是应该看到一些小小的烟尘,你还应该听到一些声音对吧。
其实在我们在写物理引擎做物理结算的时候,实际上每一个碎片它变成一个raid body的时候,当它和环境发生这种contact的时候,你都要给你的上层的用户提供一些回调的函数。
让他决定说我是否要播放一个特效,我是否要播放一个生效,否则的话你那个场景看上去再酷,它实际上也是很塑料,所以大家到这一趴的话呢,我希望让同学们能感受到,就是说在做一个真实的游戏的这个物理引擎。
它其实啊复杂度还是非常高,因为人对这种fidelity就是这种真实性的东西啊,它的PROCEPTION,特别是物理感的东西是非常非常敏锐的好,那么其实呢就是destruction呢,我觉得最大的问题。
刚才我已经反复点到这件事情,就是说大家会觉得游戏中非常酷的一个东西,但实际上在现代游戏中呢,我们一般都会非常谨慎的使用,因为一旦参与破坏的东西多少,它生成的碎片可能是成千上万,而且接下去以这个例子。
你看这个是我们实时录下来的,这是我们在那个joint引擎里面做的模拟,这个案例里面的话,你会发现它的速度就很慢,为什么它碎成了这个上几百块,上千块的碎片的时候,他每个碎片都在高速的互相碰撞,互相结算。
这样你才能看到这种碎片逐渐散开的效果,否则的话这些碎片散开了之后全叠到一起去了,但是你看到这么很自然的翻转,散开的这个效果的话,在物理解上里面其实是非常非常的复杂的,这就是我认为就是大家很多时候在讲。
我们的游戏引擎嘛,在我看来的话,就是如果我们认为真实的世界是一个大的,一个simulation,就是上帝写的一个模拟器的话,那我们人类写的模拟器在它面前,那简直就是小巫见大巫啊。
简直都这个不知道差到哪里去了,所以说我们未来的游戏引擎,它其实对算力的需求是非常巨大的,就比今天的算力再大两个三个数量级,我们都会消耗得掉,因为我们会有很多的细节需要表达,就刚才我讲的那个布料对吧。
包括像头发系统,像这个物理的破坏系统,实际上你想做得好的话,它对算力的需求非常的高,另外一个就是说它的系统对,这个就是计算的复杂,就是那个算法的复杂度实际上也会高很多很多,今天我们做了很多的模拟。
都是做了大量的简化,所以呢这一点的话,当当当我们讲的DISCORTION这1part的时候,希望同学们建立这样一个基础的概念,好接下来给大家讲一个这个destruction的话呢。
提一下就比较常见的应用啊,比如说像PHX里面最著名的那个apex这个系统,就是一个最著名的一个destruction,一个系统,这个早年也是很惊艳的一个系统,那现在的话呢它把它升级到了blast了。
然后呢这个NVD啊,他现在想搞那个ominous,就开始偷偷摸摸的把他的开源协议也换掉了,而且呢那个physics也也不再去维护和更新了,对吧,你懂的,这个这个这个黄教主总是那么的那个英明神武,然后呢。
把我们这个这个这个老百姓的快乐,全部给切断掉了,那么当然了,还有很著名的,比如像那个havoc引擎,当年也是以破坏文明的,那havoc的话呢,自从被应该是被微软收购之后吧,就是非常非常的贵对吧。
而且维护起来好像也没有那么积极了,那么当然了,现在还有这个就是unreal引擎,虚幻引擎的这个KOS的这个物理引擎,那么这个呢号称是完全用XPPT的算法,待会我给大家解释什么XPPT。
然后呢号称是性能最强的这样的一个物理引擎,但是呢就是在目前的行业工业界那么好,就在我们的游戏行业里面,大家实战中用的还不多,所以呢这个东西还有待观察,看它的真实的效果对,接下来给大家讲了这一趴呢。
就我个人是最喜欢的一趴是什么,是vehicle载具系统,我个人为什么那么喜欢呢,因为从我开始会写游戏引擎的时候,就可以,或者说从我动了念头想去写游戏的时候,我就自己想写一个这样的一个赛车游戏。
我觉得这个小车坐起来真的很可爱,我做各种地形,我自己会对着他津津有味的玩个一晚上,完全没有问题对吧,我所以所以就是我一直在想说,一辆小车是怎么做的,那今天呢我就给大家做个简单的这个科普。
就是说在游戏引擎里面,因为这也是属于游戏引擎的一个服务,就是我们一般来讲vehicle是physics engine,PC通过游戏引擎开放给开发者的一个标准接口,那么好。
我们要知道这个一个vehicle怎么做的,其实vehicle啊他的表达有很多变种,比如说这个我们中国大名鼎鼎的,什么叫这个这个什么什么飞车对吧,各种各样的飞车,有各种很炫酷的技术。
很多人认为我是这个什么什么飞车的漂移大神,对不对,那么这个道非常真实的,比如说像FA像need for speed,Need to be honest,我个人觉得need of speed。
不是一个以写实著称的游戏,那个那个赛车游戏啊,我一直认为FA是比较写实的,还有一个忘了叫什么了,反正这个东西是非常拉仇恨的一场讨论,就是每一个每个人都有自己,最爱的一个赛车游戏。
让彼此就互相看不上对方对吧,但anyway,就是说有一大批的这个赛车游戏的话呢,其实是非常非常做的,非常非常真实的,特别像那个dirt对吧,就是那个以拉力赛,越野赛为为著称的这样一个赛车的游戏。
那我们怎么在游戏世界里面表达一个就是赛车,一辆车呢,其实非常的简单,但是我这边讲的是最简单的模型啊,OK我们给他一个这样的一个一个一个,一个一个一个缸体放在上面,那下面呢我放两个轮子,两个轮子是什么呢。
其实就是弹簧对吧,但是这个轮子和地面是有contact,那这个缸体在动的时候,这个地面一直在变,那个缸体一直在动,它就会不停的压缩和和拉伸,那个弹簧是什么,就是我们叫做汽车的悬挂系统。
如果你们回头看看你们家的车啊,你会发现每辆车你仔细看它的轮,轮子的轴承和那个车架连接的地方,都有那种一圈圈的那个弹簧,那就是全悬挂系统,有的车更牛逼的,我记得好像什么空气悬挂,还有什么什么什么液压悬挂。
我就不知道了,反正特别的专业啊,但anyway,他其实你可以把它理解成一个弹簧,那好这样的话这个车如果能动的话,它是不是就是已经能模拟一个车,上下上下翻翻滚的这个样子了。
那这个时候其实车是怎么能动起来的呢,首先它有一个驱动力对吧,Traction false,驱动力从什么地方来,是由engine来对吧,engine其实会输出一个东西,什么东西呢叫做扭矩。
那么大家如果在那个,就是你们如果喜欢买那种越野车的时候,买这种大马力的车的时候,比如说著名的美式肌肉车直线加速之王的话,它实际上那个车最高速度并不高,但是它的扭矩脱口特别大,扭矩大就表示他的那个加速大。
但是这个汽车的扭矩啊实际上是很复杂的,如果真实的大家做真实的赛车游戏啊,我们会写一个什么呢,叫发动机转速,油门和它的扭矩之间的关系,那是一条很奇怪的一个曲线,但没关系。
这个交给这个小引擎工程师去给我输出来,我也不管这个参数,我就读进来了对吧,所以大家如果玩赛车游戏的时候,你们会发现就是不同的赛车,你的这个油门的感觉对吧,和加速感觉是完全不一样的。
包括你买真实的车也是在这边有区别,那么好,这个扭矩啊,它要经过在传统的汽油车要通过什么呢,一个叫档位器,就是变速箱对吧,shift就是我换挡,这变速箱还有什么呢,还有一个差速器。
把这个扭矩给差分到你的各个轮子里面,差速器这个概念比较高端,其实我说实话不是所有的车都有差速器,但是我据说现在所有的新新车都是有差速器的,差速器,我知道以前的理解是什么,就是越野赛车的时候。
他的那个每个轮子它的力量分配是不一样的,比如说我有一只轮子悬空了,有一只轮子抓到地面了,他就差数据会更多的那个talk扭扭矩,移到它这一侧,能抓到地面的轮子上,帮助这个车车脱困。
但我不知道这东西已经成了标配了,这样就转化成你真实的扭曲,而这个真实的扭矩的话呢,它实际上和你的这个这个这个地面上的,这个旋转,这个这个轴,这个这个就是这个半径输出去之后,那么我就可以算出一个什么东西。
算出你在地面上产生的一个真实的,向前的这个力,这个力就是我汽车往前的这个驱动力,所以这就是汽车和地面啊,就往前动了一个技术点,就是说白了它是一个静摩擦力,它不是个不是个叫。
我记得我们以前学过滑动摩擦力和静摩擦对吧,其实轮胎只要不打滑,只要你不弯漂移的话,它和地面的摩擦关系是个静摩擦关系,就是它始终是在那个点上形成一个链接的好,那这个车呢实际上还有一个力是什么呢,是悬挂。
悬挂的一个力呢,其实比较简单,就是说它有一个REPLES,这个车就放在这儿,但是车在跑的过程中动,对不对,如果你这个轮胎放长了,这个车就会往下压,试图往下压,你这个车呢如果比如说从一个坡下来之后。
车身往下惯性气候,他就试图把你车往上顶对吧,因为你有四个轮子,四个悬挂,所以呢这个车你会出现这种,左摇右晃的这种现象,但是如果做的好,调校的好,你这个车本身就比较稳,所以呢它有一个suspension。
就是悬挂的这个动力好,还有什么呢,就是轮胎力,轮胎力其实比大家想象的比较复杂,其实汽车在移动的时候,它为什么可以转向,它有两个轮胎里,一个轮胎里呢是沿着它的,这个就是镜像的这个摩擦力。
就long titude的摩擦力,这个实际上你可以理解成,就是说他如果只是前轮的导向轮的话,它就是一个单纯的沿着前轮的这个,镜像的这样的一个力,这个力的话呢就是你的阻力而已,但是如果是驱动轮的话。
它实际上要加上一个你往前推的这个driver,这个力对吧,它形成这样的一个往前进的这个TXT的这个力,那么关键的一个力是什么呢,就是它的切下面,因为当我们的轮胎打了一个方向之后,你移动方向是A。
但是呢你的轮胎往这样去走了之后,它会产生一个切向力,这个切向力的话呢实际上是一个滑动摩擦力,而这个滑动摩擦力呢,实际上就是我们汽车一个很重要的一个导向力,那么这个力呢它的大小既受制于我的摩擦系数。
其实也受制于我的重心,因为你想大家想想看,我的重心越靠前的话,我那边的压力是不是越大,重心越后,那边压力就越小,所以这个也会影响到我的整个力的分分布,所以其实如果我们解解一个车的导向方程的话。
你会发现你要把这两个力分开算,你才能算出来这个车啊,有多大的力气往一边去转,而且你会发现为什么这个轮胎打了之后,它会有的时候会出现打滑,其实也是这个道理,因为它每一个摩擦力都有上限好。
这是一个最最简单的一个汽车模型,To be honest,但是呢这已经不妨碍我做一个非常简单的,我自己自娱自乐的一个汽车模特汽车游戏了,当然你想做FA,你想做need speed,这个还太远了。
但是我做一个简单的小飞车游戏,我觉得还是可以的好,这个时候的话呢一个很重要的概念就是重心,重心实际上是那个set up max的话呢,它实际上是对车的驾驶的体感影响特别大,但其实它的计算方法也非常简单。
就是你你前后两个支点对吧,前前轮组,后轮组在中间的那个那个重量的那个中心点,就在他们中间找一个点,这个这个点的话,其实很多时候也是你车最关键的一个属性,大家知道对车的重心啊。
特别是小车影响最大的东西是什么呢,至少在汽油车时代影响最大的是那个发动机,因为汽油车有发动机的密度是最大的,一个大铁坨子,放到前面重心就靠前了,放到后面重心就靠后了对吧。
那么这也是那个就是啊到这里面有个细节,就是如果你要做那个轿车的话,其实在早年的很多轿车都是前轮既当导向轮,又当驱动轮的,所以那个就是前驱车的这个啊,待会我也讲了,就是说前驱车的转向力就会比较差,OK好。
那么其实重心的话呢,实际上对车子的影响是蛮大的,就是说一般来讲你的重心如果太靠前的话,当你去做这个车子飞升的时候,它就很容易一头栽下去,这个车子就不太稳定,如果重心偏后的话呢。
这个车呢它会在飞跃的时候相对稳定,大家如果玩过拉力赛车,就会知道哎这个点好像很重要对吧,所以我们经常讲的汽车调校,还有一个是什么呢,就是重心会对你的汽车的拐弯产生影响,一般来讲如果重心比较靠前。
那你骑车拐弯的时候,它的转向力就不足,那为什么呢,其实很简单,大家还记得我们在学那个刚体动力学的时候,讲过,就是有一个叫那个转动惯量对吧,应该是那个叫那个那个叫什么来着,哎呦突然想不起转动惯量中文。
Anyway,那么当那个就是重心靠前的时候啊,你会让相对于那个就是你的这个转动中心,那个转动惯量中心的时候,你的那个转向的利弊啊不够长,所以它的扭矩不够大,所以你的转向是不足的,这就是我们讲就是前驱车。
因为发动机靠前导致它的转向不足,但是像一些跑车的时候,它的发动机会逐渐的往后靠,它的重心就往中间往中间一点,但这个时候呢它的它的驱动呢又在后面,它的导向呢就在前面,这个车的转向性能就会好于那些前驱车。
其实就是这个道理,所以这里面也可以很容易地,用刚体动力学的方法可以讲出来,那其实这而且呢大家会注意,就是在我们在做一个真实的汽车模拟的时候,因为汽车这个弹性系统嘛,因为它车身的地方和那个车的几个轮子。
它有个悬挂,因为这里面还有一个转动的关系对吧,所以它的重心呢会当我去加速的时候,重心会稍微的往后移那么一点点,大家如果自己开过车,就知道会有一种感觉,对我们经常讲的内容诶,好像感觉车子一加速。
整个车头好像稍微抬那么一点点对吧,我减刹车的时候,你会觉得车头稍微按下去一点点,你的重心其实也有一点点的偏差,而这个东西的话呢,实际上在汽车的动力学模拟的时候,也是一个很重要的一个东西。
叫WETRANSFER,对吧好,那这里呢给大家讲一个很有意思的东西,叫做这个就是那个就是argument的这个转向角,它实际上讲的意思是什么呢,就是如果我的汽车的两个导向轮,假设都打一样的方向角的时候。
其实它外侧的轮呢实际上是空转的,它是在那被拖着走的,它的转向力其实是不足,所以呢它有一个数学的方法,就是内侧的轮它实际上转的更多一点,而外侧的轮呢转的稍微小,它指向是一个很远的一个旋转中心。
然后呢以他那个连接线做垂线决定我的角度,这个非常的微妙,就是因为你的车本身是有宽度的汽车,如果同学没开过车,就知道车不像我们的人,我们的人可以这样来回这样运动,但车呢它是个刚体,所以当你做运动的时候。
你其实要考虑到车自身的宽度,其实像这个ark米转向角的话呢,也是考虑到车是个缸体,也就是相对两个轮胎,它的前后关系是不能发生变化的,所以这个时候当你想让转向的时候,两边的导向轮都最大限度地发挥它的。
转向作用的时候,它实际上是有一个小小的角度差的,大家不要觉得这种很高深啊,如果大家学的是汽车的工程学的话,这就是一个标配,就是现在所有的汽车它里面都有这个系统,所以才使得我们驾驶起来。
觉得这个车诶好像很丝滑,但实际上人家做了一个非常精细的,一个数学运算,如果没有这个角度的处理的话,你会发现就是你的这个旋转的话,它会非常的不稳定,它就会变成一个螺旋衰减线。
但是呢如果你有了这个arching这个角度的,这个叫嚣了,你就可以让这个车开出一个完美的弧线,怎么样,很有意思吧,其实其实我是觉得物理,数学这个东西非常的巧妙,然后呢它离我们的生活真的非常的近。
而这个东西的话,当我们在做游戏的时候,你会发现你真的什么都要懂,我记得同学们在留言中在讲课,诶,最后一游戏引擎,怎么我什么都要明白,确实是这样的,因为我们干的活是什么,我们干的是上帝的活。
我们在做一个就是人类世界的simulator,所以我们要符模拟几乎所有的物理规律,所以这个的话呢也是做汽车模拟,很关键的一个点,我们有了这些东西的时候,其实我们基本上就能模拟辆车。
最后给大家讲一个东西是什么呢,就是说汽车的轮胎很多时候你会觉得很简单,我就是做一个简单的这样的一个recast,我就知道了高度,但实际上的话呢在真实的这个赛车游戏里面,我们都会用一个球。
或者用一个圆去做这个sweeping,Sweeping,这样我就能知道跟这个环境真实的焦点在哪里,这样的话你的整个这个运动看上去的真真实,那么有了以上的这些所有的模型之后。
你就用我们前面讲的那种弹簧质点对吧,速度这个惯性这些动力学,你其实就可以作为一个,非常简单的汽车模拟游戏了,而且这个东西非常的有意思,因为你调校它的每一个参数,比如说那个轮胎的摩擦力。
发动机的扭矩和他那个发动机的扭矩,随着转速的变化曲线,包括你的重心的位置,你就可以做出各种各样不同质感的车了,其实我知道很多同学喜欢玩一种游戏,我不知道大家有没有玩过。
就是说啊给你很多的building block,然后呢它有各种各样的物理的,这个比如说发动机的功率啊,它的摩擦力啊,一些连接关系啊,你做出各种各样的小机械,然后比比如说我们去竞速对吧。
我们去这个互相打架,看谁把谁拆了,其实我个人是特别喜欢这种类型的游戏的,因为他给我无限的创造可能性,所以说VIP系统的话呢,它是真的能给大家带来这种感觉的一个系统,所以讲到这儿的话。
我希望同学们应该大概知道,一辆一个车的模拟是怎么做的,但是呢如果我们自己不去写这个VIP系统,也没关系,你懂了这些概念之后,你去看一个标准的物理引擎里面,VIP系统的等于是AAPI的话。
他基本上也是按照这个逻辑去构建,它几乎所有的接口,所以你接下来你要做的事情很简单,只需要调各个参数就可以了,这个就可以造出一辆你心仪的车,但是呢今天这个课程中啊,有些东西我们没有讲,举个简单的例子啊。
虽然我们学会了这些V格系统,但我想问我们怎么去造一辆坦克呢对吧,坦克的下面是什么,是个履带,其实我们几乎所有的游戏,只要一做到坦克这件事情的话,大家都很头疼,因为坦克你想做的很真实的话,它还是蛮复杂的。
因为你仔细看那个履带,他当你地上有一个有一个破破的东西的时候,它的履带还会变形,它那有些轮子可以上来就下来,然后呢有些是驱动轮对吧,而且它是左右转速不同,会导致这个这个坦克的转动。
所以我就讲就是说真的在做物理型的时候,你做下去会有很多有意思的细节,包括在这节课中,我们没有讲解一个东西是什么叫飞行模拟,其实那个就是那个airplane的这种系统。
我曾经有一次就是在国内一个非常著名的一个,飞行模拟的一个一个一个啊一个一个平台,我在那边看他们的后台系统,当时我们打开那个飞机的模拟的,那个物理参数的时候,当时我表示我已经完全看傻了。
但是这些东西呢又是非常专业的,所以这也是物理引擎特别有意思的东西,非常希望大家有机会啊,钻下去就光光一个vehicle,光一个那个比如像坦克,像bot轮船,它的这个模型,船的模型。
包括像那个飞机的模型对吧,其实就很有意思,讲到这的时候,大家是不是脑子中出现了啊,我们可以做一个叫海陆空一体的,这个一个战争模拟游戏了对吧,确实是我也是很喜欢这种游戏的,所以这里面有很多很有意思的。
可以值得大家去遵义那个去钻研,那关于车呢,我们就讲到这儿了,好最后这一节课呢,我们最高能的一个part,就是说给大家介绍一些比较前沿的东西吧,叫什么叫PBD,什么叫XPPD对吧,这个听上去非常的高端。
那首先的话呢传统的E呢,就跟大家就是挖挖这个,这个这个像祭拜一下仙人,那这里面我们不得不去膜拜一下,我们的数学界的这个这个先贤,就是这个拉格朗日,其实大家知道我们现在学的很多的力学,特别是在高中和阶段。
我们学的都是什么,牛顿力学,像我讲的,你是用速度质点对吧,惯性加速度,好像匀速直线运动就能解释整个世界,但是呢这个其实从数学上看并不美妙,更像是一群工程师的想法,但是拉格朗日他的思维方式。
就是有一套完全不一样的力学,叫拉格朗日力学,他的思维方式是这样,其实他把整个力学的规律描述成一系列的约束,然后呢他用约束去反向定义运动,他你会发现一个很巧妙的东西。
就是说所有的运动都可以被反向运动规律吧,都可以被这些约束反向的求解回来,这件事情是非常了不起的,比如说我们假设要求你的这个约束,是这个动量守恒,实际上牛顿的这个啊应该是第一定律吧。
就可以就可以直接退出来,你就必须是匀速直线运动,否则你的动量就是不守恒的,简单来讲就是这样的对吧,那么所以的话呢,就是那个拉格朗日的这个力学,是非常了不起的东西,特别是大家上大学之后,其实我也没有。
大学的时候也没学过,因为我当时学的是啊计算机,但实际上如果大家学的是大学的高等物理的话,可能要接触到这些这些知识,那在我们的物理引擎里面,拉格朗日的这个力学对我们的帮助是什么呢。
就是说他把我们很多力学的计算,变成了一个求解约束的问题,这里面给大家举一个比较简单的例子啊,大家还记得我们在上节课讲了一个,A匀速圆周运动嘛对吧,那这个运动我不管它是匀速还是不匀速啊。
在这里面它其实有一个约束的,约束是什么呢,就是说这个点它始终绕着那个圆点不超过一,就是以围绕着距离为二的方向去去运动,那么其实我们要描述成一个就是约束,我要求它等于零对吧,我可以把这个运动描述成什么呢。
就是X假设是他的那个位置,它的模减去二恒等于零,这是不是就它的约束,那在这里面的话,我对速度的约束是什么呢,速度是你这个关于空间位置的约束,把它对时间上求一个偏导,这个时候我对他求了个导。
那么我对面dd t c x我就这个地方呢,我就用一个就是说我们的求导的展开对吧,这是属于我们叫枣树可以展开的这个原理,你会发现就是说我可以把它变成一个这个约束,关于空间位置的这个导数。
就是DC到DX和这个DX到DT,DX到DT是什么呢,就是你的速度对吧,你会发现你的速度乘上前面就是那个那个约束,关于空间位置的这个导数,它两个乘积的话永远是零,但这里面其实比较复杂,它身上是个向量对吧。
大家先脑补一下,而前面的这个约束关于空间位置的变化呢,这个东西是什么呢,就是大名鼎鼎的夹克比矩阵,其实我在讲那个动画的时候,讲AK的时候就讲过那个DKP取胜的存在对吧,在上一节课好像也提到了一点。
讲课比之上,其实讲课比之上,我觉得真的是一个非常了不起的一个,数学的观察,就是说我我确实是没有办法用一个,用一个很简单很直接的话,给他解释他的这个数学,数学的这个直观的想象,在我的理解中。
就是当我一个系统,比如大家想象一个教练,就是我想构建一个顶,我记得我上次说过,就是那我在思考,就是当我每个东西动那么一点点,动那么一点点之后,最后离我想要的结果,它到底是变得更近了,变得更远。
这个趋势是什么,其实讲课比矩阵的话,更多的表达的是一个趋势的变化量,而这一点的话呢实际上是一个非常重要的,就是迭代法的一个一个思考题,大家如果学过牛顿迭代法,就是我一个方程式让我去解。
我也不知道怎么去解怎么办,诶我随便先假猜测一个值,然后呢我求在那个点上的导数,那个导数呢就是表示这个值我对他扰动一点点,它的趋势是什么好,我就朝着那个最靠近我那个趋势的方向去。
德尔塔X德尔塔X德尔塔X居家,最终我会加到那个点,所以这个夹克比矩阵,你可以认为它就是一个对这个,对这个约束的一个导数,在那个点上的导数,他就告诉你说,你如果想下一步尝试的时候,你沿着这个方向尝试。
你以最快的速度就能收敛到我那个点,其实它最简单的一个数学解释,就是这个解释其实不是数学,我觉得是我个人发明的一个空间学姐,因为我是一个很依赖于空间想象的一个人,就是你让我真的对一堆数学公式我会很崩溃。
但是呢你让我去面对诶,一个空气上的一个弹簧啊,一个支点,一个什么东西的时候,诶,我会想象的特别好,那么其实对于弹簧质点模型里面,你也可以一样的用这种约束去表达,你会发现当你有两个支点XX2的时候。
他可以乱动,对不对,但是它中间应该反满足,这个就是他要回到他的Rest pose,那么实际上它的约束是什么呢,就是X1减X2,它两个之间的距离就是那个模长诶。
他减那个他我们的Rest pse那个距离它等于零,这就是我对一个弹簧的约束,那么我怎么去有了这些约束东西的时候,我怎么去迭代去找他的点呢,这里面就要去讲一下一个大名鼎鼎的PPT的。
这个思想其实刚才我讲的夹克比矩阵对吧,那么假设我一开始有这个点,所有的点在空间上就是X1234,56789 11,直到N,那么实际上呢,我认为他这个所有的约束为零的那个状态,以以那个我们右边的图为例啊。
就是那个实现的那个形状,但我现在很不幸,我在他最外面那个点对吧,你会发现啊,就是说你求出这个函数的这个讲课比矩阵,哎呀这个地方就讲解来比较复杂了,这个这个方面,其实我一点点的讲还是蛮有意思的。
但是呢它最简单的一个理解,就是说在我当前那个点的话,我去求他一个夹克比矩阵,我就知道他的那个取倾向性是什么,它就往哪儿去指,然后呢接下来呢我就要猜我的步伐,那个number mea到底是多少,然后呢。
当我就是永远沿着那个那个他的那个切线,那个就是那个应该叫倒垂直那个方向走一个,我认为它应该的步长去逼近,我要的那个就是你所有的约束都为零的那个点,其实这个东西啊,在解那个就是IK的时候也是一样的。
就当我人身上有很多的joint对吧,每个教练都会自己动啊,我要往这边来一点,每个joint都会自己动,当我到这个点的时候,其实你可以理解成,就是我每个join都试着去动一下对吧,每个角。
那我其实用一个讲课比矩阵,它就会告诉我一个趋势,说如果你想go这个点的话,你这个joint得收起来,你这个专业可能要去打开,你这个专业可能也要打开,这个时候你就能够到上面这个点,实际上讲课比起传套话。
他能算出就是在当前的这个姿态下,你要想靠近你的目标点的话,你每一个约就每一个变量,他应该去扰动的趋势是什么,但这个趋势呢当你的扰动量变大的时候呢,他这个趋势就不准了对吧。
所以呢它会有一个number mea的步长的计算,而在我们的PPT里面的话呢,我们最核心的思想就是说我们不去算速度了,我们也不算什么加速度,我们也不算什么力,什么都不算,我们只算一个事情。
就是说你把所有的这种物理系统,都描述成一系列复杂的关于你位置的约束,因为你就以那个医疗为例吧,它实际上你本质上,这个医疗是有一系列的约束构成的,对不对,那我用夹克比矩阵去算它,在每一个当前的pose下。
我应该往哪个方向扰动,我就一直扰动扰动扰动,但是每一次我都动一点点,动一点点之后呢,我再去算我是不是满足这个约束,如果不满足的话,我把这个过程再重复一遍,所以大家可以把就是对这个PPT的理解啊。
在我看来就是一个啊超级的牛顿迭代法,但是它的核心思想呢,用的是拉格朗日力学的方法,就是说把所有的比如说碰撞也好呀,惯性也好耶,加速度也好,全部我不管你372 11,我全部把你变成了一组的约束的。
这个这个这个这个这个矩阵,然后呢我求出你的这个这个趋势,然后呢沿着你的趋势去不停的去扰动,你的每个顶点,就这么个思想,就是你可以认为它像套圈,一圈圈圈圈圈去逼近那个结果,所以它是个迭代式算法。
那么PPT最核心的一个点就在于,就是说他因为把所有的物理学的规律,都抽象成约束了,包括比如像碰撞,它也是把它变成一个约束了,那你以前在解这种牛顿力学的这种速度啊,加速这些。
可能会导致你的这个iteration或者simulation,不稳定的东西的话,把它给优化掉,所以真实的这个数学啊讲讲起来就比较复杂了,那我们诶有一个传统的异能是什么,就是听大家的意见。
在这节课一开始的时候,同学们就讲课,说要求我们提供参考资料,所以呢我们在这个这个课件的后面几页,就会把PPT详细的这个这个文章啊发出来,因为PPT,它其实最早的篇章应该是2007年的文章。
那篇文章还发表了一个非常小的会议上,但是确实是一个非常巧妙的思想,那么就是说哎呀我的天呐,这个地方就很高能了,就是实际上啊你要算那个德尔塔,其实这里面你可以看到,就是说啊这个公式里面的话呢,啊。
你就算你每一个顶点应该往前移动的,一个小小的步长,而它的德尔塔X的那个方向呢,就是德尔塔X是所有的定点的移动啊,它实际上是沿着这个甲克比矩阵的方向,跟他的那个讲课比值的那个模长之间,一个二次方的比。
这个公式其实啊我自己是真的推导过的,还蛮有意思的,一步一步的推下来,其实特别好玩,就是它本质上是要解个什么方程,就是这边就是说我在C的XK,加上一个德尔塔X之后,这个约束他还是尽可能的逼近零。
它这个里面他做了一部简化,就是我先把这个C的X加DX呢用泰勒展开,把它展开了,然后把高阶项全部扔掉,因为有些是德尔塔X的平方,有的DX3次方,一般在我们这种就是说在simulation的时候。
我们认为德尔塔克非常的小,所以我们会把高阶全部扔掉,然后接下来我们就去求说啊,那我这个德尔塔到底是多少呢,诶他又假设了一件事情,就是说我德尔塔的方向,一定是沿着一个亚克比矩阵的那个,切线方向去走。
所以我认为我是我要选择我要走的步长,拉姆达到底是多少,然后呢他把这个东西呢反向了再带回来诶,就得到了这样的一个方程,这样的方程的话你就会发现你消消消,你就可以反向的算出来我的number a是多少。
算出了NELA,我又知道了我要走的方向,你把NELA乘上,那个他的那个就是那个雅克比矩阵,给定的那个方向的话,实际上就是我们要的这个这个疑似迭代了补偿,其实整个PPT就是这个算法。
我本来不想讲解那个数学的,但是其实这个公式呢,如果大家学过这个高等的这个,偏分分的东西的话,大概能看得明白,包括如果大家读原文的话,其实这是我认为它最核心的一个思想。
所以PPT呢你去理解它实际上是蛮简单,这是一个非常经典的PPT的一个一个代码,你可以发现就是你的约束会在变,你的环境在变,但是呢它基础的循环不会变,一上来我就是按照这个step去iteration。
那首先在每一部里面的话呢,我先把这个就是说所有的这个V,把所有的V全放上去,这里面是做了一个就是半音式的积分,然后接下来呢我去算我把地方全变了的时候,我看有没有碰撞,如果有碰撞的话。
本质上就等于是我给你这个系统加了一个约束,就是说我第一步因为我知道你当前的位了对吧,我知道你的这个这个上一帧的位置了,我其实可以算出我当前这一阵的位置,对不对,但是我当前这个位置算出来的时候呢。
实际上很多时候可能是有问题的,他可能有穿插对吧,他可能钻到地下去了,我这样的话呢,我用这个这个general collection的话呢,把这些科生的约束也也算出来了,好这个时候我就有两组约束了。
第一组约束是什么,是我布料,以布料为例啊,我布料本身我的这个不能被拉升的这个约束,对不对,还有一个什么呢,还有就是说我不能够这个这个这个穿模,我不能够这个这个这个就是说自我碰撞,这个约束。
这约束我也放进去了,好接下来就开始用刚才那个那个方法,就是那个我我认为叫做用夹克比矩阵的,超级的这个打个双引号的这个牛顿迭代法,我就开始每一次按照一个number补偿去迭代,直到两个结果,哪两个结果呢。
一就是我真的把这个所有的constrain的这个,这个这个误差小于某个我给定的epsilon,一个小的值,就这个迭代会一直下去,或者说呢哎哎呀大哥,你已经迭代了十几部了,也差不多了,别再闹了。
那就不迭代了,就放在这了对吧,那么这两个终止条件我们就停止接单,这个时候其实我们就会算出,真正的我们认为在这一帧的情况下,你应该停留的位置在哪里,你应该就是获得的这个就是这个速度在哪里。
那我们呢还会基于这个速度给它加一个dumpling,那为什么这个dumpling很重要呢,因为就是刚才也讲过,就是这个系统的话,如果不加上一个速度的dumpling的话。
这个PPT的这个这个server很可能会不稳定,会炸掉,大家可以试一下,把这个地方关掉对吧,我自己呢这个PPT我是没写过的,但是呢我在读他的原文的时候,他就反复强调这个事情。
就是说这个dumpling是一定要加的好,但是PPT呢其实是一个非常呃,现在来讲是越来越热的一个东西,特别是像医疗的模拟的话,基本上都在用PPT这个思想也可以理解成,就是说早期的物理引擎。
比如说这次我们给大家接的那个joint引擎,它还是传统的这个基于这个就是顶点,基于速度的物理引擎,但PPT引擎就是说PPT,他就说用影视的这种约束的方法去解它的好处,就是说它整个这个解第一个收敛会很快。
第二个呢它比较稳定,不太容易出现异异常的情况,比如像在布料系统里面的话,PPT是一个非常重要的一个方法,基本上大家现在都在用PPT了,那么懂了这个知道PPT的概念的话呢,其实XPPT就不太难懂了。
XPT呢这个东西呢现在也慢慢的越来越火,这也是现在物理引擎一个比较前沿的一个方向,比如说像虚幻五,他自己猛推的,属于自己的那个chaos的那个物理引擎的话,他自称就是用的XPPT,那么XPPT呢。
你可以理解成就是个PPT的一个优化,就是说他在这个PPT中间引入了一个量,这个量叫做stiffness,就是说我的这个约束它到底是一个硬约束,还是个软约束,注意啊,这里面很有意思。
就是说他的这个SYPHUS的话,在那个地方,如果这个约束如果是个零,那个STEPHENCORE是零的话,它的它的导数就是1÷0才是无穷大,就表示我这个约束非常的STEVE,你别惹我,你惹我。
我就把你的能量给你直接炸掉对吧,如果我这个东西其实是可以软软的,没关系,你可以有足够大的弹性和误差的时候,我的这个stiffness是相对小一点,所以它有点抽象,所以他写进去的时候。
都是会用阿尔法和阿尔法的那个导数,就是阿尔法的那个一来做,那么其实呢,这个时候我们如果以前的一个方程又优化了,那个那个那个就是约束方程是CX的话呢,其实我自己对PXPPT的理解啊,在这里面的话。
我只能必须得承认我的理解还比较粗浅,但是大家可以顺着这个思路去看下去,实际上我认为它是把这个以前的约束方程,升格成了一个叫做compliance matrix,就是叫服从度矩阵。
这个矩阵呢其实是什么样的,就是下面写到的这个UX,这个UX的话呢,它实际上你可以认为就是他把CX和CX的转置,中间,把他的STENNESS沉进去了,然后前面加了个1/2,这个玩意儿。
其实看上去好像大家觉得很奇怪,这个一个变化之后,为什么他就诶有点意思了,我给大家一个最简单的我个人的土法理解啊,其实我是特别喜欢用土法理,去理解一个高深的算法,大家想象一下。
如果你把这个约束想象成一个弹簧,那么这个stiffness,你可以把它理解成就是弹簧的硬度对吧,就是它为零的时候,这个弹簧硬度就无穷大,那么它的导数就是虎克常数,那么CX是什么呢。
就是那个那个偏移量就或者叫做误差,你可以理解成位移,那么一个弹簧它的误差偏移量多少的时候,是不是就是二分之1KX平方,大家可以推导一下,一个弹簧所储存的势能。
就是你把它从Rest pose拉开来的位移的平方,但是如果这个不是一个单一维的弹簧,它可能是个多维的系统的时候,实际上你把他这个约束,就会变成一个矩阵的形式,那矩阵乘以矩阵的转置。
中间再加上一个这样的一个STEFFNESS的话,实际上他从他的这个这个数学的逻辑上,其实你可以认为,就是说这个系统内涵的一种势能,它本质上就是让你去优化,让这个势能足够的小,但是这个XPPT。
它有一个很大的好处是什么呢,就是说它可以给逐条的约束,增加它的这个stiffness,简单来讲,就比如说像这里面展示的一个案例,就是那个硬币在来回的抖动对吧,他这个约束呢就是一个非常硬的约束。
这个时候他身边的就会射的很高,你能看到那种非常合理的这种高频的抖动,大家知道其实在传统的物理模拟里面,刚提模拟里面这个case是比较难解决的,那么但是呢对于比如说软的木料啊,软的布料。
或者是一些我们叫做一个一个一个一个,比如说软软的这种,柔性的或者可塑性的形体的话,这个STEPHENIST我就可以放得比较弱,而这些东西放到一起之后,特别是布料对吧,我是比较柔软的。
所以有些约束我其实可以约束的轻一点,那我就可以在一个方程里面,根据对每条约束设定它的stiffness的话,我就可以一个方程把它解出来,这其实是我个人认为XPPPPD最大的好处。
这方面的话呢实际上有很多的专家,其实那个啊那个就是说大家去看那个太极嘛,就昨天我还跟那个胡彦明在讲,我说哎,我们可以Q1下你们的太极的这个课程对吧,那实际上在他们那边的话呢。
其实PPTXPPT的这个SL的话,实际上是啊一个很重要的一个,这个这个就是说这个语言的application,那么简单来讲的话呢,就是XPPT在现代的游戏引擎里面的话呢,已经越来越popular。
这也是我们现在也比较关注的一个方向,那么但是呢很遗憾的就是说,这个东西是刚刚这两年兴起的,还没有经过工业化的大规模检验,其实我们也在看,比如说这个算法的稳定度,这个算法的这个数值的可控性和精度。
是不是能保证住,包括在对于游戏各种各样复杂的场景,因为游戏对这个物理式的表达,它不仅是物理的模拟的真实性,还有很多的可控性,那么这一点的话呢,实际上也是啊现代物理引擎,一个比较前沿的一个发展方向。
所以这里面很那个我们的数学就不展开了,大家记住,这里面引入了一个complex match matrix,在我的理解中,这个matrix的话是一个势能的一种表达,基本上讲到这个的话呢。
我们物理的两节课终于讲完了,讲的我又是嗓子哑了,我先喝口水,然后终于到了大家最喜闻乐见的环节了,就对吧,大家天天问我们说要么不作业,那好吧,那既然我们憋了四节课才会布一次作业的话。
那这个作业的那个量就不会太小,那我们这次这个作业呢,就是基于我们前四节课讲的物理和动画,会把那个jolt引擎接进去给大家,那我们希望大家做,就是一个基础作业和一个就是高级作业,技术作业,作业呢。
我们希望同学们在引擎中实现一个小小的,动画的混合系统,一个动画的状态机,大家还记得我们在上一节课讲课的,这个animation state machine嘛,对不对,那这里面的话。
你看这个角色从慢走走向正常的走到快跑,然后还能跳一下,大家还记得在我们的动画的状态机里面讲过,你比如说这个角色走跑跳跳起来在landing,其实这里面有很多的动画的这个blending的问题。
那么这个肯定是要用到steam machine的,那么这些动画的素材呢我们会提供给大家,那希望大家的话呢,能够在我们的小引擎中实现一个,非常简单的角色的这样的一个状态机,那么第二个呢。
课程呢就是我们想提的一个需求啊,一个要求就是大家实现一个最简单的,Character controller,那么大家知道就是刚才我讲课就是KKCTRL,有很多属性,比如说我走到墙上的话,我不会把它挡住。
而是我能一路滑过去,对不对,而且我也不会穿墙而过,那这里面还有很多的小细节,举个例子啊,比如说这个角色跳起来撞到墙了,如果这个control做得不够好,你会发现那个角色就整个吸在墙上,墙上去了。
因为物理已经不会告诉你这个人会掉下来了,对吧,诶你这个时候还要能让它自己的滑下来,所以这样的话就是还有一点,就是,比如说我们的世界会做的很多的,起起伏伏的东西嘛,这个角色在走的时候,在跳的时候。
比如说他跳起来,他就能真的落到一个表面上,而现在的我们的那个就是啊,游戏在小引擎中的实现的话,如果我没记错的话,应该是非常粗暴的一个recasting,所以的话呢我希望同学们用control的思想。
实现一个真正的control,所以的话这也是我们从6月1号开始对吧,哎呀不好意思,真的好坏啊,6月儿童节给大家补作业,而且同学们现在还有这个考试,我知道很多同学期末考试,很多同学有毕业设计。
毕业季毕业设计应该已经做完了,那么大家如果有兴趣的话呢,可以在未来的这个这个就是几周里面,去挑战一下这个作业,因为这个作业你如果做完之后的话,就表示你真的懂了这个动画系统,真的懂了,物理系统怎么用。
那真的就是一个游戏引擎的使用的基础,那么最后那个大家如果有任何问题的话,大家也不要紧张,就是说到我们的课程的官网上,直接问我们的课程组,因为不论是我这边没有跟大家讲清楚,课程题目是什么呀。
还是说大家真的不知道怎么下手的话,不要不好意思,直接找我们课程组,课程组帮忙,我们会帮大家去解决这些问题,那最后的话呢就跟大家分享一下,我们最喜闻乐见的部分了,就是我们的reference了。
终于我们的104开始有reference,那我们呢课程组的小伙伴还是很用心的,把今天讲的character controller,Rock door,所有的论文放在这了。
还有呢就是大家讲的这个class系统的论文,也放在这了对吧,然后呢还有我们的破坏系统论文也放在这了,对吧,居然还有中文的资料,然后呢还有什么呢,还有我们的这个微课系统也放在这了。
还有刚才讲的这个特别高端的PPT系统,也放在这了,所以同学们如果对我们今天讲的任何一趴,感兴趣的话,就可以在这里面去找到你想要的资料,这个也会以后也会成为我们games,104的一个惯例吧。
我们就在这边立个flag,争取每节课都给同学们提供一个详细的,我们的reference文档,因为这些文档确实在我们准备课课程中的话,都是认真的读过,认真的理解过,确保我们给大家讲的东西。
在我们的能力之下尽可能的正确,OK好,那今天的课程就到这儿了,那个说实话,我们课程组的小伙伴真的非常的辛苦,我现在都有点不好意思了,就是那个很多时候怎么说呢,我认为他们花的精力比我多很多很多。
很多才能准备一个这么高质量的课程,我自己也非常的感动,那那么就是我们一起感谢一下他们的好,那就是今天我的课程的全部,同学们有没有什么问题,我先喝口水,好的同学们有什么问题吗,啊哇哈第一个问题就好难。
同学问我说,为什么游戏里的布娃娃会鬼畜啊,这个问题呢其实就两点吧,第一点的话呢就是说刚才我也讲了,就是如果那个joint它做的不够好的话,很容易产生鬼畜的结果,但是joint约束就算做好了之后。
会不会产生鬼会的,因为在真实的游戏世界里面啊,一个布娃娃系统,它的初始的这个运动,很多时候是动画系统输入给他的,动画系统就在我们前面,第一节课讲那个讲物理的时候,讲课是动画驱动的这个东西的运动。
它是个CONDEMIC物体,就是说它是一个反物理学的一个东西,他输出的例句,输入的那个就是他的那个impose,有可能在某种计算机下会变成无穷大,另外一个的话呢,就是说我真实的物理世界有大量的这种。
比如说actor,他们是符合物理规律的时候,比如说特别像静态的vector,静态factor在这个你去撞他的时候,你可以认为它的那个就是整个质量,和它的那个动量是无穷大的。
所以你会发现很多的REACD的东西,它一旦进入到一个复杂的环境里面,就是你比如说你社死了一个角色,你把这个角色调到一个很小的一个,一个坑道里面,那他整个RAGDOLL的行为就会非常的奇怪啊。
因为有的时候RAGDOLL的约束的话,他让这个人一定会穿过,那个就没办法装进那个狭小的区间,但是呢他又不小心某一帧他就进去了,进去了之后在里面就是这个它的物理的SIMILATION,它就会不稳定。
其实物理的simulation的稳定,实际上是一个非常难的一个问题,所以在我们的就是我经常讲解,就是我们所有的物理解算都是iteration对吧,但是真正好的物理引擎,或者说一个做物理引擎功率很高的人。
它就在于我什么时候stop iteration就停在那儿了,但是stop停的不好的话,你会出现一个就是我们经常讲的就是一个东西,正好卡在一半,卡得住了,好,你一旦卡上去了,你后面除非你给他。
就其实你后面给他加再大的力,至少在物理引擎里面,你是没办法,他两个分开了,很多时候我们得high的把他们两个分开了,其实我们以前在做角色的时候,经常会出现,就是这个碰撞,这个物理仿真没解决好之后。
一个角色就卡在一个地方,他就是也是这个原因,所以RAGDOLL的话呢,因为这个这些所有的action的运动,全是交给物理模拟的,所以有很很有可能会卡在一个地方,或者说很有可能会产生一些。
就是没有办法dumpling掉的这种扰动,这个这种很奇怪的速度量,惯性量,然后在里面来回的系统里面震荡,就震荡来震荡去,第二个问题是同学问,我说就是爆炸和可破坏物体之间的,交那个交互啊。
其实这个东西呢它是由两部的,不是一步完成的,就是当我们在游戏的game play系统里面说,这个地方发生了一个爆炸之后呢,一般我们会有一个叫爆炸区域,爆炸区域呢,一般它是一个沿着中心衰减的一个冲量场。
大家这个很好理解吧,就是我在靠中间的地方冲量就很大,越靠你旁边冲量就越小,当我有一个另外一个可破坏物体,他受到了这个就是它检测到了,说我在爆炸区域里面之后,它其实可以根据你的爆炸的这个。
这个离爆炸中心的距离算出自己的冲量,刚才我们已经讲了,就是说你有了一个冲量之后,我可以根据你的HARDLESS,就算出你的这个这个,这个破坏的那个系数是多少对吧,就是其实就是冲量除杀哈德斯。
然后那个值如果大于我们一开始预设的那个,就是每一个chunk之间的那个connection,那个最大的容忍度的话,那这个时候就发生它整个碎裂或者破坏了,这个问题有点难,有同学问我说有没有实时的音效模拟。
它到底算不算物理模拟啊,实际上的话呢,声音系统和物理系统是两个系统,基本上我们没有,我没有看到一个物理引擎里面它会带声音系统,但是今天为什么我会提到声音和particle呢。
就是说其实这里面就引就引出了,就是物理引擎,如果我们自己做物理引擎的时候,有个很重要的机制叫call back,是他是什么意思呢,就是说当我在某一帧就某一个事件发生的时候,我一定要交给其他这个引擎。
一个回调的一个能力,就是说我知道,比如说呃我现在把这个雕像炸成了十几块,那当这些碎片自己之间发生碰撞,或者碎片撞到地上或者某一个环境物体的时候,我会有一个产生这样的一个call back。
告诉我说诶你到底撞到什么东西,你撞到它的力量角度点在哪里,这个时候其实是交给这个引擎自己去决定,说我是不是产生一个particle,我是不是产生一个音效对吧,那么在很多时候呢,我们不会做的这么精细。
但是在某些特殊的场合的时候,比如说你真的离得特别特别近,或者说呢这个东西特别特别的巨大,那么一些对于比较大的一些碎块的话,我们确实要做一个,比如说这个石头砸到地上的那个声音,包括他们自身碰撞的声音。
那这个系统的话呢,它是两个非常分开的系统去处理的,但是呢中间是通过我们的游戏引擎,把它们连到一起去,那么这个call back也不是说你每次产生意见,产生事件,它就call back,实际上有也。
你可以是这一帧整个物理模拟完之后,我一个query,把所有的这种collision的事件全部拿到也可以的,就是你如果catch的那边对吧,所以它是两个系统,哇这个同学问的问题很有意思。
他说如果我要让物理系统非常的符合现实,那还需要用的controller吗,实话实说,如果极度的现实的话,就不应该有control了,因为我们人的移动的话,不是因为跟汽车一样,就是我们身体输出一个扭矩。
在我们的脚上和地面,脚跟轮胎一样,形成了一个一个摩擦力对吧,让我的整个人往前走,那原则上来讲的话,用物理引擎,你可以把东西全部都做一遍的,但是事实上的话呢,在游戏中的话呢,我们一般不会这么做。
所以这这里面其实就引发了一个,非常经典的一个一个辩论,就是说我们在游戏引擎中,是不是物理模拟做的越真实,越细腻越好,我个人的答案是NO,因为就是说因为我以前在做科研的时候。
我们经常会跟ground truth去比,比如说一个小球,一个烟过去,然后沿着烟形成一个很漂亮的形状对吧,一个小船在水里面,就用那个就是那个那个那个never choke那个方程。
让它模拟各种水面的波动都很好看,但实际上呢当我们在游戏的时候,我个人一直认为游戏的核心,它是一个趣味性的东西,它是一个playable的东西,所以是一个用户自我表达的东西。
所以他对世界的模拟我认为是达到一个精度,它能反映出用户的需求就可以了,而过度追求物理的那种仿真的无限细节的话,实际上在有就从根本的角度来讲,我认为有的时候它是一种destruction,就是一种干扰。
比如说我们经常会看到有些3A大作,它的整个战场环境做的非常的细腻,非常的复杂,对啊烟尘满天飞啊,气氛感足足的,但是你真的玩这个游戏的时候,你发现除了一开始觉得他很酷啊。
但是你玩起来你觉得这个游戏不是特别好玩,因为你大家回想一下,我们在真实的世界里,我们真实世界是上帝写的模拟器,它的模拟精度应该是百分之百,对不对,但是99%的时候,你并不会不会觉得这个世界很好玩对吧。
那其实呢在游戏世界里面也是一样的,所以我认为就是说在游戏引擎里面,这个物理模拟它实际上是一种表达,足够就可以了,而不需要过度追求它的这个细腻度和仿真度,但追求细腻度的仿真度呢,在很多比如说像cg对吧。
就是电影的影视动画里面,这个要求确实是非常高的,他真的要求的非常非常的细,但很多时候我们会用离线渲染的方法去表达它,哇这个问题问的好挑战啊,他说你没研究过虚幻里面五里面,上万个碎片是怎么优化的。
呃实话实说,那一趴我还没有用,还没看到哈,就是还没有真的去优化,但是我在虚幻五里面,我看了一下它的整个效能啊,就是呃它一个很重要的就是那个GPU particle。
还有很多的物理的那种碎片的particle,但是我看到的情况是,他们那个一旦这些东西全开了之后,帧率掉的还是蛮厉害的,就是虚幻五目前的版本好像还是很吃性能的,但是优化的话呢你要仔细看他的话呢。
我猜大概率可能就是把它扔到很多核并行计算,因为其实物理的很多运算它全部是可以并行的,包括甚至我可以用GPU追问的方法,用一些GPU方法去加速它,但真实的从物理算法来讲的话呢,我觉得如果你选择了。
就是说牛顿力学的就是顶点速度法,或者是用的PPT算法,或者他那个cos自己说的XP算法的话呢,SA本身的话呃,应该它的性能应该是基本上是会定在那了,但是呢你可以在很多的hack。
很多的trick把它优化,所以简单来讲的话,这一趴我没有看过,但是我目前自己的体感,就是至少从他的几个demo上来看的话,他的有些demo的这个帧率还是有很大的一个,提高的空间,好的。
是不是就这些问题了,好的好,那谢谢大家,那我们那个两周后见,今天我们终于完成了一个大的section,然后呢,我们下一那个下下周在新的章节界面,好。
11.计算工具箱:成像梯度与处理 | GAMES204-计算成像 - P1 - GAMES-Webinar - BV14B4y177Mv
今天要给大家掰扯掰扯这个image gradient他们的内容呃,我们上一节课是讲到了这个我们就是整个image成像的过程的最后一关,也就是噪声,就我们从一个原始的一个光学信号。
然后我们经过它在物理空间中的传播诶,然后到达透镜,到达透镜之后呢,然后我们会经过一系列的,比如说调制啊,诶最后到达传感器,诶,上节课我们就把这个整个成像的一个过程啊,就给大家完整的描述就是下来了。
然后从这节课开始,我们就开始进入了一个新的阶段,也就是我们进入到整个一个computing的一个two books,就是我们计算摄影里面就是计算的这么一个工具啊。
这套工具箱会有非常多的呃一些有意思的算法啊,然后告诉大家一些啊对一个image gradient的一个基础的处理,其实呃大家如果喜欢p图的话,就是可以经常遇到我们这个整个图像拼接边缘的问题。
就是最早的时候大家可能直接把这个图抠出来,然后边缘阿尔法通道一平均诶,这个时候就把一张图贴到另一张图上了,但是实际上呃我们会有一些更好的办法,就是我们并不是想把一个图直接扣到另一张图上。
其实我们想要看到的事情啊,就是实际上是我们在我们目标图上把这个图像自然的生长出来,诶这个事情就变得非常有意思,呃这个就可以很无痕的把一些图像拼接起来,所以说今天这节课就会给大家呃。
从这个image规定的这个方式开始给大家呃讲一讲这个就computing这个历程,然后呢后面会给大家逐渐介绍一些比较高级的应用啊,比如说像嗯有一个half quetic speeting method。
那就是我怎么样解一个图优化的方程,因为我们呃之前就eming to box讲的就是我们整个成像的过程,我们可以用一个operator或者用一个matrix来表示我们成像的过程。
然后呢呃我们那个这个target function啊,就可以根据这个image formation model跟我们的目标就是感受到了一个信号,诶。
就是给我们第一节课讲的那个嗯这个cost ftg的target cost function唉,通过这个我们就可以解一个优化函数,当然这里面会有非常多的一些约束啊,唉。
我们也学到过这个有这个就weak por跟strong prior啊,vg rider wag prior呢,其实这个我们今天这节课讲到了一个鬼点子。
就是一个非常嗯基础性的这么一个图像的一个统计的先验知识,然后除此之外哎我们就可以呃,也可以在这个约束在这个它的一个复利叶语或者一个小波域去加约束,当然了,有的还可以就是把那个把那个就是我们后面的一个呃。
像learning por或者是甚至一个specific的一个pr去加进来啊,伊万你可以看看他在不在这个直播间里,后面呢有一些display的课会让伊万老师给大家讲解。
对tv norm也是一个呃就是一个很常见的一个image pro,因为像为什么要有这个total variation,total variation,实际上就是我们假设呃这个图像它本身是稀疏的。
或者是它的一个规定性等,man是稀疏的诶,我们知道这个我们可以看到一个图啊,里面有非常多的内容诶,但是我们看到图像的梯度长的时候,哎我们就发现这个边缘的这个点呀,比它整体的一个点是非常小的。
所以我有时候就minimize这个tv n哎这个mini tv是啥呢,是我们经常就是mini ma图像的一个规定的一个tv哎,mini它之前有啥好处呢,比如说我这个图像有噪声的时候,哎就可以加一个tv。
就让它平滑一下,对不对,就可以把这个噪声诶给一定程度上去掉,然后还可以有啥呢,比如说啊我这个两个啊,这个同学说了一个deep image power,这个也是有的,大家解优化函数的时候。
其实可以代入非常多乱七八糟的一个fire吧,就当它的一个呃这个后面的一个约束函数,这个甚至bm c d这种东西都可以搞进去,这个非常有意思的,然后这个整个优化的一些比如说像a d m m啊。
我们有时间的话也会给大家分享一下这个proximal erator,讲完这个之后,我们也会给大家cover一下,就是呃一些一部分常常见的神经网络,就是大家在解决摄影的时候也常见的一些神经网络。
因为这个哪怕现在技术已经做的非常好了,就是学术界大家把技术做的非常好,但是工业界用这个神经网络的还不是特别多,因为很多这个场景它那个能耗跟成本划不来,所以说就给大家讲一些比较常见的一些网络。
然后为什么网络设计成这个样子来对,我们这个底层的这个computer image起作用啊,这个也会给大家分析一下,那这个就是我们整个课堂的一个computing。
就是computing to box这一部分,然后这一部分过后啊,就会给大家分享的一些optical in就是temple encoding,嗯,然后就special the main coding。
但还有一些呃其他其他乱七八糟的一些啊,这个special的一个topics,当然special topics我们会尽量的缩短一下,就每节课的一个内容,因为这个special topics可能太具体了。
大家学起来可能会比较吃力,诶好了,我们这时间差不多了,首先欢迎同学们来到我们的game 204计算摄影,现在摄影目前这个整个工业界的应用应该是越来越广泛啊,今天给大家分享了一个主题。
就是我们计算的一个tall box,也就是它的一个第一课,给大家分享这个image gradient,还有在gradient dm是怎么做处理的。
首先我们要给大家分享一下,讲一下这个在规定性走位我们都有哪些应用,就是大家可能有非常多这个耳熟能详的应用啊,或者拍照啊啊,或者是就是影视制作呀,都有非常多可以直接应用的案例诶,然后造一个简介之后呢。
给大家分享一下整个呃就是gradient跟厂的一些基础知识,然后再给大家讲一下这个就可以积分的一个vector fields,最后呃举一个实例,实例就是一个破松bending,也就是扩充融合。
这个也就是非常好的一种基于规定,然后在一个目标的图像上,就把我们想要的一个融合的一部分给它,根据gradient的分布长出来,它不再是一个抠图往上贴的一个过程。
它是根据gradient一个让gradient连续的,根据gradient连续性让它长出来这么一个过程,这个扩充bin是非常有意思的,他是跟本身啊,就是我们电厂那个破松方程,它是从那个地方借鉴来的。
所以说诶这个地方就叫psbending,然后这个gradient to my image processing,诶,都有啥可以玩的呢,唉然后最典型的应用就是我整个就破松融合,唉比如说我们左边哈。
我们看到左左上这个地方诶,我们有一个我们目标的这么一个呃目标了这么一张贴图吧,我们想把这个这个色块诶提到我们的目标图像上,也就是我们背景底色上有这个色块,对不对,诶当我们发现我们这个如果直接贴的话。
诶这上面的背景跟我们本身的这个图像的柜背景它非常就不和谐,然后怎么办呢,诶这个时候我们有一种方法就叫破松融合,我们可以看一下右边这个都是就是用通过破松融合来实现的,而这么一张图像融合。
这个就基本没有违和感啊,这个大家在很多就是影视制作会经常看到呃,一些像嗯这种便宜的五毛特效啊,当然也不能算是五毛特效,这个还是效果还是比较好的,这个大概是论文是大概是2004年的。
还是2005年的一篇西瓜的论文,自那之后,大家在一个呃这个整个图片上,就整个加上一个这么一个物体做融合的时候,就不再像以前我们这个图形群里面,special effect怎么这么复杂的一个计算。
就这么贵的一个计算就不需要诶,这个时候我们就可以拿一个很低的成本a来把我们想要的元素,融入到我们这个想要的画面里面,啊除了除此之外。
我这个gradient image processing还有哪些应用呢,比如说我们这个玻璃上的一个反射,我要把这个反射去除,这里面就遇到一个什么idea呢。
就我们可以看到左边的一张图跟右边左边的一张图是融合了一个,你看那个玻璃上有一个大概一个黑白棋盘格的这么一个反,射的一个图像,诶我们观测到这个图像有什么性质呢。
我们反射的图像跟我们本体的图像大概有什么性质呢,其实呢这就是基于一个假设,根据图像本身啊,我们知道这个图像的gradient它是非常稀疏的,那样的话我们这个反射,的图像,它的规定呢是不是也是很稀疏的呢。
是不是这个时候就可以有这么一个约束,就是我背景图像跟我们反射图像它的鬼点子哎,这基本上是不太可能重合的,对不对。
我们可以根据这一个image prior就可以轻松的把这个glass reflection给去掉,很还有很经典的应用啊,就是我想p图抠图啊,我把这个图就没有这种边缘,artifc的时候给他嗯。
挪过来挪过去就是或者是拼图啊,这四个色块拼在一起诶,这个时候都是整个规定的动漫imaging的啊,一些就是好处跟应用诶,这个我们可以看到右边这张图完全就像在一张图里面有一种感觉。
当然我们呃搞一点比较花活的操作。
就可以把这个呃白天跟夜晚的景象,我们在同一张图啊,这同一个位置我们拍一张白天的图,拍一张晚上的图,诶我们把这两个图融合起来会是啥效果呢,诶这个我们就可以看到白天跟晚上这两张图融合在一起。
就可以拿到右边的一种很神奇的一种效果,哈哈那下面这个是一种tm的一个案例,就是我们要把and的跟量的结合在一起,然后形成一张亮暗细节都很鲜明的这么一张图像,诶这个就是它在一个tmap里面的内容。
也是在我们规定域去处理的,实际上我们在规定的预处理啊,他就是根据我们在这个他给的image上,我们的规定呢,它的分布跟我们想要的就是就是我们source,因为是鬼脸呢,它是一直在那上面生长。
这个就是我们这个规定动脉的一个问题,因为很多信息都是存在边缘的,啊这是一个比较经典的论文。
大家可以看到这个呃,它是叫intestitute of imaging editing toys,这个就给大家展示了各种各样啊不一样的这个图像的一个操作,但是这个基本上都是根据这个规定。
动漫的一个optientation framework来实现的。
当然我们这个规定的动漫,它整个处理是根据什么样的一个链路呢,就是我们有一个原始的一个original image,诶,我们现在先把这个原图的一个gradient不出来。
同时呢我们也可以对这个鬼脸呢进行一定的操作,哎我们这个时候就可以对我拿到这个鬼点的一个厂了嘛,因为我们比如说一张图,我把这个xy方向各求一个导,哎。
这x y方向我们就从一个黑白的图就变成一个二维的一个图啊,这个图一个是x规定的,一个是y规定的,这就变成一个矢量场了,我们通过对这个规定的field咱们进行编辑,然,后再进行合成诶。
这个时候我们就可以拿到我们这个编辑过的一个图像,它的整体的一个链路是这个样子,然后给大家介绍一下这个呃鬼点子跟厂的一个基础知识,就是简单一点就是我们在一个2d的图像上来定义这个一个vector。
比如说我一个标量场,标量场是啥意思呢,呃就是,它就是可以你可以理解为是就是图像上的一个点啊,它是就是一个标量,然后矢量场的就可以认为一个点上记录为记录了诶,不同的一个就就有两个值嘛。
就是它到rt空间的art空间的一个映射唉,比如说我这个u跟v一个像素上有两个诶,这个就是一个矢量差,然后举个例子哈,像我们那个黑白图,黑白图就是一个标量场哎。
我每个像素点上这个像素阵列上每个点上都只有一个值诶,但是两个channel的一个图像呢,有一个南通道,或者是有一个一个通道是x gradient的,一个通道是y规定的哎。
这个时候我们就一个点上有两个值或者三个值,这个时候它就变成了矢量场,无论是表示颜色的矢量场,还是表示啊这个梯度的矢量场诶,这个我们就可以理解为只要是我一个像素点啊,大于两个值。
这个时候你就可以把它理解为一个web fields,当然更高维的也是可以的,比我们像呃我们的一个视频,我一个像素点上记录了一串值诶这个时候也是啊,可以理解为是一个随时间变化的一个呃。
mac or phd,唉这个怎么去计算呢,我们用这个它叫vector deficial operator,我们有时候把它记成nova,nova就是对xy方向分别求导了一个operator。
然后我们就把这个lava姑且集成为一个2d的一个向量哎,一个就是对x方向求导的算子,然后第二个元素就是对y方向求导了一个算子,然后我们这个规定它这个算子是啥意思呢。
就是规定的算子本身就是我们这个前面的那个nba,然后乘以一个标量场,就是比如说我们把这个拿给我们的这个图像,这个黑白,比如说这个i是一个xy,是一个黑白图像,诶,把它把nank gradient的相乘。
而最后我们就可以拿到他的鬼点子,好,我们可以拿到,你看我们上下第一个元素对x方向求导,第二个方向对y方向求偏导,诶我们跟这个黑白图像i x y作用之后,就可以拿到x方向的梯度,y方向的梯度。
然后与此同时呢,我们也可以看到这个divergence,divergence就叫散度,散度是啥呢,散度就是拉不拉跟一个标量场跟一个矢量场的内积,这个我们知道两个vector的内积啊,它就是一个标量。
对不对,实际上我们就拿到的是什么呢,哪里是对u v对u求x方向偏导,跟v y方向偏的一个标量和,然后克这个是啥呢,克这个叫玄度,大家学电磁场的时候可能学过这个旋度,它是它遵循的一个右手螺旋法则。
它是一个啊,我们这个呃差分算子跟这个一个矢量场的一个cross product叫差成诶,这个插成之后啊,它还是一个我们这两个矢量,插成它还是一个矢量嘛,它是而且方向是遵守遵循这个右手螺旋法则。
然后同样的我们就是遵循我们线性代数里面的这个对角线法则,在这个方程前面的那减后面的,然后乘以这个第三个方向,这个就是我们最后诶这个求它的一个旋度的这么一个结果。
然后呢嗯但是哈本身哈就是刨掉我们最后算出来那个方向,它前面那个系数就是我们呃对这个求他选度的前面那个系数,实际上还是一个标量,就是前面除了刨掉方向,前面就是还是一个标量。
啊求它把我们把这些东西都结合起来看一下啊,比如说我们求这个规定和这个散步,我们知道这个i但是xy对不对,这个实际上就是我们可以看到,德尔塔那个拉姆达x y2 x y sorry。
拿不到i xy等于一个啥嘞,等一个看到对x方向求偏导,然后对y方向求偏导,对不对,我们求叉乘诶,这个nva又等于啥呢,那么大就等于一个round 1 round x,round 1 round y。
是不是诶我们这两个球比差成拿到了什么呢,实际上就是我们可以看到第二第一项乘以第二项减掉个,减掉个第二项乘第一项,哎实际上把这个前面这个合并起来,就得到我们这个规定它的一个呃玄度。
当我们对这个规定呢求散度啊,这个我也看到我们前面我们这个image的briliant,是就是我们这个地方标标标记住的,我们对它求散度呢,实际上就是我这个两个项分别点乘相加起来,对不对。
这个也就是在x方向,在x方向二次求导,再加上y方向的二次求导a这个时候,我们就拿到了一个嗯叫德尔塔r xy,这个嗯有时候这个也叫拉普拉斯算子,叫scholar deficial operator。
实际上你可以理解为是一个啊拉斯拉拉布拉斯算算算子,实际上我们算的时候就可以把它理解为两个这个,拿不拿扇子,的一个内积,对这个就是非常简单,然后我又有没有检验要点技法呢,其实啊简单点记法。
实际上诶我们就run的老是round x,round y,这个也挺难受的,对不对,我们最后就干脆就用一个角标,哎我们下面标了一个x的时候,诶这个角标就是对x方向求t那对y下面角标标了一个小y的时候。
就是对外y方向来求偏导,诶,这个时候我们整个写的时候就会显得非常简洁,然后再看一看我们呃这个旋度的一个计算,你看我们这个实实际上还是我们这个拉不拉就等于啥啥啥小撇x对吧,这一个小小撇y诶,这个叉乘号。
我们这个,i x i y诶,这个时候就变得非常漂亮诶,第一项,两个e相减就可以拿到我们最后的这个规定,它的一个旋度,同样的话,那它的散度啊更简单,a就是x上面写一个y,后面写一个就可以拿到它的散度。
看拉普拉斯算子诶,直接我们就说这么一看,就是两个小x两个小y这对吧,然后我们把这个作用到一个i上,就可以直接拿到这么一个i xx加上i yy,这是一个简洁的技法,我们可以看到我们这个一个图像呢。
它的一个灰度图就是左边它是一个标量场,我们可以看到右边是它的一个呃一个gradient的一个矢量场,这个我们把它这个intensity用三维的一个mesh去表示出来啊,我也可以看到亮的地方诶。
凸的高一点,诶,暗的地方往下凹一点,这个它是一个标准的一个标量场,这些标准的一个标量场,哎当我们计算出它的一个鬼脸的时候。
我们看到我们对x方向求偏导,就可以拿到第一个图像,是中间上面第一个最左边是我们的原始的一个grace skill的一个level图,而我们对x方向求这个偏导,我们可以看到像这种这个是x方向。
像这些柱子这些地方我们可以看到这个鬼点还是很明显的,然后同样的我们对外方向求偏导也是这个方向,我也看到我们这个原本的这个灰度图啊,对外方向求偏导之后,诶,诶确实是因为比如说这条线剪这条线。
它基本上在这个y方向基本上是看不到的,但是呢这里面有个地方需要注意到,我们这个最gradient xy方向分别求偏导的时候,我们是把这一个灰度的一个这么一个标量场。
变成了一个有xy方向的规定的一个呃矢量场,本来是r图到r这么一个空间变换,后来变我们变成了r two到r two的这么一个空间变换,这个时候我们最后拿到了一个两个方向的这个,这个实际上就是一个矢量场。
像我一般啊,就是我们像数学上求导的时候,诶,我们这个喜欢打球呢,比如说就像上面这个我们对x方向求偏导,我们假设有一个微小的变化,这个h h很小哈,诶我们在x方向稍微有点变化,然后减掉原本那个位置。
然后求他了一个,一个里面一个这么一个技巧,在这个极小变化下的一个da的一个变化值,诶,这个时候就是它的一个导数,但是对我们的这么一个离散的图像呢,你要是个h啊,它基本上你要让它是零或者零点几。
这个不现实,但这个时候大家通常就喜欢用哎,我这个都是像素啊,都是整数的,我这个导数不就是实际上就是求差嘛,对不对,我这个单位的一个x方向和y方向的一个变化,诶这个h我设置成一不就好了吗。
这个时候我们这个求这图像的一个梯度就变得非常简单,实际上就是错位的剪,那么一下对吧,但是我们可以思考一下这个错位的剪一下,我们可不可以用一个conversion的一个卷积的方式,卷积的和来去表示它呢。
诶我们现在比如说有两个卷积核啊,左边这个是x加1y减掉个xy,我们现在右边给出来这个两个中一个kl,哪个kl对应着我们左边这个公式呢,我们是加一的位置减掉前后面的位置。
实际上就是后面的位置减掉前面的位置,对不对,实际上我们就可以用一个这种一跟-1的这么一个,简单的这么一个filter替代我们最后啊这个差分的一个形式。
因为这个我们计算这种卷积对我们的就计算机来说它是比较省内存的,就我们当然也有很多vector计算,同学们喜欢只有我们两张图,比如说mac python里面两张图,那么错一位相减a不就行了吗。
这个时候有时候会比较吃内存啊,所以说有时候大家就直接干脆诶搞个小剪辑,就把这个整个事儿就给处理了,但有的时候像除了我们这个错位相减啊,有时候大家还会把这个中心这个点忽略掉诶,我直接我把这个h设成二。
但是我中中间这个点中间这个点忽略掉,我直接x加一的位置,减掉x减一的位置,再除以二,这个东西呢叫中心差分,但这个中心差分有时候就比我们这个直接做差分误差小,当然也不是绝对的,这个就要看具体情况。
但我们可以看到这个最后,x方向我们知道了这个它是在x方向这么一个fs相减,y方向呢其实也很容易啊,我们去把这个x的地方换成y,实际上就是对它做一个transpose,对不对,实际上就是还是一个一-1。
只是换了一个方向的这么一个future,当然这个整体还是非常简单的,诶当然我们这个拉普拉斯算子又能怎么算呢,对不对,我们想一想啊,这个,我们在x方向求为了一次比呃,这就是拉普拉斯,实际上就是两个。
就是x方向求了个二阶偏导,加上y方向求了个二阶偏导,对不对,我们实际上就是把这个x方向求两次偏导呢,实际上就是我这个fter,看跟这个做了两次convolution对吧。
但我们知道conclusion和conclusion之间,这个实际上是对i哈,前面这个这卡做了两次康复注释呢,我们就可以把这个写在一起诶,这个时候这个是啥呢,这个一我知道这第一个,做卷积哈,一-1。
这个一乘以一个-11哈,然后下边这个地方就是,一,-1,-1,然后乘以一,实际上就是,最后我们拿到了实际上是一个一-21这么一个东西,然后同同理,我们在y方向达到了一-21这么一个东西,对不对。
我们把这两个方向的一个拉普拉斯加起来,就可以等效拿到右边这个拉斯拉普拉斯这么一个扇子,也就是一一-411这么一个简单的一个算子诶,这个时候我们发现二阶导实际上就是一个简单的一个拉普拉斯,对不对。
这个拉普拉斯fter也是非常简单诶,中间是一个-4,旁边啊,就上下左右各一个一就完了,对不对,当然我们有时候要注意到我们这个最后求到的这个值,我们还要进行一步下一步的验证。
就是我们最后求着这个拉普拉斯算子跟我们在x y方向分别求两次导,加起来到底是不是一样呢,比如我们看看内部啊,我对他求一个拉布达,实际上就是拿到一个xy方向的一个鬼点子。
我再给他一个做一个divergence operator,就是一个点乘啊,就是他这个算子给他做一个点乘,是不是就等于拉普拉斯特呢,这个我们下面用实验来验证一下,诶我们可以看到这个x y方向的鬼点子。
诶这个我们去怎么验证呢,我们对x y方向分别继续求导,然后再验证,哎我们这个拉普拉斯算出来的图跟我们这二阶求导,然后再相加的这个值到底是不是一样,但这个在我们看到这个结果之前。
就我们需要呃先抛出来两个问题啊,就是我们后面会给,我们后面会给大家讲一下啊,就是整个图像的一个,融合了integration的这么一个过程,但是对这个vector field它是怎么样啊。
什么时候这个可以做这个对这个vc field做了integration呢,它本身是有一定的一些信息或者是条件是缺失的,然后这个我们是怎么样把这个东西给它算出来呢,这个先抛出来两个问题,但像对上一页。
我我刚才给大家问到这个验证这个问题啊,大家呃回去感兴趣的话,可以就是我们分别对x y,然后去求个导,就就拿那么一张图像去求个导,然后再求一个二阶导,把它加起来。
然后呢另一张图直接用一个二维的一个拉普拉斯算子,大家算一算它之间那个差到底是不是零,首先说这个integrable fields,就我们已经就是说有了一个就是这种矢量场u和v啊。
假设啊这个u和v就是两张图吧,就我们可以看到我们右边给了一个例子,就是两张图,我们用这两张图怎么样去拼出来这么一个标量图标,一个标量的一个图i我们两个这么一个原图像。
u和v我们要拼出来这么一个i这么一个图像,然后这个需要满足啥条件呢,就我们追我们假设这个x y u跟v分别是呃,这个这个矢量场就两个元素分别是x方向的梯度跟y方向的梯度。
也就是我们最后的这个目标图像需要满足这么一个条件,对x方向求偏导,就等于这个图,然后对于y方向求偏导,就满足这个图我们需要满足这么一个条件,但我们知道我们这一个规定的求散度,这个它理论上这个值应该是零。
对不对,就是我们之前呃,上次刚才给大家留了个小亏子,理论上我这个,它的这个旋度啊,这个鬼脸的fi长的一个旋度,它理论上应该是等于零才对,因为我们这个xy方向求梯度,y方向求梯度,它理论上应该是相等的。
这个给大家验证一下哈,诶这个rx i y我们求到了,诶我们可以拿到这个德尔塔i,然后ti之后呢,诶我们对这个德尔塔i求它的一个散度,实际上就是让它等于零。
然后最后r x i y rx y跟i y x0 上这两个值应该是相等的,就我们这个可以用实验去验证一下,它这个是相等的,因为本身这个玩意儿这个玄度它本身是一个无源场啊,这这这是一个无源场无人场。
他这个球它的根选度呃呃呃有这是无缘无缘场,有人场无人场,他这个无烟场,他这个深度它就是等于零,这个是可以借鉴一些物理上的一个玩法,但我们知道呃这个时候已经知道让他让这个对规定的field求旋度。
它等于零,然后就可以得到i y x跟rx y也是前后顺序求导,并不影响我最后的一个结果,这个时候它理论上这两个地方就是相等的,这是我们就是对后面做了一个图像的一个integro。
就是integrable,就是呃它的一个前置的一个条件,这个时候我们再看这张图,现在我们已经知道对我们这个目标的这个图像,就我们的目标图像,目标图像对x y分别求导,然后我们就可以满足。
我们就有这么两个条件,但是呢这个又需要满足一个什么条件呢,它的一个3度就是等于零,也就是round u对y方向的偏导,跟round v在x方向的偏导它应该是相等的。
所以说这个就解答了刚才啊这个第一个问题,就什么时候这个integration它是可能呢,也就是我们用散度去check,这个就是我们混合到了这个偏方,偏方程在二阶二阶导的情况下是不是相等。
二阶的一个偏微分,就是x y方向它是不是相等,这是我们的一个呃,就是做那个integration的一个前提条件,对这个同学呃,这个1996同学说这个smart这确实是的。
因为我们图像本身它这个规定太细了,你这个你求它的一个难度,你求它的一个选度的话,他确实理论上该吸的地方就已经没了,它二阶的地方应该就就没了,所以说我们就是i y x就跟i x y连上这个箱子本身。
还是由于这个图像的一个稀疏,图像信号本身的规定呢,它是非常稀疏的,当然我们考虑到这个integration这个问题的时候,就我们想要就重就重新,就是重建,就是根据这个诡异点的重新长出来这么一张图。
它有一些什么样的应用呢,就是比如说我们去通过这个shading来去估它的一个形状,然后还有一个比较好玩的就叫光度立体,大家如果学过这个computer vision的同学啊。
可能会对这个光度立体立体比较手写,就是我们一个光照达到一个物体上,我们去切换它不同的角度诶,这个时候我们就可以,但那相机固定不动啊,我这个光照换到不同的角度,假设我们这个材材料是比较均一的。
我们表本身表面那个abele,这个时候我们就可以计算它那个vector的一个,就是它表面的一个呃那个叫法,线方向的一个fs,然后把这个通过光度立体的办法啊,去把这个呃图像算成一个三维的一个出来。
然后第二个玩法呢就是这个玩法呢啊,就是我们对这个image gradient进行一个操作,比如说像这个tom making image editing啊,或者是这个消光啊,或者是融合诶去诶。
就马赛克这个都是这个image规定直接进行操作的一些玩法,那除此之外我们还可以第三题的一个规定进行呃搞一些玩法,比如说像我们mesh,就我们大家可能马上301。
刘立刚老师会开一个呃这个这个loop divation的这些课程啊,这个match editing这个就跟这个integration,problem有关,当然我们还可以对一些video啊进行操作。
但是我们这个地方我们要实现这个integration的这个问题诶,它会有一个非常大的一个挑战啊,就是我们这些矢量场很多时候就是不大可逆啊,这个它不大好恢复成一个比较好的一个标量场。
就是但是这个时候呢我们就不得不利用一些小trick,就我们有一些近似的一些小trick,来把这个那个矢量场就可以比较好的融合成一个,我们最后的一个标量场,啊这个怎么玩呢,举个例子。
这个第一个例子就是我们这个破松bin这么一个过程,这个破松融合这个这个bblinding就是融合的意思,这个破除融合是啥呢,就是我们之前看到了这个普通融合这么一个例子。
我们可以看到像传统的一个copy piece的,是我们把这一块,传统的一个copy paste是我们把这一块图像诶直接扣过来,然后放到我们的目标图像上,对不对,但是整个扩充融合它干的不是让两幅图像叠加。
这个大家不能把这个东西理解为直接的一个叠加,那这个普通融合到底是一个什么样的思想呢,实际上扩充融合是让这个目标图像在融合的部分,就是根据它的gradient长出来。
这个原图像就是它不是一个简单的一个这个图像叠加或者是抠图啊,在贴上它是根据gradient让它斜率连续变化的情况下,然后让它在我们的目标图像上把这一块想要贴上去的东西给它长出来,诶,这个就很特。
这个就很有意思啊,这个本身它是根据这个本身我们目标图像的自己的特点哎,来生成的这么一个图像,所以说我们最后看到的像右边这张就是呃扩充融合这个图啊,就看得非常自然,就好像是这么一个呃空中花园飘在那里一样。
这个怎么掉了,不好意思,这个刚才手抖,哎我们讲到了第几页了,我这个进进行扩充融合,它的一个核心思想是什么呢,就我们在做融合的时候嗯,就是我们要把这个尽可能的把这个鬼脸让他就连续的呃就表达在一起。
这个时候我们就看到了这个图像诶,就会更加自然,比如说我们从左边那个原图上,我们想要把这两个光源抠出来,放到我们就是第二张图像这么一个目标上面,然后我们像传统的一个copy peace。
我们把这个随便一抠,但是呢我们通过泊松混合图层融合诶,我们就可以把这两个光源,都可以很自然地融合到我们这个目标的一个图像上,这个时候我们就首先要对整个啊进行一个定义。
我们给定了一个source,这就把这个g啊记为一个short image,就右边这个我想要把这一块,但这个也是一个记号,我们要把这个融合到这个目标函数上,这个我们的目标图像是啥呢,是一个把它记为s。
也就是这个地方是一个s,然后呢我们有一个or omega,也就是我们目标的这么一个区域,然后我们现在有一个intemplation function,也就是我们这个啊就是往上插值的这么一个方程。
然后本身呢我对我目标上面,目标函数上面就是我们这边s2 实际上就是我们的目标图像,就是我们这个目标图像,我们把它记为f2 ,我们这个时候想要看到哪个参数是未知的呢。
我们知道这个source function就这个把它抠出来,这个要贴上去的图肯定是已知的,我们的目标底呢这个s大家肯定也是一致的,这个我们目标的区域,也就是我们要贴图或者是抠出来这一块。
这个区域这个时候也是知道的,哎我们最后的一个destination function,当然就是我们最后这个要往上贴的这个区域,这个时候这块也是已知的,未知的是啥呢,未知的其实就是我们里边这一块。
我们想要把这个地方就是an interpret出来的这一块区域,这个f是未知的一块图像,我们可以看到这个f是我们的一个目标,我们要把这个f解出来,在这个omega区域里面。
把这个f很好的跟后面的背景融在一起,我们要解了一个函数,其实就是这个f它是一块区域,但是这块区域每个都有一个小像素,但这个f需要满足一个什么条件呢。
就是我们想要把这个sars就是原图像融合到我们的目标图像上,哎这个时候f需要满足到什么情况呢,我们目标区域内有这个目标区域内,跟我的一个source function,比如像这一块。
第一个我们就想要它的一个鬼点的是两个图像的拐点的相等,这个时候诶我们融合之后跟没有融合之前,这个时候就是本身你你看它这个内容不是应该不应该有改变,对不对,所以说它的规定呢在这个omega区域内部。
我们第二条让它相等,除了这个内部它的规定呢它相等之外呢,我们还要加一个约束条件,也就是我这个背景的一个就是目标的一个背景图像,跟我这个要中间要插出来这个图像。
它的一个boundary应该在这个欧米伽区域的这么一个约束下,也就是在这个德尔塔omega这个区间,里面这个时候我们满足这两个约束条件的时候,我们这个图像我们可以才可以就最后我们拿到了一个融合后的图像。
我们才可以理解为跟之前的啊原图也好,跟之前的背背景图也好,哎都没有一个很大的一个差别,也就是我们需要解决的一个就是内容的规定连续六相等一个问题,第二个就是我们boundary。
就我们边缘的地方啊要比较好看,所以这个不同混合的过程呢就是呃它的一个integrate vector field,这叫nt,它是要需要满足一个叫嗯狄利克雷的边界条件,这个是一个常微分方程,常微分方程的。
第一类边界条件,数学上这个叫啊狄雷克a和边界条件,实际上就是在我们这个图像上这一块,而实际上它就是一个就是这个图像的边缘,这么一个run到omega这么一个区间。
我们想要通过一个呃解一个最小二乘法的时候,来解这么一个呃破松混合的一个过程,当然我们要解一个啊最小二乘的一个呃函数嘛,我们就要先把这个目标函数解出来,我们要先把这个目标写出来之后,才能对它做优化。
对不对,然后呢,所以我们可以看到这个叫rational problem,这个函数是啥意思呢,就是我们要把,德尔塔f实际上就是我们对我们这个目标图像,我们最后的一个目标图像诶,它在x y方向的一个呃偏导。
实际上就是我们目标目标头上的鬼点子啊,v又是个啥呢,那个原图像g我们好把它提上来,那个他的在x y方向的鬼点子,对不对,我们就是刚开始写到那两个方程,就是我们需要让德尔塔f就是拉姆的f等一个lvg。
然后在这个,omega这么一个域里面,然后第二个呢就是我们刚才讲到的一个边界条件,就是我们最后想要拿到了一个integration的这么一个图。
实际上它在边缘的地方应该跟我的这个背景的这个图它应该是相等的,对吧,我们在这个放到omega这个地方应该是相等的,就有了这么一个地方,我们就可以呃解这么一个方程,然后这个嗯我们会慢慢给大家道来哈。
这个第一项实际上就是gradient,这个我们刚才已经讲解到了,这个v实际上就是呃就是source图像,我们需要贴着那个图像的一个gradient,然后呢外面实际上就是在bug上面满足一个条件就可以了。
然后我们可以看到这个nf v,还有这个后面这个呃f star和f前面这个地方是一个标量,它是一个是一个矢量,右边呢实际上是一个标量的地方,让它相等,然后呢我们这个,对我们这个扩充怎么解这个扩充方程呢。
首先我们要可以求一下这个图像的一个按点,对不对,我们可以看到很很容易的看到是像这种目标函数,它理论上是不是就是一个二次方程,虽然说我们大家有很多的维度,因为非常多的一个element。
那本身呢这一个目标函数是一个凸的,是一个凸函数,我们知道凸函数有啥好处呢,凸函数有个好处,就是它有极大或极小值,对不对,我无论你这个用的什么优化方法诶,我这个最后都能解到一个最好的值。
呃当然这个不是满志的时候,这个有可能有很多解哈,但是这个解析值的情况是是这种,我们对这个德尔塔f它求它的一个拉普拉斯,也就是二阶安点的时候跟他这个v的一个divergence,哎。
这个时候我们一阶的地方,已经让它相等了,对我们二阶的时候是不是也得让它相等才对呢,那我们就可以继续看啊,后面的一些故事,我看到就是之前我们讲过,目标函数跟我们目标的一个图像。
跟我们最终的一个融合好的图像,就是我们这个sars图像,它的一个规定呢,在这个我们要融合的区域内应该是相等的,然后呢同时它这个边界也要满足它相当的一个条件,那也就是说我们这个v这个地方就是德尔塔g。
然后我们这这个v求它的一个散度哎,就是我们刚才讲到了一个d i v,然后作用到这个,大不了g这个上面,这不好意思,这个刚才讲那个了,ppt卡了,不好意思不好意思,这个ppt卡了,我给大家再再掰扯一遍哈。
要刷新一下这个,就这个目标函数,就我们可以看到,我们现在有一个,我们刚才讲到了,就是德尔塔f就是nf f的一个梯度,跟这个g的梯度,就是我们source图的梯度诶,应该在这个欧米伽的区域是相等的。
那同时呢我们要满足这个边界条件啊,就是我们最后要融合的这么一个区域,跟我们呃背景这个区域在这个boundary loomega这个区间a应该是相等的,然后在第一项和第二项分别代表什么呢,哎这个就看哎。
第一项就是我们第一步就是在x y方向的规定的分别相等,然后第二步呢实际上就是在帮助的地方,他应该在这个boundary里融合前,融合后这个标量的地方应该是相等的。
但是我们看到这个minimize这个function的时候,它就是一个两个方式的一个sobedience now,它本身这个我们可以看到跟这个一二次方程类似,它实际上是一个凸函数。
这个凸函数有啥好性质呢,就是它通函数有个极值,但我们本身哈还是围绕着这两个条件来看的,就是目标的图像,目标这个图像的一个x y方向梯度跟原图像的x方向梯度应该相等。
然后同时我们需要考虑到这个它的鞍点就是二阶的一个拉普拉斯,这个时候他的二阶拉普拉斯是不是也应该相等呢,哎我们就可以看到啊,就是拉普拉斯就f这种目标区域的一个拉普拉斯二阶导。
应该是跟我们最后一个目标的一个梯度的一个呃散度,也就是他在就是我们这个目标函数的一个方向梯度,再求个3度应该是相等的,因为本身一阶梯度都相等了嘛,这个我们要让它一样看起来一样就变化了,更连续。
这个二阶的梯度应该也是相等的,对不对,说当我们满足还是这两个条件啊,所以说这个,输入的这个uv实际上就是我们source图像的一个x y方向的一个导数,这个就是呃变得非常简单明晰。
当然对这个x y方向的导数给它再求一个呃3度,就他求他一个二阶的一个3度,这个时候诶那这个,德尔塔g等一个,这个跟这个f的就是x方向的二阶导相等,然后我们去怎么样解这个普通方程呢。
让它相等的目的实际上就是国电的更延续,我们看起来会非常自然,怎么样解这个破分方程呢,我们呃其实解这个破分方程啊也不是特别困难,我们前面我们对这个普通方,我这个拉普拉斯算子。
拉普拉斯算子我通常把它写成一个operator呢,它是一个卷积的形式,而且x方向的一个差分,它是一个filter诶,y方向的一个差分,他也是一个一个一-1的一个fter。
所以说呢在我们就是对这个图像进行操作的时候,诶我们就取一个deltf,就是他的拉普拉斯fter进行一个这么一个our plator写上去,然后呢呃我们也可以呃用这个像素相加相减的这么一个过程。
就是下面这个地方,这是一个dissection的表示,实际上就是呃这中间-4,然后其他几个地方相加,然后我们就有时候要解一个线性方程,你怎么把它变成一个线性方程呢。
现在我们拿到的是一个拉普拉斯的operator,对不对,我们这个时候目标就是这个f的拉普拉斯,跟这个就是我目标的一个梯度场的一个divergence,让它相等,诶这个我们写写硬写下来也可以看成这个样子。
那相等我们可不可以用一些线性的方式来表达它呢,就是我们可以看到我们把这个我们的目标函数f,比如说他一个二维的图像,打到这个拍掉,拍成一个长条,我们就把上面这个计算的这个公式。
通过这种拍成这个长条的一种方式来写成一个vector对吧,我们这个每个elements跟它对应的这么一个加减,实际上它就可以把这个拉普拉斯这么一个3x3的矩阵。
拍成这么一个a这么一个长条a然后用一个内积的方式诶,直接就把这个呃线性的表述出来,我们最后的一个b就把它写成a f等于b,a就是一个对应的拉普拉斯的一个matrix,二维不好算。
我就把它拍成一个一维的长条,然后最后我们需要的时候再把它变回去,当然我们要把这个一维的每个像素,操作的时候都有这么一个意味的长条,但这个时候我们就看到诶。
我们要想把所有的这个图像都通通的用一个线性的一个,就是拉普拉斯的一个算子去表示,哎,这个时候我们把它拼成一个大的一个a哈,诶就我们就在对角线上,那你们我们就拿到一个d,然后呢这是一个非常恐怖的一个数字。
因为我们的整个图像是m乘n的,然后每一个点我图像的大小是m乘n,每个点都有一个matrix来表示它,对不对,然后我们最后要对所有的像素,也就是m一个像素,然后把它这个整体写成一个大,的一个matrix。
我靠这个就是a m n乘以m n这么大一个超级巨大的一个mhx,这个大家觉得很恐怖,实际上我们可以看到啊,这中间那个diagonal是一个-4的,然后边上呢我们可以看到还是有一的哈。
因为这因为这个它是一个有一的这么一个地方,所以说它不是一个简单的一个对角的一个简单的一个对角的一个mrx,所以说这个我们有时候就不能用一个一去把这个提出来,这个提不出来啊,对不对。
这个时候我们算起来就非常困难,是不是因为它太大了,本身呢我们也不大好的一个进行直接,简化啊,这但是这个时候也可以用sparse present,就是它大部分地方都是零,基本上也就在对角线上,这个地方有。
那这有多少个元素呢,我对角线上我们知道这个size是m乘n,然后再加上旁边派的一直接上整体的数量,也就是3m乘n这么多个点,就是大家就是可以用spark的,我们不需要用m n乘m n的平方。
n的平方这么多,那么m n乘以三这么多个位置表示也就够了,然后我们要剪让它这个f的一个拉普拉斯,等于这个最后我们目标函数的一个梯度的一个呃散度,我把这个大的方程都写在一起哈。
我这个f是我目标去要求的一个值,我们前面有一个大的一个拉普拉斯的一个呃一个大maxx,那么右边呃是我们因为这个source是已知的嘛,我们这个source。
就是已知就是source的一个vector field,就是我们最后要往上贴的那一块它的鬼脸,然后再散度,再求和散度都是已知的,这个时候我们中间要求的哎,就是中间这个f这个大长条。
这是一个一个m乘以n的一个大长条,哎这个时候我们把前面中间这一块就写,可以写成一个大的matrix,也就是a,就a f等于b,也就是a,a sorry,卡了不好意思,到哪儿了,对就是这个地方。
a f等于b啊,右边就是b我们要求的一个大actor f,就这,但这个边缘的地方要大家要注意一下,就不能直接嗯上来,就算就是有时候要考虑一下这个边缘的,这个就是帮助了一个问题,有时候大家用就是pad啊。
这个或者是直接reflection,这些都是可以的,哎这个时候我们考虑到我实际上拿到的是一个a f减b的这么一个,cost function,我们想要它们之间的一个l尽可能小,那理论上等于零是最好的啊。
当然这个等于零是非常困难,然后这个a f减b它在这里是一个,线性的一个函数,a f减b这个地方是一个线性的函数,是不是不是线性函数啊,sorry,它是一个凸的函数,我们把这个写开呢,这不需要解开。
我们对这个求导就好了,哎我们让这个哎呀我这个笔设置一下,不好意思,我们对这个e s l求导,实际上就是拿到了一个a transport,然后a transport,然后括号里面a f减b让它等于零。
对不对,诶这个怎么写的不好使了,你看我重新翻译一下啊,诶这个为什么不好使了,我们可以看到这个对他求一个偏导,e s求个偏导,我们就可以看到呃,实际上就是a transport括弧af减b来让它等于零。
但是我们知道这个a transport我们就拿到一个让他等于零吗,实际上是我们求它的极值,它的这个极值啊,实际上就是我们最后要求的这个f这个a实际上是非常大的一个matrix。
然后a transport a呢它还是一个m乘m m n的平方,乘m n的平方a这么大一个超级大的一个矩阵,那对他球迷基本上是不太现实的,你不大可能就是直接对这么大一个没水的球逆啊。
这个计算量得是超级巨大,是不是,但这个也有他自己应对的一个方法,就是我们可以看到这是一个af等于b的一个问题,一般的话呃我们会有一些专门的一些pl server,也就是呃类似词汇的一些server呃。
比如说像我control gredients,就是我们叫共轭梯度法,当然我们还有一些像multic grade approach,i preconditional approach,诶。
这些我们就是这个方程到底怎么解,诶,这个时候我们在下一节课会给大家覆盖到呃,怎么解这么一个扩散方程,今天呢给大家介绍了一个就是在古典德曼的基础的一些知识,还有一些呃basic就是我们这个规定到底怎么算。
然,后我们这个integrable vector fields,还有最后啊举个例子就是pm benning,下节课我就给大家继续讲这个破bendy的那个计算的问题,大家有什么问题可以问一下a这么大。
这个这个这个这个零同学问这个a这么大,求你不大可能吧,这个你想这个假设一张图纸一照就一就1000x1000,这个图不算大,对不对,然后他1100兆的平方就是一个哥,就是一个g。
然后一个g的这么一个大的这么一个就一个一个边嘛,一边是一个一个边,就是一个g的像素了,然后另一边又是一个g1 g乘以g,这个是一gg是多少啊,这个这么大是不大可能求逆的,就是大家没那么大的内存。
也不大可能呃去在内存里面反复读写cpu去算算,所以说这个时候啊就会用一些就是iteration的方法,这个方法有很多哈,呃这个会给大家下节课介绍一下这个像ctrl i gradient这种方法。
当然还有一些像传统的一些像贾克比迭代诶,或者是那个牛顿迭代,这个都是有办法去把这个东西解出来的,这个就是我要看一下它的这个能效比,这同学们有啥问题吗,这个可以快速问一下,就上下一课之前。
贾克比迭代是一个比较基础的一种迭代方法,但除了这个之外,我觉得ctrl v鬼脸可能会更好一些,它他这个速度会快一些,当然这个除此之外,下节课会给大家讲一些其他的一些融合的玩法。
比如说像我们这个text诶,怎么去替换别的texture,这个地方也是非常有意思的一些玩法,大家同学们可以下节课继续啊,把这个这这个image规定的这块继续完成下来,这个就非常多。
有意思的image editing都可以通过这个gradient这个操作来进行完成,虽然说这个块已经搞了挺长时间了,这个这块知识应该有了个接近20年了,0405年是一个非常火的那么一阵。
但这个到今天还是挺火,大家有很多地方是可以交叉应用的,特别是我们像tmaking哎这些地方就都可以利用到这个鬼脸的一些知识,因为这个gradient在图像里面,特别是成像里面,它永远都不会过时。
就我们所有的呃这个这个图像它都有这么一个性质啊,第二次作业的截止日期是好像是25号晚上,我有点记不清了,因为作业里面会写到啊,对课前有同学问这个通道开了吗,应该是开了助教。
我记得是把这个第二次上交作业的通道打开了,第二次作业相比第一次作业会稍微简单一些,是第二第一次作业呃,这个当时我觉得很简单,但是后来听大家反,应好像内容有点太多了。
就虽然说每一个环节大家实现起来都没有什么太大的难度,但这个环节一太一太多了呢,就是大家不知道这个环节做的到底对不对,所以说这个时候就不知道就整个串起来,一旦出问题哎。
那就很难找到这个问题出现到底在出现在啥地方,那第二次作业就好多了,我们就实现两个特定的任务,local tommy跟hdr fusion,这个就会好一些,然后期待大家展示一些很漂亮的结果。
就哪怕现在有很多乱七八糟的软件就做出来,融合效果并不好,而且这个第二次作业吸取了第一次,做作业这个教训,然后给大家一个工具软件,可以让大家对比一下嗯。
就最后融合出来的效果跟这个你们自己算出来的效果是不是差不太多,然后就可以check一下,你融合了这个hdr图像,还有你最后tommy变成图像呃,这个正确度大家可以先用我给的那个工具先自己check一下。
大家对这堂课的这个image规定的有啥问题吗,其实这堂课很基础,就是我们我们目标厂目标的那张图跟我们这个sars的图,它规定的应该是相等,然后在帮助的这个地方哎也让它相等啊。
这个我不记得工具人证明了这个,就在下这个作业的时候里面就有这个工具了。
诶难道是我放忘了放吗,这个叫picture not,我要我要忘的话,待会我就发群里好了,对不对,放了是吧,我记得我放了没忘这个事,同学们还有啥问题吗,好没有问题,就嗯再次感谢大家来到gz 204。
希望大家把计算摄影啊继续好好学学这个没有mac os的嗯,这个我不是很清楚啊,这个你可以从官网下一个,就是或者是从再搜一搜,下一个可能是我记得应该是有mac的,应该是有mac的,我看一眼。
如果这个mac没有的话,那就下一个类似的这个问题也不大,对,因为这种软件非常多,麦克也可能有自己的工具,这个大家不用太担心,对好,那再次感谢大家好,希望大家有个愉快的周末。
12.游戏引擎中的粒子和声效系统 | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV1bU4y1R7x5
Hello,大家好,欢迎回到games104现代游戏引擎的理论与实践,我是王希,那个又两周没有和大家见面了,大家端午节休息的怎么样,我知道大家刚刚过完高考完,然后毕业马上要来,我的期末考试,马上要来。
我的接下来就是我的暑假,所以的话呢我觉得同学们最近应该是非常的忙,然后忙到我们最近也是一头转向,今天我才发现我的钟没有对齐,所以我们发现我的时间居然误差了,将近有半分钟左右,下次我们一定把它校正。
然后那个即将来了暑假嘛,很多同学们可能有的大学已经毕业了,然后有些同学准备好自己暑假的安排,反正我的104课程呢就会一直陪着大家对吧,我们继续讲我的知识,讲我的那个维护我的小引擎。
然后同学们也可以过一个非常充实的暑假,嗯那在那个开始今天的课程之前的话呢,先跟大家就是做一些我的社区里面,同学们的声音的一些反馈,首先的话就是上周我们上上一次课程,应该是上上周。
我们决定了我的新引擎的那个名字叫PICO,这个名字还是蛮可爱的,我个人是蛮喜欢这个这个名字的,然后呢我的就是设计师团队呢,就拜托我的设计师团队花了这个一个星期,好好的设计一下新的我的引擎的icon。
然后我们基本的想法就是不要变得太多,尽量继承大家已经习惯的东西,所以我们就设计出了我的新的这个icon,那这个新的icon是个什么东西呢,就是我们查了一下PICO,这个单词的意思是意大利语。
短笛的意思是一种非常小,但是音域特别广的一种乐器,我觉得这个蛮好的,就很像我的小引擎,就是虽然我们是一个小小引擎,但是我们大家一起努力,其实可以越做越丰富,越做越有趣,所以还蛮契合我的意思的。
然后在设计这个图标的时候,它上面设计了很多孔,然后我就问设计师这些孔代表什么,然后我才知道大家的想法是这样,就是说我们上面那个空洞代表的是零,然后呢那个短笛的形状代表的是一。
所以一和零又构建了我的计算机世界,哎我就觉得好胖啊,哈哈就是一下子我觉得这个icon好有寓意,所以的话呢在接下来的话呢,我们还有很多工作要做,因为我们要把那个polo的引擎里面的代码的,命名啊。
文件名啊,还有我的那个GITHUB上的工程名,可能都要发生一些变化,所以这个事情的话,预计我们还要再持续个一个一个星期左右,然后呢争取能够完成我的小引擎,正式定名为PICO这个引擎的这个这个工程对吧。
这也是一件让我们还蛮兴奋的一件事情,另外一个的话呢,就是上周的很多同学已经把作业交上来,我们还是蛮震撼的,就是像这个做的就非常的完备,非常的震撼,怎么样,我觉得任何时候,当我们觉得作业很难的时候。
总会有人超额完成,甚至有人觉得这个作业是不是太简单了,这个我从读书时代就明白这个道理,就是你觉得考试不可能有人满分的卷子,总是有人会做满分,然后就是这像这个做的就非常的好吧。
所我的动画差值blending,包括我的这个那个controller的,所我的这个stepping,还有那个墙上的sliding全部做出来了,我觉得这个做的还是蛮完备的。
其实大家看这个是不是很像一个小游戏的样子,是的,所以我的小引擎代码虽然很小,但是大家基于它做一些你想做的小游戏的话,其实难度并不是很大,而且因为这是知识引擎代码全部开放嘛。
所以将来你可以对它做各种变化的,空间也是非常大的,那么其实呢就是我们也在跟同学们交流的时候,发现同学们做这个作业的也没有那么一帆风顺,经常会踩到一些坑,包括我们自己的同学也试做一下。
然后呢我们总结了一些比较容易踩坑的地方,比如说我们在做这个动画权重差值的时候,因为有的时候不是只是两个动画差值,有时候可能会三个甚至四个更多的动画在插值,因为这个整个控制的状态比较多嘛。
所以大家注意那个动画差值的总权重,一定要归一化,否则的话就会出现一些很奇怪的一些bug,然后呢我们在课程上讲的那个就是动画,blending的时候,一定要用S2,不要用那个简单的一个ENERP的差值。
因为你用一个简单的差值的话,就可能会出现一瞬间,就是当COTAN就出现了钝角之间差值的时候,他就会感觉很不自然对吧,但是那一瞬间它就插过去了,所以的话呢这个是我们在做这个系统的时候,同学们一定要小心。
然后啊另外一个呢还有一个比较有意思的东西,就是说很多同学说哎无论我怎么做,我这个ASM怎么做,我的这个小人的角色都有点滑步对吧,然后总是觉得自己是不是哪做错了,这一点的话呢,我们跟大家讲。
大家千万不要为这个事情这个有太大的压力,因为啊,我们其实这次提供的动画素材量并不够的,因为你真正要做到完美的脚,没有滑步的效果的话,其实要需要大量的素材,比如说人物的斜向移动啊,这些横向移动啊。
我们都要提供一些素材,让这个角色看上去更加的真实,而且这样的话我们在插值的时候,这个误差会更小,但是这一次因为是个小引擎,所以我们没有把它做的特别的复杂,所以的话呢在某些情况下。
比如说突然走跑跳突然变的时候,不是突然跳起来落地还带带一点前移的时候,比如说你跑着跑着突然跳起来,和和你慢慢走跳起来对吧,和你加上加上一点斜向移动等等,复杂的组合情况下。
它确实可能会产生产生一些滑步的情况,所以呢大家的话不要为此而纠结,不要因此而怀疑自己,代码写错了,因为动画系统真的想做到尽善尽美的话,它本身就是非常非常难的,所以的话这些是我的同学们在做上一次。
是上一个单元作业的时候,很容易遇到的问题,所以我们104课程的话呢,就是不会每一节课布置作业,但是呢其实每个章节布置作业,它的难度和他的工作量还是有保障的,就是说我觉得。
如果同学们把我们就前面几节课的作业,都能做得完的话,实话实说,你基本上会对基础的引擎架构是有所了解的,那接下来的话呢进入我们今天的课程的正文了,今天的课程正文讲什么呢,我们就讲特效系统对吧。
就特殊的效果,那核心来讲的话,特效系统的话呢,我们有两大盘,一大盘呢就是粒子系统,还有一趴呢是我的声音系统,其实这个都是大家很熟悉喜闻乐见的东西了,比如说像粒子系统,像这个是星战的游戏。
你们的这个效果怎么样,看上去还是非常酷吧,因为像这种只要塞F对,就SAFI,就是科幻的类型的游戏的话,其实粒子系统是个非常关键的一个系统,它几乎这个成就了我,我们游戏的整体的这种质感的东西。
都靠它来去表达这种打击感呀,这种这种效果感都要靠它拉满,那么粒子系统的话呢,其实是一个非常重要的系统,这里面我们讲鬼泣对吧,像那个老头环,还有像我的这个这个就是啊这几个,其他的像在下面的游戏。
我就不一点名了吧,但是的话我突然脑子里反应为,我突然想把那个什么那个翻译翻译过来,我突然翻译我翻译不过来了,那个对马老师混啊,不是代码混,脑子晕了,没玩法打铁,Ok anyway。
就是说其实啊在我们以前在做游戏的时候,我开个玩笑,就是比如说我们要玩很多的网游的话,你很多时候你的付费都是为特效付费的,为什么就是你发现你充实,让你的角色变得越来越强的话。
它本质上就是把以前那个一个大剑,砍出去的粒子再做大一倍,做大两倍而已,对大家回想一下,是不是以前傻乎乎的,充个648得到的效果,是不是就这样的一个变化,所以说粒子系统有的时候我们开玩笑,就是啊。
是游戏里面这个变现能力最强的这种游戏系统,当然了,我们是做游戏引擎技术的,另外一个就是,我个人还是比较推崇做这种3A型游戏,所以说的话呢,粒子系统更多的是跟游戏的内容去表达。
但这一年反向的也能说明一件事情,就是说其实粒子系统的话对这个游戏的表现力,角色的打击感,游戏的game play,其实是影响非常大的一个系统,那么今天的话呢,给大家介绍粒子系统的时候的话呢。
我会先从相对简单的开始介绍起来,其实粒子系统啊,它最早定义的时候是在电来自于电影行业,并不是这个游戏行业,就是最早的粒子系统引入的话,那是1982年的这个星,那个星际迷航里面的那个。
就是那个可汗之怒那里面的,他他当时做那个效果,他说所有这种fuzzy object它定义了一种叫proc system,就是管他的整个产生以及生命周期中的动画,以及整个生命周期的管理,然后呢。
这个的文章呢就出现在了191983年,就第2年的这个c rap上面,就是那个呃那个就是那个transaction graphics,这是我们在图形学领域大名鼎鼎的一个杂志,我们早年都是这个还是图形学的。
这个这个我们就皇冠上的这种杂志吧,我们一直都是以他为为荣的,那么上面最早定义了这个party system这个概念,那么其实呢到后面,游戏行业逐渐的越来越复杂的时候,我们就引入了粒子系统。
这个我应该大概率应该是在3D游戏时代之后,粒子系统就会越来越普及,那么其实一个particle就是一个粒子,它首先我们讲party system,它最基础的构建元素是什么呢,是一个粒子,那一个粒子。
它你可以理解成,这空间中一个小点或者一个小面片,我的有什么东西,然后呢你可以看到它有几个基本的属性,比如说它的位置啊,它的速度啊,它的尺寸啊,它的颜色啊,包括他现在的他现在生命周期啊。
它比如说它已经产生了五秒钟还是六秒钟对吧,这就是一个很简单很直觉的,比如说我们想象一下,我们一个锤子打下去会蹦出很多火花,那每个火花就是个粒子,对不对,所以说这其实是一个非常好理解的一个东西。
那么每一个粒子呢其实它是有一个生命周期的,生命周期中的话呢,它首先被spawn出来,就是被创生出来,然后呢它有一个运动的属性,比如它有个速度对吧,然后呢它各种颜色也会变化,同时呢它还会跟环境的那个互动。
比如说我撞到一个东西会反弹,比如说我会受到风力的影响,我会受到重力的影响,然后呢诶他还有个生命的lifespan,就是说它的生命的这个寿命,它的寿命到了寿命它会自动消灭掉。
否则的话你不断产生粒子系统的话,这个粒子如果没有死亡的话,整个游戏环境里面的这个粒子会不会越来越多,那这样整个系统就跑不动了,其实粒子系统很容易写出的bug,就是粒子的这个这个生命周期没管理好。
导致系统崩啊,系统的资源消耗殆尽,所以这其实就是一个最最简单的一个,粒子的生命周期的管理,那么这个时候呢我们还有一个很有意思的东西,就是image,就是粒子的发射器,大家想象对吧,就是想象一下。
就是我的这个这个粒子,就从一个小发饰,心里的不断腾腾腾腾腾就扔出来,扔出各种各样的小球,然后每个小球呢,它又有自己的刚才讲的那些属性,它就会形成自己的运动轨迹,那发射器会给他一些什么呢。
有的时候会给他一些随机的初始值,比如说我要表演,我要表演一个像喷泉的东西的话,那我的粒子它发射的时候,初速度不能够是同一个速度,对不对,它之间速度大小是有一个小小的随机,然后呢它的方向有点小小的cg。
这样你看上去像一个喷泉的效果,所以IMMETER真的是,这也是非常好理解的一个概念,其实今天的整个talk的话,一开始的这几part都比较简单的,非常的直观,很很容易很容易理解,然后呢。
诶当我们把很多个IMMETER放在一起的时候,我们叫做一个system,就是system粒子系统,你可以理解成就是这些image在一起的组合,当然了,其实更严格的讲的话。
是这么多的image和它发射出来的所有的party,在正在活着的,或者已经还在管理中的party的一个总和,那么实际上为什么我们要定义一个system呢,因为你会发现在游戏中,我们真正的表达一个效果。
比如像这里面一个火焰燃烧的效果,我们实际上是有很多种不同的particle的,比如说我要有那种就是火焰的本身比较大,比较暗的这种比较亮的这种party,就表示我的火焰对吧。
那火焰从火的根部出来到中间开始变得最亮,然后再叠加到上面也逐渐暗淡下去,那么我上面还有一些飞着的火星,火星又是一名particle,它的轨道又不太一样,还有什么呢,还有烟对吧,你看这三种东西合到一起。
才能形成一个看上去很真实的一个火的效果,其实同学们去看一下游戏中的那种啊,特效的话,其实就是用这种组合方法给它做出来的,那么再举个例子,比如说一个一个最简单的是这个这个石头的,就是被击中了。
这个一个弹药击中了石头爆炸的这么一个粒子,你可以发现它实际上也是有诶,直接击中的时候冲击的那一下的烟尘对吧,往四周扩散的这种,这个比较四散的这种这种炸开的东西,还包括很多碎片。
DEBRICK这种碎片形成,所以说其实我们的effect artist,就是特效艺术家的话,它最核心的研究的就是这个组合怎么样子,我们在真实世界里看到了一些这种效果之后,我怎么用一个一个简单的系统组合。
来生成我们想要的效果,这就是粒子系统,非常有意思,其实也是非常好的理解,那么粒子系统的话呢,实际上它的那个particle sport,实际上如果image它只是在一个点上的话。
我们其实是最常用的一种image,对不对,但实际上呢我的IMETER可以做的更复杂,比如说我可以限定一个空间的区域,比如说我希望你在一个box的这个空间,或者一个SFA的空间。
或者是capital的空间去生成我的particle对吧,当然我开的速度,这样我的形成各种各样复杂的形状,那我甚至可以拿一个mesh,就是比如像这里面一个洞的这个人,我在他身上采样。
然后用他身上采样出来的随机点生成我的party,这可是形成一些更酷炫的效果,所以其实拍这个系统啊,对于比如说啊不仅是对游戏啊,其实对于影视后期特效行业来讲,那都是一个最最重要的一个一个关键性系统吧。
所以我们经常讲那个啊一个电影的特效,做的不好,我们今天会说什么叫五毛钱的特效对吧,那这个这里面黑的东西是什么呢,就是说啊particle如果做得好,你会觉得他非常的效果增益,让你觉得很真实,很有感觉。
如果发这个做的不好呢,你就感觉一群简单的面片满天飞,这就是啊展现出我的粒子系统设计的好坏,还有我的特效艺术家的水平高低,那个就在这地方体现出来,那么其实呢particle呢就是SPA的话呢。
你会发现就是说它本身party sport,也有很多可以定制的东西,比如说我们可以让它连续的随机的哒哒哒哒,往外喷对吧,比如就比如说我刚才讲了一个,喷喷泉的这种案例,那么它也可以变成什么呢。
就是说哎periodic,就是说我到了一定时间随机的碰突然爆发,1111批出来,那这样的话你根据你要表达的效果不同的话,在EMOR这边的话,你其实可以设置各种各样的不同的,这个它的行为模型。
那么当我们这个span就是那个image spawn了很多,particle出来之后,这个particle在这个空间上的这个所有的行为,我们叫什么呢,我们叫做simulate,就是模拟。
那就simulate的话呢,他首先要模拟就是说我的particle,每一个particle出来,它受到的各种各样的立场的作用,比如说它受到重,一定,很多时候我们要考虑它受到重力的作用对吧。
他要受到重力还说了什么呢,空气阻力对不对,还有什么呢,还有风的扰动,比如说大家玩那个对马岛之魂的时候对吧,最有印象的不就是信仰之风嘛,对不对,那么信仰之风的话,他那个就是说就是模拟那种particle。
沿着风吹的那个方向的那种感觉,给你指引方向,所以这三个是我们particle最常受到的力的影响,那么其实的话呢就是在simulate的时候呢,其实就跟我们之前在讲那个啊物理那一趴,很接近。
就是说我每个particle呢,你可以认为就是一个非常小的物理的质点,那么他大家还记得我们那那节课上讲了,各种各样的时候显示积分,影视积分办理时积分对吧,whatever你用什么,其实粒子系统还好。
因为它不是需要严格的物理准确,所以说一般来讲大家就是用最简单的显示积分,就可以了,然后的话呢就是我们每一帧根据当前的速度,根据我受到的力决定我下一帧的这个决定,我受影响的速度和下一帧的位移速度方向。
就一点一点的把它记下来,其实就非常简单,那么这个过程中我正在形成这种一个喷泉啊,或者是往上撒的这种炸弹的爆炸,或者一些各种各样的奇怪的效果,其实这个效果做的其实可以非常的真实,那么其实当我们在。
但在这个赛季simulation的过程中呢,其实我们扰动的不仅仅是它的位置速度,还有什么呢,还有他各种各样的这个这个其他的参数,比如说我要让它旋转起来,这样看上去是更真实对吧,那我们还可以什么呢。
我看还可以改变它的颜色,就是它的颜色在过程中间可以一直在变,比如刚才我们讲了一个火焰,你在做那个火焰的时候,那个particle产生出来的时候,它一开始的颜色可能是暗红色。
到中间的时候是温度最高的时候变得发亮,然后再飞得更高一点的时候,因为温度损失得很厉害嘛,它就会变得暗,这样的话你能感感感觉产生了一个火的效果,其实严格来讲的话,火焰在不同的高度,它的颜色都是不一样的。
大家还记得我们学过黑体辐射对吧,就不同温度的这个辐射体的颜色都是不一样的,那么包括呢它的尺寸,因为很多东西它在扩散,比如像烟,我们做它的particle的时候,他一开始是浓密的小小的。
然后呢慢慢越来越扩散越大,它的它越来越淡,但是呢他的覆覆盖的空间的范围越来越大,所以这些参数的变化,都是我们在做simulation的时候最重要的一个计算,那么这个计算呢一般在早期的PC系统来讲。
其实非常简单,基本上都预先设定好,然后交给artist调整一下它的参数基本够用了,但现在拍这个系统的话呢,已经变得越来越复杂了,那么更复杂的就是说我们还希望这个particle啊。
他在simulation的时候还和环境有互动,举个例子,就是说我们在人的认知中,我们总是会认为你喷出去的这个粒子遇到了,比如说有些障碍物的时候,它会被反弹,它会被阻挡,对不对,那么这件事情呢。
如果我们直接调用物理系统的话呢,实际上会非常的慢,但是呢你想一下,就是说像我们一个系统,动辄就撒出几百个甚至上千个particle,那我们对它的模拟的话呢,就需要一种非常高效的物理碰撞检测算法。
后面会讲的细节,但是呢其实对整个世界的collection,也是这个系统非常重要的一个属性要求好,那么这个simulation的过程的话,就构建了整个particle的生命周期的管理。
那么particle的话呢,每个出来之后,其实大家想象的它并不是一个抽象的一个质点,那么particle是什么呢,particle一般来讲有各种各样的形态,那么最常用的形态是什么呢。
最常用的是bear world bebo这个词呢,呃翻译成中文不知道怎么翻译了,反正就是它就是一种使,就是你做一个面,一个阔的他始终朝向你的camera,就是无论你camera怎么转。
这个b bot总是嘲笑你,我们做的这个事例,同学们把camera freeze freeze出了,就告诉你说,你现在看到这个火和烟,它其实是一群永远朝向你的这个party面的。
但是呢这个单位会让大家有点误解,实际上应该做的是,我无论怎么转,你总是会觉得那个particle总是朝向我的这一点,为什么是它是有用的,因为在真实的在做particle的时候。
我们那个那个每个party的颜色和外观一直在变化,所以呢你可能会被那个变化吸引走,你注意不到说那个particle一直朝着你的转,如果那个particle是一张静态的图的话。
它假如它的阿尔法它的内容不发生变化的话呢,大家其实是非常容易意识到,就是说这个particle是由一个永远朝向camera,camera的比尔波的构成,所以这个是啊我们在做PC系统的时候。
一个小trick,就是说你在做particle,如果做b bot的时候呢,如果这个particle本身尺寸很小,那你没关系,用一些颜色,有些简单的东西你能表达,如果这个part比较大的话呢。
我们一般建议你用animate texture,就是说它的那个外观总是随着时间在变化,这样的话就是作为用户来讲,不会注意到说你是用很多小面片,模拟空间中的一种体量感的东西。
所以这是一个非常有意思的一个小trick,那billboard的particle呢,实际上是particle系统,最经典也是最古老的一个东西,就是基本上你可以认为就是早期的particle系统。
基本上讲的就是比ba particle,但是呢随着游戏变得越来越复杂的时候,我们就发现不够了,比如说我们要表现各种各样的小的,这种碎屑的时候,那你可能要模拟很多的小的这种碎片钢铁。
所以有的时候我们用MARMESH直接作为particle,那这里面注意注意一下,就是说这些mesh的话呢,一般来讲需要有一些随机性,最简单的一个随机啊,就是假设我做不了很多REMARCH怎么办。
诶我把每一个match的T把它转个角度,然后把它大小放缩一下,甚至会做一些XYZ方向呢随机的放缩,这样也能让你产生一种它的不一样的感觉,注意大家在做PC系统的时候,我们一般都会追求一种随机感。
尽量避免一种重复感,所以这里面的话呢是我们在设计作为引擎,去提供PC系统的时候,你会发现你最重要的是给artist提供各种随机的,可调整的量,他们特别喜欢在里面说,诶。
你给我告你把所有的变量都允许我随机一下,这样的话我做出的效果看上去才会自然和真实,那么第三种呢,particle呢也是一种大家可能比较少见,但其实在游戏中非常常用的一种particle。
我们叫做ribbon,Ribon particle,或者有的人叫做ban particle,他的意思是什么呢,就是你的这条particle,它脱出的是一条光带。
大家想象一下这个particle什么叫有用啊,实际上是在这个打个比方,比如说我们在游戏中打出一条这个一根,那一根很厉害的这个加了魔法的剑,那个箭的尾迹在空中,是不是打出了一条漂亮的抛物线的那个丝带。
而当你有很多很多人这样去做的时候,是不是就形成了一条一条的袋子,这种东西就是ribon particle,那么rain particle呢,它的它的核心的点是什么呢。
就是这个particle在飞行的过程中啊,它会不断地拉出一个一个一个额外的控制节点,然后呢他认为我是应该有一定宽宽度,把这一个个的控制点连接在一起的,这样一个绶带,这个东西在很多我们在control。
比如说轨迹对吧,或者我刀剑划过去的一道弧度,上面是非常有用的,基本上我们在游戏里面,要表现出一些空间的这种时空滞留感,比如打出一个气功弹对吧,一个一个气功波打出去。
这也是一个很典型的ribbon text啊,BON那个particle,那么rain particle的话呢,他实际上呢有一个小小的挑战,就是说如果我们只是把这一个个的离散点去,我们连接在一起的时候。
你会发现我们连出来是一条一折一折一折的线,所以呢当我们真的在去实现这个ribbon,particle的时候的话呢,我们一般会采用样条曲线差值,大家在前面的动画系统啊,物理系统啊。
还有更前面的rendering系统里面,应该对我们的样条曲线,应该是这个非常熟悉了吧,那这里面给大家小小的科普一下,一般来讲在做ribon particle的时候,他们我们一般会用cut more曲线。
那为什么用cut more曲线呢,第一个就是cut more曲线比较简单,大家还记得cut more曲线就是一个啊,应该是个二三阶还是二阶的,一个一个PANORMAL的公式就可以直接插出来。
那么第二个的话呢,它可以严格的保证你插出来的这条曲线,是通过所有的控制点的,所以呢这样的话呢,我只要在这个控制点之间再插入若干的点,形成一小节一小节的这个transition的话。
那整个这个特效看上去就会圆滑很多,所以的话呢这个当我们去大家做游戏引擎,如果你要做project系统的话,一般来讲你提供这三类,比如说bill board,这个mesh和ribbon particle。
按照刚才我讲的,就是你要加入一些尽可能多的这个随机扰动,然后呢你做ribon particle的时候,一定要注意加入那个cat more的这个插值曲线,让这个texture。
让这个这个插值出来的shape看上去性能的平滑,那你基本上就可以做一个简单的小的游戏引擎,用的PC系统了,其实十几年前啊,我们在做帕克系统的时候,差不多也就这些东西就够用了,那么其实呢这个系统的话呢。
它从基本原理上来讲非常的简单对吧,当然我的我的强调一下,我在前面这一趴讲的party系统,都是最基础的party系统,但是因为这门课还有些门基础课,所以给大家讲的就是最经典的。
particle系统的核心要素,那么其实呢就是这么简单的party系统,当我们真的去做他的绘制的时候,你会发现我们有很多的挑战,那你们最大的一个挑战是什么呢,哎我的老朋友又来了。
大家还记得我们在讲rendering pipeline的时候,我就讲过,就是说其实啊透明物排序是我们游戏渲染中的,挥之不去的一个噩梦,因为它非常的就是你非常的这个非常的,这个常用。
就是到时你到时候你都会用到,但是呢如果你做不好或者做的效率特别低的话,效果就会一塌糊涂,就觉得像这个粒子里面,就是说如果你一次看这些透明我的话,那你排序的和没有排序的结果的话,看上去感觉是完全不一样的。
那么它核心的点就是我的画,透明物永远是要从最远的那个透明木画的,最近的一个透明,我这样一层层的覆盖,这样的阿尔法布兰妮的结果才是正确的,如果我的顺序是乱的,其实我产生的结果也会是乱的。
人的眼睛一眼就能看得出来,那么这样的话对于系统来讲的话,这就是个超级大的问题了,因为大家想象一下,在场景里面我去做一些玻璃墙,做什么东西,我大不了做个几十块也就不得了了对吧,那我去那个绘制它的时候。
实际上也还好,这个排序我还能排得出来,而且每一个范围基本能够控制,但是大家想象一下这个系统,我在游戏中动辄就能产生几百,上千个这样的一个beer board,那我怎么去排他们前后关系呢。
那么这里面呢就有两大流派,第一大流派呢就是说哎我全局的进行排序,就是说我不管你是用哪个particle系统,哪个em特性的particle,你比如说有的有的,有的系统产生了50个particle。
我的系统产生了100个party,我的系统产生70particle,我把你们这200多个particle全部合到一起拍,就像这里面的粒子就是绿色的,是一个immature existence。
红色是ISTENCE,他们之间的话对于每个particle来讲,他们之间是交叠的,那没关系,我就自己按顺序排,那这样我排出来的结果就是正确的,但是呢在真实的这个大家就知道,因为排序你越多的元素参与的话。
它排序的成本就越高,而且因为我们每个派系统绘制的时候呢,实际上我们有很多参数的设置都是要求一致的,那你这样的话来回跳的绘制啊,其实成本很高,实际上在很多的particle系统里面的话。
我们只能按EMETER进行排序,就是说诶你这个在前在后,那这样的话两个靠得非常近的IMETER,就会产生什么问题呢,就会产生这样的,就是说哎你看虽然其实真实的情况。
绿色的particle和红色的particle之间有很多胶底,但是你现在看上去好像所有的绿色都在前面,因为绿色的那个IMETER可能靠相机稍微近一点,这其实是我们在party系统非常常见的一个问题。
就是如果你们看一些早期的游戏啊,他经常就是当你的相机发生动的时候,你会发现比如说有些smoke column就是烟柱,还有一些什么特效,它会突然一下就闪动了。
这这种情况下一般就是particle sorting出了问题,但是如果今天大家在写游戏引擎的话,特别是入门的话,我会建议大家先不要去写那个global的那个shot,因为那个写起来比较麻烦。
而且后面会讲到一些GPU更复杂的一些算法,你先写一个最简单的per imeter sorting的话,能够解决你部分的问题,但是这个锁定它如果不解决,产生的后果是非常严重的,比如这里面这个粒子。
里面那个就是那条带子的那个ribbon,它就是一个particle,它实际上是穿过这些particle我的眼中间而入的,但是因为他的bounding volume,是总是在靠近最靠近相机的。
所以它会被排序到最后,所以你会觉得那个那个光标它是穿过,就是浮在所有的烟之上,那么你再看下面一个例子,就是如果我用global shooting的话,我就是把这个ribbon的每一节。
和你的这个particle进行排序的话,你会发现诶看上去好像现在的结果就对了,所以大家看看,所以说其实transparency的物体的排序和渲染,其实是游戏引擎里面特别要仔细去处理,随着现在的这个游戏。
它的环境越做越复杂,真的就是我们很多游戏里面那种气氛感,都是有大量的particle,大量的我们叫做ambient的东西让你感觉出来了,比如说我们举个例子,比如说我们表达一个一个你到一个地方去。
这个环境的感觉,你可能在那走,你没有意识到,但是我为了让你觉得这个环境是真实的,你的脚下可能有几千上万个那种大气的,微微扰动的particle在那流动,所以你会觉得这个地方的空气,就这个地方环境是活的。
是有很多互动的,包括你的脚走出的每一步,风吹过来的落叶,天上这个一些鸟雀在飞,这些东西才让你觉得这个世界是真实的,所以说一个好的游戏和坏的游戏,其实对于这种particle系统的依赖度。
其实差别是非常非常大的,就我们讲高质量的游戏的话,那么其实的话呢,particle系统的sorting的话是是一个挑战,另外一个还有很大的挑战是什么呢,这也是大家很多时候,我经常会意识不到的一件事情。
就是说其实啊那个系统看起来非常的简单,只是一些简单的诶,每一个粒子这样移动来移动去移动来取,但是呢它很多时候是我们游戏的性能杀手,为什么呢,我们绘制透不透明的物体啊,无论这个世界多复杂。
我们只需要绘制最后一个像素,什么意思,就是说当我一根视线看过去,我可能看到非常多复杂的几何层次,对不对,但是呢我有一个叫z buffer,z buffer会把所有后面的最后面的东西全部滤掉。
只留下最靠近我的眼睛的那个点,然后呢我对它进行shading,特别是deer的shading,就是说我所有的屏幕上,比如说100万个像素点,我只需要设定一四,但是当我们去绘制透明物的时候,但是透明物呢。
如果这个透明物来自于环境还好还好,因为你一根视线看过去的话,那你顶多也就看到过,比如说七八个透明物就不得了了,但是party system那简直就是丧,就是这个怎么说呢。
我称之为叫trouble maker,就是说你面前有一个烟的一个爆炸,然后呢,其实在你眼面前迅速就可以怼出几十个,甚至上百个,有你整个屏幕那么大的这个particle。
然后所以我们以前经常叫做overdraw,就是说同一个像素我被绘制了多少次,那大家想想看一个屏幕大小的particle,它就是1100多万个像素点对吧,那么我怼他个就是几十个甚至上百个的时候。
那就是几个亿甚至十几个亿的计算量级,那其实你会发现游戏的帧率就会迅速的下降,所以其实在游戏中的话,它这个系统很多时候会把你的游戏的帧率,迅迅速的下降了,所以在现代游戏中的话呢。
我们基本上会用的一个技术就是half resolution,什么意思,就是说哎我服了你了,你很厉害,那我怎么办,既然你是这种很faster的东西对吧,那我怎么办呢。
哎我把屏幕的resolution整个减少一半,当然了,我要把z buffer也减少一半,然后呢我把你这些所有透明的物体,特别是particle全部在一,就是1/4的。
就是那个像素数量就是half resolution,就是XY都缩小一半,它的总像素量是不是少了四倍,然后呢我把你这些透明物渲染上去,注意这里面有个细节,第一就是说,如果你的Z是在这个已经当仓破了。
这bug之后的话,那就不需要绘制了,第二呢,你这些所有的particle的这个这个啊,这些透明物的这个这个算出来结果的话,一定要集体算一个阿尔法,然后呢,这个阿尔法再和我的这个就是前面的。
OPAC的物体进行blending,当然我的blending的过程是一个up的过程,这里面做一些简单的差值,一些变化,一些扰动,我就能得到一个非常不错的效果,其实在游戏引擎里面,现在越来越多的这个渲染。
我们已经开始用half resolution了,这个好处是什么呢,就是说我们会发现在现在游戏里面,随着我们游戏显示器的分辨率越来越高对吧,之前是1080P,我讲的是大概啊差不多有200多万那个像素。
如果是4K的话,那就是差不多接近1000万的像素对吧,我们后面还有8K的显示器不得了,那就那个像素量就特别大了,就是说即使在现在超强的GPU的话,我们也做不到全尺寸的渲染。
所以我们一定会用当山坡林的方法去做,当然了,这里面有讲到了著名鼎鼎的,比如大名鼎门,像大力水手DRSSR,就是其实up sampling down sampling的,就是用低精度的绘制。
然后再用一些算法把它放回系统网站,其实是现在渲染里面一个非常常用的一个技术,那么当然在帕克斯里面的话呢,希望大家去写的时候一定要小心,就是说它非常容易出现,就是你觉得一个很简单的效果。
突然把你的游戏的帧率就降下来,但这里面我们还有一些更更多更复杂的算法,比如说以前我们在做PC系统时,如果我们发现这些particle离相机特别近的时候,我们会cut掉一些particle。
就是或者说我们用一些其他的方法,就是降低那种就是在同一个像素点上,重复化的这个particle的数量,这也是一个非常重要的,particle系统的一个功能好,那么讲了这么多的话,其实part6系统的话。
它最大的问题,无论是绘制,其实还有一个它的本身,simulation对效率的影响也特别大,因为对于现代游戏来讲的话,我们很容易在一个场景里面,可以达到几万甚至是上10万的帕克数量。
我们才能产生我们想要的这样的一个效果,那么这么多的particle,我的每一帧都要对它进行各种各样的这个,计算处理,实际上对于CPU来讲是一个很重大的负载,那么大家想想。
这种东西是不是天在我的rendering讲过GPU,对不对,GPU是干什么用的,GPU是不是特别善于处理这种海量的并发的东西,所以呢这个时候大家就很自然地想到说。
诶我能不能把这个系统直接扔到GPU上去管理,但是呢particle它有一个比较复杂的东西,是什么呢,它有个生命周期,就是说它不是说一直在那算,而他每时每刻都会有新的particle产生。
也会有很多particle死亡,那这里面的话,我怎么在这样一个简单的GPU硬件上,实现了它的模拟呢,那我在这节课的话呢,不讲不讲的特别细,但是给大家讲一个基本的概念,所以同学们如果有兴趣的话。
自己想写part这个系统,我会建议就是大家写两套,先去写一个CPU的particle,接下来呢,按照我接下来这个课里面讲的这个思路,也尝试写一个GPU的版本,其实GP版本蛮有趣的。
那么首先的话呢我们去想说唉,我们怎么把这个pk系统放到GPU上去,你会发现有很多很多的好处,比如说第一个我肯定可以用GPU的并行化的算力,对不对,另外一个就是说我去读z buffer。
我去对frame buffer进行各种各样的处,理和计算的时候,实际上不用再把以前的z buffer再去读回来,进行处理,我直接可以全部的在这个就是GPU,你全部搞完。
所以这是一个最简单的GPU particle的一个框架,对大家会发现他所有红色的区域,以前是在CPU里做的,现在全部移到了GPU,那它具体怎么做呢,其实他的思路非常的简单。
第一个呢我们会定义一个叫particle pool,这个铺呢大家想想看,就是诶我用一串标准的数据结构,描述了所有的particle的描述数据,比如说你的位置,你的速度,你的颜色,你的尺寸。
你的其他的一些meta的information对吧,比如说你的texture uv,whatever好,我定义一个标准的数据结构,那我假设我的整个系统的容量最多的容量。
10万个particle在我的系统里面去,然后呢我再管一个东西是什么呢,叫做DEADLIST,就是说这个是我的上限,那我现在所有的一个part都没有,那我的DL是满的对吧。
我再存一个值叫deadlist count对吧,就是我说哎我现在有这个这里面举个例子,假设是八个,然后呢我还有一个什么呢,还有我现在需要活着的party list,现在一开始是空的,但这个时候。
当我一个image在GPU里面产生了particle的时候,哎我假设产生了五个particle,这个时候呢我就从那个DEADLIST里面,从尾巴开始去取五个空位出来,大家想想这是不是一个标准的一个。
就是这个这个这个一个链表的插入,这个这个插入和那个释放的操作,对不对,我我是啊,这个这应该是个是个队列,就始终从它尾巴上去取它的数据,应该是个站吧,应该是个站,我使用松尾尾巴取数据。
然后呢我塞到我我的列表里面去,这样的话我三四我就取了3456号particle,说是活的,我把数据填上去了,然后呢DEADLIST里面只有三个数据了,这样我就知道现在有活的particle了。
然后这个时候呢我在GPU里面,假设我的时间take又往前走了一步,我就开始算了,我的哪个particle活,哪个particle死,我发现当然了,我首先要看我的所有活着的particle。
我的particle不用管,我所有的活的particle进行一次simulation,我发现诶6号particle已经死了,那怎么办,那我从就把6号particle加到dead list里面去。
同时的话呢其实呢我对particle那个active,那个alive list0啊,其实进行traverse的时候,我同时在写下一个friend lilist,我的叫做alive list1。
这个时候呢如果我认为我的自己还是活着的,比如像345我的没问题,我就三写一个一下五,四写一个一下,五写一个一下,当我去similate party6的时候,发现六六死了。
那我把6appended到DEADLIST上去,同时的话呢我就skip掉,往LEVELIST1里面去写六这个编号,然后呢接下来我再走七,这些东西在CPU上写的是很好写的,对不对。
但是在GPU上好不好写呢,在以前的GPU上是很难写的,但是自从有了computer shader之后,这事就变得非常的简单,因为computer shader提供了一个就是原子操作。
就是你可以在一个一组计算中,我可以设置一个就是全局变量,这个其实它叫一个局部变量,然后呢啊我们可以保证它的原子性,我的就是说我我虽然是BACHELLE在运行,但是当我去读写那个变量的时候。
我们都是保证它的原子性的,所以这是确实是COMPUSHA一个很好的一个属性,所以这样的话,我实际上用了一个简单的双8buffer的这个策略,就可以每一个tick在GPU中啊。
在那个就是那个computer shader,其实也是GP了,computer shader中算出来每一个particle,它的生命周期的变化和它的属性的变化,然后呢。
把它反向的更新到我们活着的这个particle,列表里面,和死的particle列表,这样呢我再做个buffer swaring,我就得到了下一帧我要绘制的particle。
那么接下来我在做一件什么事情呢,因为我的这些数据全在GPU了,对不对,接下来呢我还能做一个更大的一个优势,就是说我可以在里面做view frost calling。
那为什么这件事情再做起来就非常的方便呢,因为啊其实view first colin呢,也是个非常简单的计算机,它特别适合用GPU去算,那么我这样的话就可以得到一个所有visible的。
就是说可见的particle的列表,这样的话,我又进一步减少了我要绘制的列表的数量,但这里面有个细节啊,同学们说诶为什么我view russian calling那个alive list。
他不会反向的去改变alive list,这是为什么呢,因为其实一个particle是死是活啊,他跟你看不看,但是没有关系的,大家想想看,比如说我这边射出了一群一群烟火,你不去看它,它还在空中飞,对不对。
当你回头去看他的时候,如果你因为上一帧看不见它,你把它从那个活的列表中给干掉的话,一回头的时候是不是他就没有了,是不是该产生了一些很奇怪的效果,所以的话呢。
就是接下来的计算全是view dependent了,也就是说particle simulation是跟view是没有关系的,所以你simulation出来,所有在在我的周围环境中活跃的particle。
我会再做一个单独的叫view fluster calling,我就把你这些particle给你给取出来,然后接下来我还做一件什么事情呢,诶我还可以去做这个跟depth buffer进行这个。
进行这个比较,同时呢我还要做什么呢,我还要去做他的这个就是sorting,Sorting,我也全在GPU里面做,但是我会讲sorting的细节,然后这个时候我基于这个alive的particle的话。
我声称我要我要去渲染用的vertex和index buffer,这样这个这个地方的话呢有很多小细节,但这些细节我相信同学们自己研究一下,都知道怎么去写,所以这其实就是个GPU。
particle系统的一个非常简单的一个思想,其实这个思想很好用,非常好用,其实你们在做任何的,就是这种集群性的这种运算啊,这些这个东西的话都可以按这个思路进行管理,因为你一上来构建一个P。
知道我所用的计算的上限,然后呢用一个LIVELIST,就是活的active的这些东西的列表,就指向一个它的数据的index,然后呢哪一些被recycle,就是我们叫dead list,就是死亡的列表。
然后这两个列表之间的index来回swap,来回交换的时候,就能够完成一个对一个很动态的系统的管理,这是一个非常常用的一套结构,那这里面就讲一个细节,就是因为我的product系统最难的东西是什么。
是排序对吧,sorting就是我们刚才讲了,如果你不排序的话,而且我们希望的是什么是global sorting,这么多particle,我们要在全局的排个先后,那以前这些数据都是在。
就是在这个就是我的组组内存上,然后我的CPU是可以排序的,那就是用我们在数据结构里面教的最简单的,比如快速排序法呀,什么什么这个这个这个冒泡排序法对吧,N平方当然没有人会用冒泡排序法了。
那么哎我们还是能排序的,但是现在问题是我到了GPU上,我怎么排序呢,那这里面的话呢其实有很多很好的算法,我这边给大家讲几个最经典的一个思路,就是叫mega salt merge,Salt。
merge salt的话呢,他的想法其实非常简单,就是就是我们在学排那个排序的中,有一个方法,就是我们把一个大的数列的排序,分解成无数个已经排好序的数列的整合的过程,也就是说。
比如说我第一步把所有相邻的两个元素,大小排序排好,我就得到了无数个小小的已经排好序的数列,对不对,然后呢这个时候我在每两个一组一组合,因为你那边已经排好序了,所以呢。
我其实把你二进四的时候就会非常的简单,这里面你会发现就是我这个排序的时候,只要用log n的时间就可以了,然后我四进八的时候,因为你两个独立的四的数列也也好,其实我每一次每个地方我选取一个元素的时候。
我只需要我自己的,这个时候我自己数列也不用找了,因为我知道后面的数据一定比我大,我只要在你的那个数列中去查找呃,有哪些数据在我的前面,他怎么去,其实非常的简单,就是一个二分查找法就可以了。
所以的话呢这种merge salt的思想是,每一步我的计算都是log n的,然后呢诶我整个这个计算的复杂度,其实就是那个呃,就是那个就是n log的一个一个计算。
所以这个其实是一个非常快速的一个计算方法,那么回到回到我们在GPU上去做这件事情的话呢,你会发现有两种非常简单的策略,就是我得到了无数个数列,比如说我在问我的,就是我找到我的每一个元素的时候。
比如在已经做得好的元素里面,我取一个放到我的,这个就是啊我的目标数列中的话,我会去问说我能不能放在这个位置,其实呢你只需要找你自己都不用比了,你跟别人去比,跟别人去比的话呢,你只要在别人那二分查找。
如果你发现别人,那个上一次那个游标节点和你的节点之间,没有冲突的话,你就可以把它放上去,这个具体的算法讲起来就比较比较用语言讲,特别的麻烦,这个最好要画图,那么这里面的话呢,其实你会发现。
就是说这个时候你的SHADER就可以写了,因为你每一个SHADER的话,其实就是对于每个数字,每个元素,他只需要自己去和另外的那个,就是source的那个数组里面做一次二分查找,就可以找到自己的点。
那么这样的一依次找下来的话呢,你就能够得到最终一个已经排序好的节点,当然了,这里面其实是有一篇参考文献的,我这里就不不展开了,结果到时候我们在会后的话会把文献给大家,这个作者呢他就做了两个比较。
他说啊其实在GPU中去进行这种sin的话,是一个很常用的操作嘛,那么左边的第一种方法的话呢,是一个非常符合人直觉的方法,也就是说我把两个source,已经排好的数组都变了一遍。
然后呢这个过程中我就能得到我想要的结果,但是呢它会出现一个什么问题呢,就是说啊他在写的时候,它的地址是一直跳来跳去的,那么这个写的时候一直跳来跳去的话呢,会让这个magic coherence。
a cash coherence降得非常低,他说如果你想象一个就是几10K,几十和几10K的东西进行排序的时候,这个内存跳起来就会非常的大,他说这个效率其实是非常非常低的。
那么他所以推荐我的做法是什么呢,他反过来去算,他说我对于我的目标那个矩阵上的任何一个点,我在两个source的这个这个这个数列上的话呢,去寻找我该应用聊的那个元素,然后呢这个反向的去找,这样的话。
我每次写的这个顺序就是12345,一路写下来,他说这种方法就是max2是更好的方法,具体的实现的话呢,同学们自己去研究一下,但它最核心的思想就是,如果给你两个已经排好序的数组。
你怎样把它合成一个排过去的速度,这其实是以前的,就是merge排序法的一个最核心的一个一个思路,但是在GPU上的话呢,你需要考虑到就硬件实现上的这种可行性,那么基本上在行业里面我们用的比较多的话呢。
是第二种方法,确实他可以依次的去往那个做得好的数字,你去写,而这个东西的话呢,又是我们在GPU上实现系统特别重要的,一个小的技术细节,但是同学们听不懂啊,没有关系,因为我这边其实我觉得我也没有讲清楚。
因为具体的来讲的话,那真的就是一个数字,一个数字去移,让你去找那个数字,但是的话呢大家看了这个参考文献,看了他的PPT的话呢,应该大概就能明白我们这节课讲的这个算法诶,好像我们这个PPT。
是我没有把参考文献放上去,我们下一我的课后给大家补上,那么其实呢,在其实当我们把整个这个particle放在GPU上,还有个好处是什么呢,就是说哎我们可以进行更复杂了,比如说我的碰撞,那碰撞。
如果让每个粒子真实的和物理的这个引擎啊,大家还记得我们上节课讲物理引擎吗,都结算一遍,那个速度是很慢的,所以呢其实在行业里面,大家很多时候用的是什么呢,就是那个用我的death buffer。
就是view dependent,就是用screen space这个深度,我们模拟出一个空间的这个几何形状,然后呢particle在这里面进行碰撞。
所以呢我们直接从depth buffer里面去取它的值,然后呢跟这个就是particle进行碰撞,这个效果呢其实还是不错的,像这个结果就是一个典型的。
用那个就是说screen space depth buffer,然后呢我们做这个碰撞,其实很多时候他肯定是远远好于没有,这个就是collision induction and particle。
所以这part这个系统永远都是在效果和,这个就是计算效率之间,做trade off的这么一个系统,好,其实呢系统呢,我前面讲的这些都是比较基本的实现,比如像gp particle。
现在已经基本上成为现代引擎的一个标配了,对吧,然后的话呢但是呢其实party系统它做的深的时候,有很多更复杂的应用,举个例子,比如说我们要展现一个人群,Crowd。
就很多很多的这个这个人或者是鸟或者是动,其实大家以前觉得诶这是不是物体在上面走了,这其实呢在很多游戏产品中,我的引擎中提供的是一种particle,系统的这种能力,比如像这里面对吧。
大家看到这些人跑来跑去,它其实就是product系统,那么这个东西它是如何做到呢,像这个是星战里面的一个demo嘛对吧,那么其实呢,它实际上把这些游戏里面的这些角色,变成一个个的就是mesh。
这个mesh是一个particle,我的PC可以卖,注意啊,这个时候这个mesh的话不仅是一个mesh,它还是可以动的,我在每个顶点上我去存一个,它受控于哪个B,注意。
这时候因为我是用particle所说的相对简单一点,所以我就不用那么复杂的skinny,所以我每个顶点的一般来讲我只存一个,就是影响我的BB,就是大家还记得我们在讲animation讲过。
就是如果没有skinny的话,就是一个骨骼,就是每个顶点只受一根骨骼控制的话,我们会出现一些骨骼转起来就断裂对吧,不会像sky那样看上去那么真实,但是没有关系。
因为就是你都已经那么小了这个particle了,我们不会注意到,就是当这样动的时候,这边会产生一个小小的裂缝,那么有了这样的一个就是skeleton。
和那个就是最简单的skinny的information的时候,哎我们就可以把这个这个小小的particle,它所有可能的动画,就所有状态下的动画状态,1234567对吧,这个动画和在这个状态的时候。
他比如他在他对他速度的影响,它是往前走,往后走,还是停止全部CODEC成一个texture,然后呢每个particle它不是一个simulation,simulation的话。
我把以前一个简单的一个加减乘除,比如速度加减变成一个什么呢,变成一个状态机,就是每个particle的话呢,他在就是在自己的这个每个时间点,在状态机之间来回切换,这个时候大家发现没有。
particle系统变得有点意思了对吧,不再是那么简单的,只是速度加位移加重力了,其实particle每个系统内部,就是每个particle内部,可以维持一个小小的状态机。
这样的话它可以在这些状态中来回的切换,那我再做一个更复杂的,就是比如说我如何让它在这个世界上去,流动起来,那就最简单的说我给他一个速度,那所有的人都是往一个方向走,给一些随机,这个当然看上去是OK的。
但是想象一下,如果我要我要表现这样的一个效果的时候,实际上呢我希望它是沿着道路去走,我不希望他走进建筑物,对不对,这里面的话呢它就会形成一个厂,这个厂是什么呢,就是我们前面讲过的SDF。
就是这个就是带正负号的这个distance field对吧,就是有正负号的distant field的话,他就会告诉你说,哎你现在是在inner还是在外面,那么随着你的那个就值越来越接近零。
我就知道你越来越接近某个障碍物,那么呢我这个我有了SDF之后呢,我可以算出整个场景比任何一个地方,它的这个空间的那个,就像一个道路一样的一个导向图。
这个导向图的话呢我们叫做directional field,那么它只要存两个量就可以了,这个时候我给这个任何一个particle,就是一个角色有一个指引性,比如你在这个点sport。
我说你应该去那个方向那么好,他就会受这个就像受了一股力的影响一样,就在这里面就开始飘起来了,然后你你在你看起来,你觉得这个人在动,当然了,我的particle的那个state machine里面的话呢。
其实我会加入一些随机量,就是走到一半的时候,我会让他产生一些随机的状态切换,这个时候你在看到这个party的时候,就会觉得他真的非常的真实,这是一个非常有意思的东西,在这里面你可以看到这些角色。
它会绕过这个障碍物,然后呢大体上往一个方向去走对吧,甚至我可以加入一些状态,就是哎如果我看到有其他的particle,我会相应的把它避开来,所以其实这个在crowd模拟的话,它最核心的底层系统的话是。
就是particle系统的这样的一个一个方向,实际上这也意味着,就是part这个系统,和大家最开始的前面讲的那个过程,那个东西的话呢不太一样,就前面讲的其实是非常简单的,或者我们叫做古典的系统。
而现代派系统的话呢,其实比大家理解的要复杂的多很多很多,那这里面举个例子,比如像这个例子,这个例子是我们取的unreal,最新的几个demo的粒子,其实我觉得做的是非常非常的好。
就是你会发现就是mesh对吧,它可以从mesh变成一个image,形成很多的particle,然后经过一些控制的路径之后,他又回在这些party又汇聚成另外一个mesh,然后呢又产生很多的行为。
然后呢我从一个可渲染的mesh,又把它打散成各种各样的一个一个一个碎片的,Particle,这些所有的动作其实它都是通过系统来实现的,那比如说讲一个更更有意思的,比如说像这种群体的模拟对吧。
这个好像以前我们叫做swan这个系统,它其实也是用particle,jim particle呢,他会感知到主角的位置啊,环境的一些变化呀,去吸收一些环境的信号量啊,跟环境的几何会产生一些互动啊。
这些其实在现代游戏中的话都是非常重要的,一些系统,所以大家去理解今天的游戏引擎的perk,系统的话呢,就是说实际上它的复杂度,已经远远超过我们最原始的一个理解了,那这里面的话呢给大家举一个简单的例子。
比如做早期的park系统的话呢,我们做起来其实蛮简单的,就是哎我们预先设定好几种IMASTER的造型,然后每个IMETER开放各种各样的参数,让artist去控制,然后呢。
我们在预先设定好各种各样的particle的类型,就是一个emit,你选择发射什么类型的particle,然后每一种particle我给你设定一个,比如说你是个mesh particle。
你我就可以说诶你要用哪个几何,你对他哪些东西进行什么样的扰动对吧,然后你觉得产生影响的效果,如果你是ribbon的话,我就会说哎你的这个颜色变化是怎么变化呀,你的这个伪纪怎么个脱法呀。
等等一大堆的东西啊,那么实际上就能产生很多我们想要的效果,通过这些imeter particle的组合,就能定义出各种各样的效果,但是呢在现代的游戏引擎里面的话。
其实从每一个particle的simulation,就是一个PARTIC被打出去之后,他在这个生命周期里面,到底发生了什么样的一些变化,比如说它怎么样通过UV的变化。
让你感觉那个particle一直在变形对吧,比如说我要读取环境变量,我需要知道我周围有没有一些啊扰动我的东西,或者说我周围最近的一个neighbor,particle是什么等等。
这些变化的量其实都要读取,那么包括image本身,它其实也是要读取,也是可以去让用户自己定义的,所以这一点上的话呢,其实我们再看这个现在particle的系统的发展,就是这些同学们需要有所了解的。
我个人认为就是做的最好的是虚幻引擎的,NIAGARA的这个最新一代的这个particle系统,因为他确实是把过去的那种,故我们基于stock base的这种particle系统。
和完全基于这种脚本化的可视化图,脚本化的这种part6系统全部结合起来,虽然那个系统非常的复杂,同学们如果研究的话,就会发现他非常的复杂,就是我们做过一个分析。
就是说整个ARA代码中将近有100多万行代码,就是这个系统,大家想象一下,就这么一个PARTIC系统,写了100多万行代码,大家想想这里面有多复杂,但是确实它对于现代游戏来讲的话。
其实是非常重要的一个系统,所以这也是我们games104这个课的这个精神,就是说呃我们会把最基础的,最基本的概念叫告诉大家,同时的话呢我们也会告诉大家,就是说这个行业最前沿发展到什么方向。
所以我个人觉得就是说,如果同学们真的想精专于particle系统的话,我觉得以这个系统NIAGARA系统为为蓝本的话,花个就是几个月,甚至半年的时间去深度钻研的话,我的收获是非常非常大的。
这也是游戏引擎的一个灭一个有意思的地方,就是说他任何一个子系统都足够,大家钻研足够久,这是一个非常有深度的一个一个一个行业好,所以讲到这儿的话呢,基本上把我们游戏的啊,最重要的一个粒子系统讲完了。
大家是不是有点觉得哎,没有想到原来粒子系统这么有趣,可以做这么多有趣的东西,确实是他可以做的东西非常非常的多,当然这里面我们也要感谢我的artist,其实在游戏公司里面有一个角色叫做。
Technique artist,他们其实也,我认为他们也承担了非常重要的研发的角色,是在用他们的聪明才智,他们的想象力,使得我们这些工程师啊,就是越来越这个广阔的,越来越深入地意识到。
就是这些底层系统它的可行性,它的可能性,所以的话呢其实粒子系统从它最早一九差不多,现在有30多年前,40多年前提出来啊,整整40年,1982年40年了,那么到今天的话发展的这么庞大而复杂。
这里面确实有我们很多technical artist的贡献,所以差不多讲到这儿,我们的粒子系统基本上就讲清楚了吧,给大家就是浅尝即止,点到为止好,那接下来呢就给大家讲我的SD系统。
这个其实受制于我们课时的安排啊,所以说我的特效系统只有一个课室,然后呢就是我们既要把粒子系统讲清楚,要把SN的讲清楚,其实实话实说,这两个这两趴都可以至少支撑一个完整的section。
其实甚至两个两个section都是可以的,所以的话今天的话呢我在讲这个声音系统的话,对游戏来讲的话也只能是浅尝,就是讲到一些最核心的概念,让同学们有概念,就是说在游戏引擎中,声音它到底有多复杂。
他到底承担了什么关键的一个角色,因为其实力粒子效果系统EFFEX4M的话,一般来讲粒子系统和声音系统是不分家的,就是很多效果系统到最后你一定是要挂生效了,没有生效,那个粒子我看上去就非常的假,对吧好。
那我们就讲什么叫声音,那首先的话呢就是audio,对于声音对于我的游戏来讲的话,是一个非常重要的一个组成部分,它基本上是对用户对这个世界的认可感知,互动性对吧,包括情绪的带入,完全是依据声音。
所以我个人一直都很,我认为在每年的一个TGA啊,上面有一个很重的奖,就是我的最佳音乐奖和最佳声效奖,因为这两个奖的话,其实是非常考验团队的水平的,就是而且好的这种游戏作品的话。
这两个东西做的绝对是没有问题的,绝对是让你觉得哇,那个音乐让你一下子情绪就带进去了,那个音效真的让你身临其境,比如说以前让我印象特别深的,比如像DESPACE死亡空间对吧。
包括像那个就是那个啊就是死亡搁浅的声音,包括像很多恐怖游戏的声音,确实你会发现那个sound engineer,就是生效工程师和sound designer,实际上是这些游戏的真正的灵魂。
那么sound为什么这么重要呢,我给大家举个例子,就是大家看这里面这个视频,完全的安静对吧,大家觉得嗯这好像看上去是一个恐怖游戏,但是好像没有任何的感觉,这就是个就是一个镜头。
但是我们把声音真的放出来的话,大家感受一下,我都不想停了,因为我特别喜欢那个带着别人玩恐怖游戏,因为我特别享受,看别人被吓的这个这个花容失色的样子对吧,这是所有男生的这个恶趣味。
所以说实话就是我觉得那个就是声音,其实对游戏的影响是直接的,因为讲一个进化学的理论啊,就是人的大脑是从脑干开始发育的,那么脑干是什么呢,就是大脑最开始是感应,就是在这很古老古老的时代啊。
实际上它并不是有思维的器官,它是个感应周围环境振动的习惯,所以我们对震动的感知是从脑脑干开始的,所以声音你会发现一个特点是什么呢,就是说他对你情绪的影响是最直觉的,我相信很多同学都有这样一个经验。
就是如果我让你看一部电影,我把他的声音关掉,你看了之后,你其实会觉得很奇怪,你没有感觉的,但是如果我把画面关掉,只听声音,其实你脑子中是可以构建这种画面感的,这就是因为声音。
它对人的这种认知的影响是更加fundamental,更加本本的呢,这也是我一直在讲,就是说在很多的游戏引擎设计中,大家会对audio这件事情不够不够重视,或者说在做游戏的时候吧。
大家对audio不够重视,但是我认为真的一个好的游戏的话,声音是非常重要的,因为它实际上很多时候,相比我们做那种很炫酷的画面来讲啊,他真的是一个事半功倍的东西,其实很多好的游戏音乐都是没得说的。
比如说像陈星汉的journey对吧,那个音乐一旦响起的时候,我的感觉就不一样了,所以说这一点的话真的非常的重要,那么声音的话呢,第一个亮你的感觉就是音量的大小,我们叫做volume对吧。
那音量大小本质上你可以认为就是声音的振幅,那么我这边有一个小小的音频,大家感觉一下注意啊,有点刺耳,就大家可以感觉到这个声音的大小,在发生变化吗,这当然就是单一的曲子,所以你听着特别的难受,特别的单调。
但这就是声音的基础,那么声音的音量是什么呢,其实呢它本质上就是你感受到的,空气中的压强的变化,声音其实它主体是一个纵波,就是空气被压缩弹开,压缩弹开一个纵波,当然了,这个纵波本身也会导致一定的横波。
那么它其实在单位的面积,就会给你产生一定的压强对吧,那这个压强呢就是你感受到音量的大小,那么我们经常接触到的一个音量的单位,是什么呢,叫分贝,那分贝怎么来的呢,给大家讲一下。
就是说其实呢分贝它是一个非常有意思的一个,始于我认为是人体认知的这么一个概念,就是说它首先定义了一个叫最小的分贝为零的,那个那个压强,最小人类能感觉到那个压强,那个压强它描述是什么呢。
就是大概一个蚊子离你3米发出的声音,诶我跟你讲,我看到这一趴的时候,我是特别有画面感的,因为我夏夏天的时候经常被蚊子招惹,然后我就觉得嗯确实是3米之外,有蚊子向我靠近的时候,我就有感觉。
我就特别想跳起来,一下子拍死他对,那就是我们人类能感知到最小的声音,你看到没有,进化还是很有道理的,就是让你建立的最低,低到的远程预警雷达的声音,那么它基于那个文字拍动,产生的空气压强下的那个声音啊。
我们以它为基数,那其他的声音的话呢,以它进行那个就是log的对比,就每十倍我们一个台阶,然后这个台阶呢我乘上个21,也就意味着就是说分贝为零,就是3米之外文字的上翅膀对吧,那分贝为一是二是什么概念。
就是那个声音产生压强的十倍对吧,那分贝为40就是100倍,那60就是1000倍,所以大家会发现就是上去的时候,等我到一,比如说120dB,人类人类能容忍的,那个听到了容忍的极限的时候。
那基本上是他的大概是啊100万倍了对吧,那么其实它就形成了一个log为单位的,这样的一个压强,那么P0的话,它的压强大概是两二十,这个没有怕的这样的一个压强。
所以其实这也是我们对声音的一个perception,就是它不是一个线性的,其实它是一个logo base的,这个还是蛮有道理的一件事情,就跟我们以前在学那个,比如大家知道地震地震地震的列强度对吧。
它其实也是这个概念,就是诶我的每一级地震之间好像是能量,如果没记错,好像是差的是十倍还是20倍吧,反正就挺大的一个一个值,所以说地震差一级的话,其实它的力度会差很多很多的,它它能量会差很多很多。
所以其实我们对我的感知也是这个,这是大家第一次真的理解了分配,那这个概念,大家会觉得哎,我们是不是在科普一个科学概念啊,不好意思,我们今天讲的是个游戏引擎的课程,我们我们当然会讲很多科学知识。
但是呢这个东西对游戏引擎非常重要,因为你会发现我们在游戏引擎设计的时候,我们开放给我们的audio designers,声音设计师用了所有的工具里面,它不是调这个声音的VOLIN的。
直接指他所有声音的volume,全部用这个分贝或者类分贝的这个数值表达,都是以20的log10次幂来表达,这样的话能符合人对声音的自然认知,这个是非常有意思的好,那么声音呢还有一个叫peach。
就是我的这个声音到底是尖锐还是不尖锐对吧,那么它其实的话呢就本质上就是声音的频率,大家都知道就是频率越高,你听上去声音就越尖,那我们人耳能听到的什么,大概是20到五十五千赫兹,就这个是声音的一个范围。
在这里给大家听一个,这个具体发生了变化,对不对,这其实就是升学的一个基础,就是我们听到所有的声音,就是由这些东西构成的,那么我们有了这些屁事之后呢,我们就想诶什么,我们就把这么多不同的这个这个频率的波。
叠在一起,这个波的跌的跌的形式不同,就会产生一个东西叫什么呢,叫做音色,其实音色你可以认为是有很多的激波,就是那个叫OVERTM叠在一起形成的东西,比如同样一个调,我是用钢琴演奏的,我是用小提琴演奏的。
我是用这个这个这个,这个这个其他的乐器出来的话,你看到的东西会完全不一样,举个例子,大家听这段声音,对吧,感觉到了吗,完全不一样,这就是我的音色,音色你可以理解的就是频率大家都差不多。
但是呢我的波我其实叠的那个激波是不一样的,或者每个低波的那个权重是不一样的,跟你听到的不同的区别,那么好,其实呢这里面就讲一个,既然空气它是一个就是那个声音是一个纵波嘛,那当你去收缩的时候。
假设我在给你发过来一个让空气舒张的波的话,这两个波之间会不会形成一个抵消呢,确实它就会产生一个非常有意思的抵消效果,这就是我的降噪耳机的原理,所以其实我们降噪耳机本质上就是把声波。
他先侦测出空气中的声波的,这个这个这个这个face它的相位和它的波的强度,然后呢我加上一个位移,把它反向的位移给我打过去之后,哎,两个波及反向底下它可能不是一个反向位移,它的是个抵消,就是真的抵消。
就是这样就形成了我们的降噪耳机的原理,其实这个在游戏中的用处其实用处不大,但是呢,我们顺便讲个比较有意思的一个科学概念吧,好上面讲的东西非常的理论啊,但是大家需要知道的是什么呢。
就是在我们我们如果我们做一个游戏引擎的话,我们需要知道人的听觉的范围,我们会知道是说话是在一个相应的,这个就是说频率和它的,这个就是分贝的范围之内,那我们能听到的这个音乐在一个范围之内,然后呢。
在我们听到的一个就是整个的音乐里面会更大,比如说我们听到一些环境噪音,比如一些爆炸声,那么它的分贝数和它的那个频率,在于更大的范围,这里面有个细节,就是说虽然我们人耳能听到的频率。
我们说我们能识别的频率是20到50HZ,但是呢其实高于50HZ,比如说到了这个1万赫兹的时候啊,实际上人还是有所感知的,他虽然你听不见,但是呢它会扰动你听的音色,所以当我们去做电影或者做一些高水平的音。
那个就声音录制的时候,实际上我们表达的声音的频率,是要高于5000HZ的,这个也是就是说,听觉是个很重要的一种心理感受,这种震动的感受的话,人体的感受是非常敏感的,那其实呢声音它在空气中是无限连续的嘛。
那在我们游戏中的话,或者在我的计算机中的话,我们是要把声音从这个无限连续的信号,变成一个离散信号,就是我们要把它DIGITALIZE,那这里面就有一个很有意思的问题,就是说我们怎么去在这个就是游戏。
在这个计算机上表达声音的,这里面就引入大名鼎鼎的就是那个啊就是PCM,就是这个叫什么呢,叫脉冲代码,这个调制器这种方法叫那个就是那个pose code,那么这里面他其实他的想法其实非常的简单。
就是我对于你这种波动的信号,我的第一个进行采样,采样率来的数据呢,你还是个浮点型,对不对,无限精度好,我对它进行框架ALIZATION,就是把它变成一个可以存储的,定点型的这个数据对吧。
那么好不一定是定点啊,我也可以用浮点数存储它没关系,我就反正把它存下来,第三个呢我要对它进行编码,编码的目的就是让他去压缩,让他去表达,那么这其实就是PCM一个最简单的思想,那么对于声波这个东西呢。
大家想象一下啊,它最基本的东西不就是一个波浪无数的波吗,我们说诶人能听见波的这个波,这个这个频率的范围不是有一个范围呢,从20HZ到那个5000HZ对吧,那伟大的香农先生,他就提出了一个香农采样定理。
他就说对任何一个频率的信号,你只要采样的是那个密度是它频率的两倍,它就可以表示无损,所以实际上我们对声波的采样,只需要超过5K以上,比如说是他两倍或者四倍或者八倍就可以了。
但实际上我的采样率会稍微高一点点,因为我刚才讲的就是说,我们实际上虽然我们能区分的声音不超过5K,但实际上很多的更高频的声音,对我们的音质是有影响的,所以呢我们会采样率会略高一点,但没关系。
然后呢我们采样完之后呢,我们对采样的每个数据诶,我们进行它的就是量化处理,以及CORONIZEDCOTNIZE叫什么呢,叫做beat depth,那一般来讲一下,现代的这个就是音频的方法的话呢。
我们有的时候会用比如说14个比特,有的人是用24个比特去存它的这个量,这里面有一个细节在里面,我没有展开啊,但实际上刚才我们讲的就是声音啊,它其实我们对它的感知,它的强度是一个非线性的,对不对。
所以呢他这CORTATION呢也有很多流派,有的是用现行的方法,就是老老实实的就是123456789十,比如说我存到100万,我存这个变化,有的人呢codex的时候,我只是用那个对数。
用对数的方法就是用指示的方法去传达,这样的话呢能够最大效率的利用我的存储空间,那各种方法其实大家都有各有利弊了,我们就不展开了,这里面有很多人做了僵硬的比较和分析,那么其实呢有了这些方法之后。
我们就可以啊,把自然界的一切的声音,转化成一个在计算机里面存储的声音,这件事情其实真的不是在像大家想的那么,trigger的事情,就是在我刚刚接触电脑的时候,电脑其实是不能够放音乐的。
那时候电脑只能发出那个我记得好像叫media音,还叫什么,就是好像是八位的那个音,那个音是很差很差的,早期的游戏就是用mini音去写出来的,就包括你们回想一下那个比如说像SUPERMARIA。
像魂斗罗的音乐,都是用那种最简单的那个声音发出来的音乐,所以其实直到很后面,才有真正的电脑的音乐的播放器,那这里面就有很多的格式出来,比如像wave格式,像那个m p three是很后面的一个格式了。
还有flag是那个就是无损的格式对吧,像OGG的格式,其实每种音乐格式啊,大家去看,我们在里面也是给大家做了一个简单的总结,其实有一些是无损的,比如像wave和flag就是无损的,那么有一些那些mp3。
我们知道的和OGG它都是有损的,它就相当于说我是以以损失一定量的质量,但是呢我会极大的节约我的存储空间,这个对音乐存储其实意义非常的大,那么这里面的话呢给大家讲一个细节,就是说其实在游戏中的话。
我们一般用的比较多的不是这个无损的格式,因为这个数据量太大,其实你的对游戏来讲的话,我们一般不会用无损的音乐格式,那么我们一般会用有损有损的话,大家会说为什么我们我们可不可以用mp3。
其实mp3呢有两个问题,第一个问题呢,就是说它mp3这个格式设计的时候有个瑕疵,它只支持立体声,什么叫立体声呢,就是只有左右两个声道,而不能支持,比如说5。1音源的这个声音的这个采样。
这个在游戏中的话呢,我们很多时候需要环绕音,那mp3就不能支持了,还有一点是什么呢,就是mp3呢是有非常重的专利保护,那就意味着说我要是支持mp3格式的话,我的引擎还要给他专利付费,大家想想诶。
有点意思了,这有点像我们写芯片,写操作系统,我们突然遇到了专利墙,确实在游戏引擎里面有些数据格式,有些算法是有专利的,那所以呢在游戏引擎里面,大家还约定俗成吗,现在越来越多的人会选选用OGG这个格式。
为什么呢,因为OGG这个格式它没有专利保护,所以谁都可以用,这个很有意思,就是你花了很多心思设计的一个格式,你申请了专利之后就没人肯用了,你不申请专利呢,反而用的人非常非常的多。
这也是我们讲的开源的精神嘛,就像我们小引擎也是个开源引擎,也是一个道理好,所以呢其实每一种声音,就是每一种声音的格式的话呢,它都有各有利弊的,那么这个地方呢我希望同学们,当你在做引擎的时候。
一定要区分清楚,就是说知道我们该用什么东西,那么其实你有了这个声音的基础原理,我们知道了声强,我们知道了声音的这个音色,我们知道了就是声音的存储的格式,并且把它整个数字化了,那其实是不是。
我们就能做一个游戏引擎的声音系统了,其实这里面只是一个开始,因为游戏引擎最难最难的事,如何在一个三维的空间去注意啊,我们讲的一般讲的游戏,已经讲的都是三维游戏引擎,我去构建一个声音的场。
让你感觉在这个世界里发生各种各样的事情,所以在三维空间如何去渲染声音,是一个很难的问题,注意啊,这里面这个词也用了一个渲染,确实它又是一套非常独立的一个渲染系统,这跟我们的这个就是光学的渲染是两个概念。
但是其实它的复杂度,甚至他的专业度,我个人认为是超过了官,也不能说超过吧,至少他有足够深的东西,其实很多算法我也没有完全搞得特别清楚,但是我知道这些基本的概念,所以同学们如果将来有兴趣写自己的。
这个声学引擎的话,我会建议大家很认真仔细的去理解,这些非常复杂的声学概念好,那首先的话呢就是在三维空间的话,我们实际上有无数的深远,每个声源呢它本身是很简单,就是一段声音的source对吧,举这个例子。
比如说这是一段柴火在烧的粒子,但是呢这个柴火你在这个世界的不同位置,你听上去的感觉这就是不一样了,大家最简单的一个理解是不是越近的地方,它的火声越大对吧,越远的地方它的声音越小,对不对。
但是呢诶它在你的左边,在你右边怎么区分呢,那我怎么知道我和这个声源之间的关系呢,所以呢这个时候在我做渲染的时候,就像我们在做这个光学渲染的时候,我们需要一个什么,需要一个camera对吧。
我们需要一个观察者,他去对这个空间进行观察对吧,大家还记得在rendering的时候,我们说camera有什么属性哦,有他的position,有它的朝向,还有它的orientation对吧。
然后我们算出一个view frustr矩阵,听上去是不是很简单诶,在深学的渲染中的话,我们首先要引入的一个东西是什么呢,叫做listener,这个listener呢其实一样的,它也有,即它有这么几个量。
第一我要有我的位置,我在哪,一般来讲A跟我的角色上面身上对不对,如果你做个FPS游戏,没错,就在你的角色身上,但是呢如果你做一个TPS,第三人称设计游戏的时候,诶这个listener的位置还是蛮讲究的。
你放到相机的时候会有点奇怪,你会觉得诶好像你人已经进入了什么地方,但是好像声音没有听到,你放到那个人身上也有点情况,因为你的视觉上又觉得我离他有点距离,一般来讲会放在啊你和他就是你的。
你现在观察者的点和那个角色中间的某个点,那这个点就很玄学了对吧,就是很多游戏会自己调整,那么还有什么呢,就是速度,为什么这里面有点意思了,就是我们算那个,我们在做那个就是光学渲染的时候呢。
相机的速度一般是不考虑,但其实也是考虑的,比如说我要做motion blur的时候,我是需要考虑的,对不对,当然在声学里面的话呢,我们也要考虑这个考虑,待会解释就是大名鼎鼎的多普勒现象对吧。
我们需要考虑这个速度还有什么呢,就是我的朝向我,我的是这样的,我是侧过耳朵听还是正向他听,我听到的东西都是不一样的,所以listener对声学的渲染也是非常重要的,它是一个几何量好,那这个时候呢。
我们就要基于它构建一个声音的空间感,那声音的空间感是怎么来的呢,其实这个问题啊,是有很多的专家很认真的去研究过的,这个其实非常有意思,就是啊当我们对世界的感知只有左耳和右耳,对不对。
那我怎么去区分这个因缘离我的远近呢,那最简单的一个理解就是诶,声音他从左边和右边如果靠近我的左边一点,我左边听的音量会稍微大一点,因为右边隔着你的整个头部,它会稍微小一点,对不对。
所以从声音的大小我能听出区别对吧,但其实呢我们人的感知能力是非常非常强的,我不仅仅是大小,还有什么呢,还有它到达我左右耳的时间的差距,我就能感知出它的这个就是比如说几行啊,应该是十几毫秒的差距。
人就能感知出它的空间位置的关系的变化,这个是非常神奇的一件事情对吧,还有什么呢,还有就同样一个声音到达我左右左右的时候,它的音色会发生一点点的变化,而这种变化的话也会形成我对空间的感知。
其实我这边跟大家讲一个有意思的概念,就是大家以以前我们在家里面构建音箱的时候,大家都喜欢说哎,我的家里构建一个5。1的环绕音箱,对不对,有的人更有钱一点,我做过气电影的音箱,我记得当时那个在博士。
他这个博士是全球最著名的一个,就是当然了,他其实不是最专业的专业级,大家不用博士,但是的话呢就是我们大众去买的时候,都会觉得博士是最高端的,他做了一个研究,他说其实我只作为音箱,只有两个speaker。
但是呢我可以让你产生一个真正的空间感,就是你会感受到一架直升飞机从你的前面飞过,你的头顶又飞到你头后面,大家会觉得很奇怪,那左右耳不是对称的吗,那我听不到声音的区别,为什么我能感觉到这样的变化呢。
他的解释就是说,其实人的大脑和耳朵,经过就是百万年的进化之化,实际上我们的大脑很很敏锐的,能够通过这些刚上面讲的三个小小的变化,我就能够反向的就是那个绘制出来这个东西,大概是在什么空间位置。
这也是我们亿万年进化的一种本能,所以我们以前讲叫听声,变那个变那个什么变武器来的方向,其实我个人相信啊,它还是有它的科学原理的,因为我们如果对听觉有足够的了解,你会发现这件事情你通过它的相位。
通过他的那个就是音声音,同一个声音频率的微妙的变化,通过他之间的深深差的话,你确实就能得到这个空间感,而这个过程的话呢,我们叫做PN,那么penny的话呢。
其实就是说当我的speaker有很多个channel,很多通道的时候,我通过调整在通道上的不同的声音的大小,甚至包括音色,包括它的latency,我能让你产生这种虚拟的空间的感觉。
这个过程我们叫做penny这个算法,那么今天给大家讲的就是最简单的,比如说哎我怎么样让你感受到声音从左到右,比如说一个东西在移动,我怎么感觉到,那最简单的做法就是我线性的,比如说我把这边的音响从左边诶。
移一点点移到右边去,那就是一个线性的这样的一个移动,对不对,但实际上这里有个很有意思的一个细节,就是人对声音的感知啊,其实是你的音强的这个平方,你感受到power,所以呢。
这个时候就会出现一个数学上很有意思的事情,就是说当我这个声音源正在我的面前的时候,因为我的power都是用平方算的,你会发现你的声音就会小一半的感觉,这个事情非常神奇啊,我给大家听一个例子。
这个例子就是从左到右移动声源,大家注意啊,这时候就此处应该戴上耳机会听得更清楚,你会发现中当那个声源移到你中间的时候,声音好像小了那么一点点,然后一会儿又恢复了,大家听一下,大家感觉到没有。
就是中间有一段,你会觉得那个声音好像小了那么一点,实际上呢它的总音音响是没有变化的,但是他就是面power,他是那个音强的这个平方,所以呢你感受到的是那个东西,那好那就时候怎么办呢。
哎我们一般用一个就是这个啊,最简单的算法,就是我保证你的平方永远是为1。0就可以了,这是我的一种归一化的方法,那怎么归一化呢,其实也比较简单,就是我用过最简单的sign cos n的函数就好了嘛,对吧。
就是sin cos,我们讲一个是early in,一个是early那个easy in y easy out对吧,或者是那个那个这样一个方法,那在前面讲差池的时候,我们也讲过这个方法,然后大家听一下啊。
对啊,这个时候听上去是不是发现诶,他的声音好像基本保持一致,其实中间还有一点点误差,其实这个呢是一个很很很简单的一个TRICKER,但是我们在做penny的时候,实际上我们是需要这样的一个技术的。
但是这里面讲的是最简单的,从左耳到右耳了,那我们再讲更复杂的,比如说我们真的在一个空间上去表达一个方位,这个这个声音就比较复杂,就大家真的要用心去听,我们那个白色的点就代表音源的位置。
然后你会发现音源的位置一直在变的时候,你虽然只有左右耳在听,但是你会感觉他的声音真的在变化,我的更左边一点哎,我的最右边,往中间来一点,然后到你的后面,到你的更后面,然后呢到你的前面。
我不知道同学们的设备行不行啊,如果你们是用手机去看的话,我会建议大家插个小小的耳机,所以这其实是声音啊,audio designer很神奇的地方,但是这里面的就是说,当我的声源在我的不同位置。
我的每一个左右声道的我要发生的变化的话,实际上是有大量的就是采集和测算组织出来,这样这样一个经验的变化,不是一个简单的数学运算,实际上呢这个东西呢是符合人体的心理学,认知的。
这个实际上在很多的这个就是音频的公司的话,他们是做了大量的实验,那在我们计算机渲染中的话呢,我们只要把这些数据真的给他搬过来,就是说,比如说我可以对两边的这个音量进行调整,有的时候可能是调整它的位向移。
有的时候我会调整它的,这个就是说他的那个就是那个,甚至我的频率进行一些调整,让你感受到诶我的是在空间形成一个定位感,这个其实比如说啊大家如果买那种高级音箱,比如5。1音箱的时候。
你在家的时候就会有技师上门,帮你去校正和定位,他干的就是这个事儿,就是让你在这个对这个声音的空间感,是做的非常的准确,而不是只是简单的说啊,声音到了左边,声音到了右边。
你要能听出前后左右上下的这种空间感,那这种就是一个定位的比较好的一个空间音箱,注意在这个时候,如果你们家的沙发或者什么位置变了的时候,你听的声音就已经有点不太一样了,当然我们打游戏的人也不需要这样。
我的打游戏就是两个大耳机一戴我就可以了,所以的话呢一般来讲在游戏的生效中,我们目前主力的还是专注在就stereo display,就是说我两个耳朵的双耳的这种渲染的效果,达到最优嗯。
所以这个东西的话呢是声音伸长的空间感,是由一个我的非常重要的一个,一个一个渲染的一个元素,这里面的话呢就是说啊有一些简单的公式,但是呢更多的是一些经验的公式,实现在我们的就是audio的引擎里面去好。
那么声音呢还有一个很重要的属性,我们叫做attenuation,就是声音的衰弱,注意刚才你听到的声音是没有衰落的,只是在空间位置不同,那衰弱就我的最简单的理解,就是说越远声音越小,对不对。
但实际上在游戏引擎里面,我们要实现的声音的attenuation系统啊,比这个要复杂得多,因为同样的音源,当你在距离你不同的位置的时候,它的高频和低频都会它的衰弱都会发生变化,这是为什么呢。
因为就是说举个例子,比如说当你在你们你们啊如果看那个电影,或者说在真实的世界,你会发现啊,你有些高频的声音,你稍微远一点点,你其实就听不太清楚了,但是呢那种轰隆轰隆的那种低频的声音,你会听得非常的远。
当然在我们的游戏的世界里面呢,有的时候我们为了表达一些效果,我们会在某一个区域把它的高频也会强化,然后呢在后面的话我会逐渐回到很低频的区域,就是叫base的一个区域,这里面的话我们就以吃鸡游戏为例。
因为吃鸡游戏最重要的一点是什么,你听到了枪声,你要根据这个枪声的这个这个这个这个感觉,判断开枪的人离你的远近对吧,那这里面给大家讲一下这个东西是怎么做到的,你会发现就是哎当你跑到中等距离的时候。
这时候高频的那种就是回响,混响会变得比较重对吧,然后呢哎当你跑得再远的时候,高频的混响逐渐的就消失掉了,这时候你听到的更多的是他那种低频的声音,这个呢实际上在我的audio engineer做的时候。
或者或者sound designer做的时候,这三个音乐都会单独制作,让你之间进行插值,但是你听上去的感觉,就能够判断他的声音的远远近的变化,所以说如果我们去做一个O。
就是游戏引擎里面的audio这个部分的时候,这个地方是一个非常重要的问题,但是现代游戏引擎,一般我的audio呢都是用中间件来解决的,所以中间件里面一般都会提供这样的一个。
一个一个一个一个工具SDK给你,让你去做这个声音的这个ATTENSI,其实声音的ATTENTIATION对于游戏来讲非常重要,他很多时候给你构建这个世界的空间感,举个例子。
比如说最简单的attention就是一个一个球形吧,就刚即使你刚才那样随着距离变化的话,实际上你往前后左右跑都是一样的,对不对,但是呢想象一下比较复杂的一个情况,就是诶我要做一个小溪,流水的小溪。
那我不能大家想要流水的小溪,它是它的声音,每个地方都有对吧,每个地方都在流,但是你就想,你怎么可能在游戏中放无数个线性的声源呢,你只能放一个深渊,那怎么办,你第一种叫capsule。
就是那种哎长圆柱胶囊的这样的一个,就是声音的衰减的shift,这样就你现在模拟什么东西呢,就是哎你你靠近小溪的时候,你大致感觉就是你离它越近,声音越大,离她越远,声音越小。
但是呢你沿着小溪镜像去走的时候,这个声音不会特别的变化,这个其实在游戏中非常的常见,那更复杂的,比如说我定义一个空间域,比如说这个盒子状的区域,那我希望这个TENNATION的话呢。
就是我想模拟这个声音是被墙阻隔阻隔住的话,那我的attention就是以这个盒子为单位,就是出了那个某一个范围,他就开始迅速的衰减,其实这就是我们应该没有办法在游戏世界里面,真实的进行生产的模拟。
其实我们用这个attenuation呢,就给你制造了一种空间感,其实这件事情是非常的重要,包括它的混响也是受这个影响,那再讲一个,就是比如说我们在游戏里面要做一个高音喇叭。
大家知道高音喇叭输出输出的生长,它实际上是有一定的定向性的,那实际上的话呢我们就要用这种qun shape的,这ATTINATION就能模拟这种诶,你走到喇叭面前,听着声音特别的吵,很刺耳。
你稍微跑开一点点,诶,感觉声音帅还可以,勉强可以接受,其实这个东西都是用attenuation实现的,这也就是说attention的话呢,对于这个声音的这个场空间的构造,其实意义非常大。
大家想想都很简单的东西对吧,但是当我们去在做一个真实的游戏引擎的时候,做一个真实的生效场的时候,就是如何在构建一个3D空间的时候,你发现这些东西都非常的重要,那接下来的话呢,比如说更复杂的就是环境。
如果我们其实同样的声音被阻挡,有两种,一种是什么呢,就abstraction什么意思,就是说我有个障碍物,但障碍物你会发现声音啊,它是个波不,当它被阻挡的时候,他到那个被阻挡屋的那个。
比如说边缘的那个地方,它就会产生新的这个波的扩散是什么,波的衍射对吧,大家想象一下我们小时候学的那个小孔,那个那个波的干涉的时候,你就会发现每个拐角的地方,又会形成一个新的波源。
所以呢这个时候你听到那个声音和,假设这个波完全被阻挡了,就注意啊,比如说我隔了一面墙,其实我还是能听到墙那边的声音是什么呢,因为是声音推动这个强震动,然后这个墙又把这边的空气有震动了。
所以我们也听到声音,那么其实在生长的这个系统里面的话,这两种东西的处理方法是完全不一样的,那么最简单的做法的话呢,就是说哎我们去做一些recasting,就是从声源设一些R,然后就散开来发散一下。
就有点像那个我们在在前面讲渲染的时候,讲过一个,就是说诶我们用蒙特卡罗积分的方法对吧,我随机设一些瑞,然后呢我们去3sampling,我们去采样,当然这个方法非常废了,但是如果对于一些非常重要的声音。
比如说啊我在打游戏中最重要的是什么,近处有颗手雷爆炸,那我们要因为其实这个事情比较简单,就是重要的event我是知道的,然后呢最重要的listener是谁,是你自己。
所以event只有一个listener这一个,这个时候呢我在现代游戏中,我加一些RECOSTING的计算的话,也能够大致模拟这样的效果,所以这个其实对现代游戏引擎来讲,还是蛮重要的。
因为比如说你玩一个射击游戏的话,你根据一个手雷爆炸声,它是传过来闷闷的,还是说诶听上去好像有点小,但是明显感觉是在拐角那边的时候,你能判断战斗是在哪发生,所以这件事情又非常的重要,所以这也是说声音啊。
对于现在游戏的game play来讲是极为重要的,我的这句话的话,相信所有玩吃鸡游戏对吧,玩cs的游戏的玩家一定是非常赞同我的观点的,这个简直就是这两个游戏,你拿掉耳机之后,你基本上站立直接就没了。
对不对,所以说其实这两种声音源的处理方法,也是现代游戏引擎非常重要的两个系统,那么接下来呢讲一个更复杂的概念,在这边我不展开了,就是混响,混响呢,其实是我们对游戏的空间感影响特别大的东西,大家想象一下。
我们在那个游戏中经常有这样的场景,比如说你在一个教堂里面跟NPC对话对吧,比如说你骑着啊,比如说你骑着一匹马穿过一个桥洞对吧,你听到的马蹄声就会发生变化,这个就是混响,混响在我们的现实世界里面。
是跟空间感跟材质感影响特别大的一个东西,那么混响呢,它一般来讲我们有333个东西构成,第一个叫干音,就是说你真实发出的声音没有经过任何反射,直接到你耳朵的,就directly到你的耳朵的声音。
我们叫做干音,那么另外一个呢就是echo,就是诶你的是那个声音打到一面墙上,再反打到某个材质上,反射到你声音,叫做这个你的这个echo回音对吧,我们比如说对着一个大的这个水泥墙,一个空腔,我喊一嗓子。
我可以听到自己的回音,唉,光有干音和回音够不够,其实不是的,你还有什么呢,还有他的尾音,就是那个声音啊,回音那个音除了静音的耳朵,其实很多声音是弹到另外一个面,然后来回弹弹弹弹弹弹弹弹。
就会形成这样的一个几乎无限的循环,当然了,每一次都会有能量的衰减,它就会形成一个tale,那么这个回音和tell在我们的声音的系统里面,我们一般叫什么呢,叫做诗音,叫vet对吧。
你说这个audio designer很有意思啊,他们用了一个dry and vet两个词就定义了,但是呢一个简简单单的dry and vet,其实就能定义出完全不一样的一个,空间的容积的感觉。
那么在这里面的话呢,其实它有几个关键的量,第一个就是说诶你的声音是这个材料,是不是吸我的声波,大家会发现啊,就是不同的材质,对不同的声音的吸收是不一样的,还有一个什么呢,因为你空间的大小不同。
他的这个声音来回的这个就是latency,这个延迟delay是不一样的,那么其实这里面呢有一个简单的表格,大家会发现一个很有意思的特点,就是说不同的材质啊,对不同波段的这个声音吸收率是不一样的。
有的材质特别善于吸收高频的声音,有的材质特别吸收这个低频的声音,比如说我们最近在研究那个消音版吧,因为我们在在做一些办公室的这个,声音的处理的时候,我们就非常有意思的,就买的那种一个一小块板子上面。
做了很多方方向的这种条件,包括我们在做一个专门的声音采集室,也是在解决这样的一个问题,其实所以最近我的升学的东西蛮感兴趣的,因为我们花了好多心血去做这个录音室,和专门的声音叫啊叫声音合成式。
就是要保证他的升学达到一定的标准,所以我也被迫掌握了一点点的这个知识,所以确实你看到这个表格,你会发现哦,原来升学是很有意思,就是说它对它是一个材质和空间的一个,几何学的东西。
然后呢最后能实现你想要的一个结果,那这里面有个细节,就是说我们听到的声音啊,如果完全没有回音,只有干音的话,那个声音听上去你会非常难受,我的人无论是说话还是放音乐,你是一定要听到一些reverb。
就是一些混音的东西的,大家都有一个生活中的经验是什么,我们唱歌什么时候最好听,是不是在浴室时候唱歌最好听,我们很多同学都觉得自己在浴室里面都是麦霸,原因很简单,因为浴室里的混音效果是最好的。
那么其实呢在我的这个就是说,各种各样的audio的引擎里面的话呢,其实对这个事情呢,他就用一个很简单的概念就定义清楚了,第一个就是诶我的高音的分量是多少啊,我这个我的写到最后了吧。
其实第一个他他第二个呢,就是我的诗音的分量是多少,第三个是什么呢,哎我的声音来的时候,他的list就是pre delay,就是它的延迟是多少,它一般是以秒为单位,有的时候延迟可以达到0。5秒。
那就表达是一个很空旷的这样的感觉,比如山谷里的感觉也可能是0。16秒,零点多少秒,那么还有一个是什么呢,叫half,Racial,half是什么呢,就是说因为我很难去精准的定义这个声音。
对不同频率的声音的这种啊,reverb的这种这种强度大小的变化,对不对,它就统一的定义了一个量,这个量呢大概在0。5到十之间,他就说呢诶你在这个高频和低频中间,到底是你对高频的这个这个混音。
这个效果更强一点,还是对低频的混音效果更强一点,那么就用这么一个简单的量,这四个量,artist就能做出你很多你想要的这个效果,所以这个混音的话实际上是现代这个audio engine。
就是声音引擎非常重要的一个基础性的功能,那么另外一个的话呢,就刚才大家同学们可能也我的,我怀疑我的一讲声音的时候,同学们就会怀疑,就会猜到,我要讲的就是大名鼎鼎的多普勒效应式的,在游戏里面的话。
多普勒效应也是一个非常重要的一个效果,因为你比如说你敢敢像这个场景里面,你感受一架飞机扑面而来的时候好吧,实际上他的飞机的声音是不变的,但就是因为跟你的距离和速度发生关系的时候,哎一直在变化对吧。
这个是一个我的中式英语有讲过的,那多普勒的原理其实也是非常简单,就是说因为你在运运动介质中运动的时候,你一直会产生这个波,这个波就以那个点为圆心扩散,所以呢他最后当你感受到那个震动的频率,就会不一样。
其实这个的话呢,实际上在啊其实不仅是在升学啊,甚至在光学中都是有用处的,比如说像那个啊,我记得好像那个我们讲我们中国的那个,就是那个高能粒子研究研究了,就超高速的那个宇宙射线打中大气层的时候。
它会出现一个叫什么辐射,那个辐射就是因为它那个粒子的速度,那个那个大于它在那个介质中的光速,然后呢就会产生一些很有趣的辐射,其实跟这个原理是有点像的,所以说多普勒效果的话,是一个非常重要的一个效果。
那么这也是我们在游戏中对速度的感知,特别重要的一个效果,比如说当你在高速移动,比如说我在开车的时候对吧,当我在空中进行追击作战的时候,甚至有有一颗子弹从我旁边送打过去的时候,其实在游戏引擎中。
多普勒的效果是非常重要,因为它是一个打击感和速度感,很重要的一个来源好,那么其实讲了这么多声音啊,其实声音现在的发展和更复杂了,比如说我们现在如果渲染我的游戏引擎,渲染或者是采集。
我们是来自于这个就是啊整个生产的采集,就是说因为我们现在假设所有的声音采集,都是有一个listener,就是左右耳,但是想象一下,我并不知道listener在哪里,我能不能采集一个整个声场呢。
这个需求其实在以前是没有,但现在如果随着VR的需求越来越强的时候,其实我们需要对整个生产进行采集,这里面只是点一下,就是在VR的这个采集的时候,我们是对空间上进行声音的采样,就在这个案例里面。
大家感觉到那个红色的点,就是我一直在变的这个空间,然后你会感觉到这个声音的小提琴的声音,一直在平衡,正在变化,所以说我们今天讲声音最重要的是一种临场感,其实我自己啊,家里还是有蛮不错的一个声音的设备。
但是呢,就是我们比如说我们去听那个,交响乐的乐队的时候,我自己亲身的感受就是如果我在现场去听,和我在家里用我的音响设备去听的时候,你会感觉完全完全不一样,所以这也是我觉得声音这件事情的话啊。
离做到我们想要的临场感,还是有很多很多的事情可以做的到,特别是大家去玩一些3A游戏的时候,我是特别推荐一个,就是说你在一个很安静的地方,找一个非常好的耳机,或者是一个非常好的一个环绕音箱。
再去玩那个游戏,你会感觉他的感觉是完全不一样,这也是我一直认为一个高品质的游戏啊,他对声音的这个把握和表现一定要非常的到位,那么其实呢这边顺便给大家讲一句声音呢,现在其实虽然我们讲游戏引擎。
声音是个非常重要的组成部分,但是呢一般来讲,很少有游戏引擎团队,会自己直接去写声音的引擎,一般我们会用中间键,那么这里面最大面积有两个,一个是f mod,一个是w wise对吧。
那现在f mod呢好像维护的有一点拉胯,所以w vs越来越受大家重视,单身的最新的游戏游戏引擎,他们也会意识到,就是说可能还是需要自己直接去写声音,引擎对吧,比如说像ARREAL对吧,那么所以的话呢。
其实声音的MIDWELL是一个非常重要的一个东西,那声声音的middle为什么这么重要呢,实际上他是让他给我们的audio designer,提供了一个非常符合他们的习惯的,一个调音环境。
这样的话呢让我的audio engineer,我们在游戏引擎工程师里面的话,我只专注于如何在3D世界里面去进行,这些声音的组合渲染,而我们会把声音的生产或者是管理,全部交给了AUDESIGNER。
其实渲染的有一部分,也是由这些meteor来完成的,那这里面的话呢给大家举个例子,就是这里面比如说我们拿我放一个视频,就这里面是一个简单的音效,诶。
我的audio designer在这个mile world里面,它有这样的一个界面对吧,它可以加上一个效果器,然后呢可以给他加上,就是刚才讲的那个reverb,就是婚姻的时候诶。
它可以给它加上各种各样的干湿音,效果和空间的效果,这就是我的audio designer每天在做的东西,当然了,我今天讲的所有的声音啊,还是实话实说,还是声音的基础,实际上你真的作为一个复杂的世界的话。
那个声音其实非常的复杂,举个例子吧,比如说以那个最新的那个这一作,我们那个就是啊,就是PS5的一个猛推的一个游戏蜘蛛侠对吧,那大家会发现,就是他为了表现一个曼哈顿的这个音场的效果。
大家想象一个城市里面的音乐,是不是非常的复杂对吧,其实当你在城市的每一个点,每个区域,他的混音效果都是不一样的,所以他为此专门做了一套算法,把整个曼哈顿的每个区域的。
他的混音的这个效果都归因纳成了不同的类型,然后呢形成了这样一个不同颜色的分布图,然后这个时候才能实现,那个SPIDERMAN在曼哈顿穿来穿去的时候,你听到整个城市的感觉不一样,接下来有段视频。
这段视频里面的话呢,他把这个蜘蛛侠的其他的音效全关了,比如他的脚步声啊,空气中的其他声音,就让你去听那个环境原因,大家感觉一下,这里面每一个蓝色的点就代表了一个姻缘。
所以我们经常讲说大家想玩开放世界的游戏,其实开放世界的游戏引擎,技术的要求是非常高的,当然你要做的质量很高,如果做得非常简单,也是很容易的一件事情,所以讲到这一趴的话。
我们今天的课程差不多所有的内容全部讲完了,差不多也快两个小时吧,一个小时40分钟,不过今天PPT准备的实在是内容量太大了,我们到最后一刻还在改,因为确实这2part的内容特别多,我们做了很多减法。
所以忘了一件事,我忘了把那个就是我的那个reference的那些,就是供大家学习的参考资料补上去,我们争取在后面发的这个PDF上给大家补上去,那么再次感谢我的那个课程组的小伙伴。
就是那个大家很辛苦准备了这期的课程,然后呢,今天我的课程的部分就到此了,那同学们有没有什么问题可以问我啊,这个同学问我的问题很有意思,他说他想写一个CPU上的粒子系统。
是不是很适合用ECS系统去去去开发,其实呢这个首先大的方向是对的,确实是如果用最简单的这种编程模型的话呢,做了你的效率一定是非常低的,因为你的你的数据一块块层,然后的话呢你去访问他。
你去处理它效率都很低,用ECS的思想就是把数据全部集中在一起,那这样处理起来是非常好,但是呢他不需要用的那么复杂的,什么这个什么NTT啊,这些概念了,它其实就是一个非常简单的。
我认为是那个就是那个就是那个DOP的,开发概念,就是DORANGE的programming,就是面向数据的编程,就是你把所有party系统的数据全部集中在一起,然后呢一类particle。
一个process把数据啪就处理完了,那个效率是很高,然后在中间的话呢你还可以用SMD,就是我们上次以前讲过,就是一条主直令,同时进行四条浮浮点数的vector运算的指令,那这样算起来速度就会很快。
所以这个基本的架构的话呢,其实已经非常成熟了,但是呢这个实话实说,我们无论在这个CPU上优化了多好,它一定是比GPU上是要慢的,但是呢就是说实际上这两个东西呢,都是有存在的价值。
因为GPU上实现的particle,虽然现在computer是非常的强大,但是呢他还是有很多的决心局限,就有些比较复杂行为的particle没办法做,而这一点呢就是我的CPU的这个优势。
所以的话呢CPU上的一个高性能的particle,系统的实现,对于现代游戏引擎来讲还是有实战价值的,哇这个问题问得好,专业同学问我说,粒子系统可以和我们前面讲的动画系统,和物理系统相结合吗,啊实话实说。
这是yes的,特别是对于现代的这个粒子系统来讲的话,虽然最早期的粒子系统,就是你看到一些小东西飞来飞去对吧,但是你看我们在这节课中讲的,那些比较复杂的那些粒子系统的话,首先比如说它有大量的环境的互动。
那么这个时候其实我们会用到物理系统,甚至有些最前沿的粒子系统的话,都加入了一些物理的解算,它能够保证这些东西能够,符合一定的物理学规律,它比如说我们能表现一个悬挂着的这种这个,教练对吧。
或者是很多小球之间彼此之间进行刚性结算,不会不会就是穿插到一起去,那么的话呢就是动画就更重要了,就比如像我们这次讲的crowd的话,实际上你可以认为它就在粒子系统里面。
实现了一个非常轻量的一个动画系统对吧,这是我们把一个轻量的动画系统,in banded into我的一个粒子系统,但其实反过来讲讲哈,就是粒子系统也可以直接从动画系统中间,形成这样的一个融合。
比如说我们在很多很复杂的效果,比如说一个角色诶走着走着,他突然变成了很多的沙尘这样效果,那这个里面就是有些有这样一个融合的需求,其实啊现代粒子系统,有的时候它其实和我们的影视特效系统。
是深度结合在一起的,比如举个例子吧,比如说像胡迪尼对吧,他是我们现在看到很多很酷的这种影视特效的,这个工具,那么它的效果,它的它的很多表现,越来越多的集成到我们现代的游戏引擎里面了。
甚至数据之间是实现了互通,第三个问题是同学问,我说刚才那个crowd的粒子系统的话,你们的SDF就是空间的,就是有正负向的,这个距离场的话是预预先送,算好了吗,啊这个在早期的引擎中呢。
还真的是运气算好的,比如说我给你一个巨大的城市对吧,那我肯定我就有它的设计图,这个城市也不会变,那我肯定可以算好,包括我上过的那个direction field,但是其实呢在现代游戏引擎里面。
特别是我们有了越来越多的这种,比如说global in an ination,就是全局光照的这样的一些计算,因为其实很多全局光照算法,他上来就需要你对这个空间算这个SDF,所以呢其实这个SDF的话呢。
在游戏引擎里面,我们认为是可以real time直接算出来,但是它的精度可能没有那么高对吧,包括我们可能是要把它算的view dependent的一点,就是说哎跟着离我的眼睛看得近的地方。
我的这个密精度高一点,远的地方我的微低一点,但现在在现在这个现代的GPU上的话呢,算一个场景的SDF的话已经不是特别难了,我们可以实时去算它,所以SDF有的时候会成为很多计算机的,我认为是标配。
比如说我算好一个场景的SDF,我可以用它来去扰动particle对吧,我的particle在空中乱飞的时候,我让他不要穿到我的物体里面去,那么特别是有些GPU追问的particle的话。
用SDF算出来的效果就真的是非常的好,你能感觉他好像沿着那个物体的表面在流动,这个是一个我们认为非常重要的效果,但同时的话呢我也可以用它来做我的GI,我的全局光照,哇这个问题有点难。
同学问我说游戏中的音效数据是怎么组织的,其实呢游戏中的音效数据的组织还是蛮复杂的,那么比如说以一个实战的引擎为例,一般我们会接入一个以那个audio midware中间件。
比如说我们接入f mode或者接入w wise,其实在音乐家在那个audio designer事件里面,他只是放入了很多的声音的clips,就是说诶就像动画我放入很多原始的数据,然后呢在游戏引擎里面。
我们会触发各种各样的event,然后各种各样的事件的时候,就会触发各种各样声音的混合的需求,然后当这些混合器,它就会从这些clips里面选出这些声音,根据我们刚才讲的混音的方法呀,或者播放的规则。
他们进行这个生成各种各样的音乐,但在游戏中的话呢,我们会进行8G的控制,比如同一时刻,我最多播放的音源的数量不能超过多少个对吧,这个这个就非常简单,这就是我的声音资源的国际最基础的管理。
你可以认为就是我假设一个游戏,我用了1000个声源,那我1000个声源就会在启动的时候,加载到我的内存中,或者加载我的硬盘,在我的硬盘上,然后我用的时候我就调用它,但实际上的话呢。
在现在的一些声音的这个中间件,包括我的引擎中都会提供这种different loading,什么意思,就是说很多的特别是音乐,特别是有一些效果,我们确定用不到的时候,我们就不去加载它。
否则的话你会发现游戏,光光把它的音乐和音效加载进来的话,哎你就吃掉了几百兆甚至是上戏的内存,但我们游戏中内存是最就是最稀缺的一个资源,所以现在的音效和音乐的资源的管理的话呢,更像是我的场景啊,网格啊。
动画的管理啊,就是用到了我去调用它,这里面就会有一套比较复杂的,就是调用的规则体系,但是呢它基础的思想就是,比如说我以关卡为单位,我把这个关卡所有用到的音效和声音,我有一个表格。
那我就把这个相应的东西漏进来,我切换关卡的时候呢,哎我重用的部分我保留下来,我不需要的地方把它移除掉,我再去加载,就是新需要这个就是两边的difference,我把它下载进来。
所以这个呢也是就是现代的游戏引擎,音效的一个啊音效资源的一个管理方法,好的,那我今天的话差不多也是一小时50分钟,那今天要不先这样好的,谢谢大家,那我们争取在下周下周我们再见面。
OK好。
12.计算工具箱:成像梯度与处理 II | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1BP411E7sw
嗨同学们,大家好好了,欢迎来到games 204,那同学们久等了,今天要给大家分享的一个是,就是上一期上一节课的续集,也就是image鬼点子,你们这gradient呢,本身是一个有非常神奇的性质。
就是我们刚才之前讲到了一个破损,不容扩充混合的一个问题,图上长出来,就是我们后面想要的那张图,这个就跟以前传统的一些图像拼接呀,就会有一些非常大的有效的提升,我们基本上是看不到。
就是我们最后图像上看到是什么情况,比如说呃像以前大家很多就做photoshop的同学,喜欢ps photoshop,photoshop哎,就用到了非常多的一些呃破损不ending。
或者是呃一些新的一些bendy的一些方式,这个基本上很多都是基于规定的去做的,所以说呃这个image gradient,它是对图像融合呀,或者是是一个非常大的一个帮助的,当然除此之外。
因为这鬼点本身还有自己的性质,比如说它的一个sparity,今天我们会讲到一个呃,就是关于图像sparity的一个性质的分析,也就是说我们什么叫spars呢,这种这个图像里面它的规定大部分都是零。
就是边缘占整个整体像素数的时候是,非常小的一个比例,所以说呃,最后我们通过这个spy给它做一个约束,我们做很多计算摄影逆问题的时候,就会有一个呃更好的一个效果吧,嗯这个想想要不要给大家布置一次作业。
关于这个研究的规定,可以的啊,上一节课最后是讲到了,我们讲到一个图像的,一个autoptimization的问题啊,在比较简单啊,但是与以前我们像学数学,我们现在是对于整张大图去做它的一个list。
我们看到了上上节课一个呃,像一个一个大的一个拉普拉斯的一个matrix,就表示啊这个图图像的这个鬼点子,但今天我们会看到,要实现这么大一个规定呢,是你大v rix就是m n乘m n的一个超。
大的一个冰水比这个是不太现实,所以我们就可以用考ution的方式,来快速的实现啊,我们这个matrix的功能,就是,我们最后无论是从写这个东西,到最后去实现它。
我们都可以用conclusion来来替代它,牛顿法,但今天会给大家讲到一个就共轭梯度法,共轭梯度法就我们有很多问题啊,就是最后我们归结为,就形成一个a x减b的一个问题,x减b等于零二。
也就是a x等于b诶,我们解这个方法,其实就像刚才讲的那几种方法一样,这个时候是我们一个摄影或者是,推行学里面就比如说求焦点呀,也是求解一个ax等于b的问题,就是我们计算机里面。
做了一个非常多的一个工作,今天要给大家继续讲解这个computing toolbox,就是image gradient and processing,然后第二讲。
再次欢迎同学们来到gains 204的课堂。
上节课我们已经把这个整个破风的过程,列出来了,但是我们并没有一个很好的一个server,去快速解,这个最后一个ax等于b的问题啊,虽然说我们最后不是a x,但是它是一个呃可以写成这种形式。
然后呢解完这个pal server,就是这个pbi的基本问题,我们去解决啊,考虑这个vication解决完之后它有哪些用途呢,比如说像psl image editor啊。
今天还会给大家晒一个非常有意思的一个,topic的,就是一个flash is not flash的photography,它的融合怎么样去除反射,这个是一个非常简单的方法。
就是我不知道现在有些手机厂家也没有,把这个用上,当,我们考虑这个背景环境跟这个flash的一些呃,打打出来flash,这两张图我们就可以很好的融合出一张啊,非常好看的一个图啊,就把这个反射呀。
还有这个那就是它本身有一个亮点,过曝了一个点给去掉,所以这个在flash ptograp里面会经常用到,那最后给大家科普一下,现在的一个规定的camera,还有在光学端,还有在一个时间域去做一个低分手。
当然时间域可能大家也会听说的比较多啊,在时间域的一个低分数呃,通常就是叫event camera,有时候也叫dynamic vation,叫dvs,首先要给大家讲解的是一个有效的一个,扩充求解器本身哈。
这个玩意儿还是呃在求解一个线性的一个,逆问题吧,但是怎么解的呢,就我们上节课啊,我们知道我们要想对这一个变分的,一个问题啊,就是我们想minimize啊,这个target f跟我就是就我这个tp。
就是我们target的目标图像的规定,跟我们这个v,他们就是不就是本身的这个,lion的一个规定,让他们相在我们的一个利用区域内相符合,然后呢同时也要满足这个边界条件。
就说怎么样去minimize他们之间的一个差,然后又要考虑他这个bd condition,就我们,知道这个madf,实际上就是对xy方向分别求偏导,对不对,然后呢,嗯我们要把这个我们知道这个nf。
在x y方向分别求偏导的时候,呃,我们也是可以用一个x y方向的一个future,就是一-1或者是y方向的一-1,这么一个future做一个conclusion。
来去替代这么一个大型的一个liniqua,实际上它是非常简单的一个算子,然后呢,就是当我们面临,就是我们要求解我们的图像诶,我们这个f啊是我们的目标图像,然后我们把这个上面这个公式就上一页。
这个公式拉姆达f减低,也就是这个时候让他等一个,实际上就是minimize诶,然后是呃这么一个不f减b这么一个情况,对不对,然后这个时候这个g黑f跟v,分别代表着什么呢,大家可以思考一下哈,这个g啊。
这时候f啊我们都考虑抽象的函数f,我们可以不用管它这个f到底是什么形式,在这个时候,我们f的这个时候是一张图像,f是一个图像,这个g呢,实际上我们知道g是对f两个方向,分别求偏导诶。
这个时候我不想用这个大型的linux来表示,我们就可以用一个aerator的形式,也就是我们xy方向的一个conclusion,来表示他对f去规定子v呢,它还还当然还是他自己这个g。
这个时候就变成一个对xy方向分别求规,定成一个procreate,那我们这个时候我们要解决这个问题,我们先把这个先不考虑这个帮助condition,你考虑帮助ming会稍微复杂一些。
我们先教大家怎么求解,这么一个线性的一个优化问题,就是一个凸的一个to的二阶的作,无论是它高级的维度,它本质无论它的维度是有多高啊,它本质上都是一样的,像我们这个要再说白一点哈,这个就是一个二次方程诶。
我们就可以用一个gradient的一个,decent的一个方式来解,那么一个二阶的方程,下面来给大家share一下,这个方法到底是什么呢,是吧,大家可以看到这个g啊,实际上就是聚在一起的。
一个就是差离散的一个鬼点子,我们就可以在x y方向分别用一-1,这么一个fter来表示,那f呢是我们最后要求的一个呃图,在它的一个xy gradient,就是一个我们未知的那个。
tv mage的一个规定,我们要优化的呢就是我们winner,就是我们实际上in source image gradient,这个大家就比较好理解了,怎么样解决这个呃优化的问题呢。
就我们知道我们可以把这整个的一个cost,function有时候也叫loss function啊,这个呃有时候被大家叫成cost function,或者是target cofunction。
我们用它用e f呃,它是什么的方程呢,就是g也就相当于这个拉布拉,然后我们用一个composition fifter来表示,v就是xy,就是呃g在x y方向分别求偏导,我们要想简单一点形式,像这么一个。
哪怕他就是你,你想只只想让他这个抽象的一个形式啊,我们对它求偏导,对x求偏导,然后让它等于零,不就是极值呢,那这个地方肯定是的,因为我们这个很明显,它这个gf减v的平方啊,它是一个凸函数。
无论是它有多少维度,它是一个凸的凸的意味着啥呢,它总有总能找到一个最优解,当然这个时候他只有一个最优解的时候啊,又没有local,又没有一个局部的极小值,极大值,哎我们这个时候对他对f求助链等。
然后让它等于零,诶这个时候就是它有直直的位置,对不对,然后我们就可以诶很轻松的求解,这个这个是怎么过审的呢,实际上就是记p gf减六对吧,我们先对外面那一层,下面最外面那一层让他等一个零。
理论上这个应该是写个1/2哈,这个比如说大家因为让他等于零了,大家有时候也不考虑这个前面有没有系数,就说这个就让它等于零,实际上就可以写成这么一个形式,让它等于零呢,我们就得到呃,我们要解这么一个方程。
就把这个呃,我们最后想要求解它给f表示出来,实际上我们可以看到哈,这个gt g等一个gt 6,对不对,我们f很明显是不是g t g transports呃,这个就是它的一个逆那个gt没有。
就是最后的结果,当然这个时候如果这么求解的话,我们要一定要保证啊,这个g是一个满志的一个matrix,要不然他那个解空间会稍微大一些,就不是唯一解,但是有的时候我们要解那么一个,线性能力问题啊。
就是像我们知道从上一节指导,我们这个g本身,它就是一个m乘n的平方的,一个超大的一个vector,就我们把一个m m n,mmn乘m n的一个大图拍成一个长条,拍成一个vector,诶。
这是有有一个可能是chinese of parameters,然后这个这么大一个没法算诶,没发散咋办呢,我聪明的人们就想用鬼点底线的方式,我们不需要算他,这个就最后的一个前面的一个matrix是啥。
我们用一些算子的方式,或者conution的方式哎,来把这个大型的一个线性计算,转化成一个卷积的形,式,这个时候诶剪辑大家对一个大家计算机啊,cpu也是比较友好的,诶这个时候就可以很大的提高效率。
这个鬼脸descent是咋玩的,同样的,我们对这个run的e,对那个我们的一个loss function求对f求偏导,诶我们这个时候,我们为了简便计算啊,就把这个gt g表示成一个matrix a对吧。
它是一个g本身,g本身是一个对mn乘m的一个大matrix,哎不管了,这个实际上就是operator诶,这个时候a实际上就是一个,拉普拉斯的一个operator啊,这可以3x3的一个看不出是哎。
这个时候大家都变得非常舒服,非常少对吧,然后把这个g t m它就是一个常数,我们把它记成b,首先把它切成b是,所以说最后哎,我们就把这个整个写成一个,a f减b的一个形式,然后呢。
我们的这个r这af减b,就是他如果不是在极值点的时候,这个时候,然后为什么加了个负号呢,因为它是离极值点的一个距离,所以说我们加了一个负号在这唉,我的每步的目标是啥呢。
就是让我们这个要求的这个f什么要mini的,这个f对要求的f每一步规定,第三就是每一步更接近f的这个极值,也就是我们想要用这个迭代的方式,然后他每一步哎加上这个residual,让它更接近它的一个机制。
所以我们就用一个迭代,就是f第n加一步,等一个f d n步加上一个step size,就是一个步长,然后再加上一个dn的recedu,然后这个步长选起来,是有非常多的一个问题啊,这个大家会给大家呃。
待会给大家讲一个最优的补偿,但理论上就最简单最简单的一个情况下,但考虑到一个一元二次方程对吧,这个是ef还有一个f的方程,我们在这个时候bf,然后我们直接咳咳咳,让这个德尔塔一塔就在这个时候。
那就找到这几点了,对不对,所以待会可以给大家讲,这个最佳的补偿是怎么找的,我们通过这么几次迭代,当我们这个recedure小于一个switch后的时候,诶这个时候我们就可以理解为。
这个就这个优化它收敛了,就收敛到一个呃我们想要的一个地方,就它跟我们的一个想要的一个f,它这个值就很接近了,大家就可以理解为它是最后的结果,然后怎么样去找到这个最优的补偿呢是吧,刚才我们看到d就是ef。
它实际上它就是gf减六,但是呢就是对他f加一步,我们用这个fi来替代它,这个时候我们可以观察到对f加一个step,这个e的函e的函数,实际上它是一个关于这个步长的一个函数。
我们就可以啊对这个不长进行优化,当然我们知道如果对这个步长求偏导,让它等于零,他就会找到一个极值,那这个极值是啥呢,为什么让他的这个极值就让它的规定,对一塔的一个求偏导的一个呃,让它值等于零呢。
这个时候我们就可以拿到最佳的波长呢,这个还是从一个简单的一个,一元二次函数来说起,就这个大家有时候会这个地方会很抽象,就是我们为什么对这个一塔对不长求偏导,然后让他等于零,就可以拿到一个最佳的不长。
其实大家这个时候有点迷迷糊糊,又觉得有点道理,又又不是很明白这个道理是啥,对不对,然后呢就随便画一个e s函数,实际上还是e f对吧,然后这个地方就是f,然后我们这这个点哈e fi,然后fi这个点对吧。
然后我们要求这个fi加一的时候,诶这个地方是fi哈,这个就是eti乘以这个receipt本身,这个receipt离知识点就是这个i i,对不对,实际上就是哎我们给它一个微小的变化。
这个一塔i给他来个小小的一个德尔塔,微小的变化,这个是趋于一个是一个小值的,我们发现如果在这些地方,我们这个不长变化一点点小值,我们发现这个德尔塔fi,实际上是对这个一塔求偏导的时候。
它是一个比较大的值的,对不对,但是我们发现在这个极值点,大家观察一下,这个你run e f i加一个g比这个,但是按本身这个地方,我们首先这个是不是已经趋于零了对吧,e f i这个地方在极值点哈。
这两个就是说在极值点左右,这个就就是零啊,它就等于零啊,就不用那个它就等于零,那你也不用管分母了,所以说就是一塔在对一塔求偏导的时候,a让它等于零,也就是这个就是最佳的弧长的一个位置。
知识点就记得他在家里不常规,所以说它很高维度的情况下也同样适用,然后我们呃,用一个二次函数来给大家画出来,会让大家更容易理解一些,啊同样的就是我们对这个解这个规定,descent的时候。
我们就可以通过这么一种迭代的方式,来把它解出来,最后我们pf的一个resgo,之前有个负号码,第able接口就是b减去一个一个a f i,然后这个一塔呢最优的不长啊。
就是d i d i x就是做transport,然后比上个r a,然后底下呢也是同样带一个a,这么一个相同的,然后呢在最佳步长求出来之后,我们呃这个d i加e f i加一步,就可以通过f加上一个步长乘。
加上他的c格,来逐渐逼近,我们最终一个想要的一个tx的值,这么做有什么好处呢,大家想一想,我做这个鬼点decent的时候有什么好处,这实际上我们这个a啊,这个a实际上这个就是用g translg。
我们这个时候实际上是表示,一个拉普拉斯的一个,就是这么一个,卷积它变成一个operator,你把它当成一个operator,不要把它当成mrx,就我们其实际上我们是对a啊,本身就没有任何操作。
本来它是一个m8 m乘n,然后乘以m乘以一个超大的一个矩阵,那这个时候我们用这种迭代的方式,这根本就没有算法,哎,我们实际上操作的就只有一个,拉普拉斯的卷积,对不对,然后我们要算的是啥呢。
实际上只是or receire,这个vector,跟我们最后他给的这个图像的一个大概,百分一,把这个图像开成长条诶,我们只求了他们的一个矩阵相乘,这个效率是非常高的。
然后呢这个a它又是一个拉普拉斯matrix,你直接用一个卷积就把这个糊弄过去了,当然也不是糊弄,这是完全等效的,这个就非常快速的来,可以求解到我们最后想要的解,而不是求解一个非常大型的一个线性方程。
当然我们在实际应用中啊,我们还会有一些更加快速的一些求解器,叫ctrl quit,规定的这个叫共轭梯度法,同样是我们这么一个cost function ef,那么求解它的时候呢。
呃我们就需要一个rt的一个计算,就是我们啊在这个呃,这个怎么给大家解释呢,就是我从头给大家解释一下吧,这个本身哈我们嗯就定义一个,那我们就先说一个解一个ax,等于b的一个问题,解这么一个问题呢。
就我们这个时候就有时候,大家觉得求个呃规定的decent就不够快,诶我们这时候就可以构构建一个虚函数啊,就是嗯比如说,构建一个这么一个虚函数,fx,然后呢就等于一个啥呢,它是因为构建一个关于x的函数啊。
这个1/2的ex transports a,然后ax减去个b transfx,对不对,然后让它的一个对x偏导round fx,然后比上个round x组装一个a x减b对吧,我们要求诶这么一个东西出来。
诶这个时候我们去怎么求它呢,因为刚开始我们讲了一个鬼脸descent,实际上就是先求当前求导的一个位置,就是就是德尔塔f,就是求一个deltf sk等于一个位置,然后同时呢呃找一个最优的一个步长。
然后不断迭代,搞这么一个圈,一个迭代就最后拿到一个呃最后的结果了,但是呢我们还会有一个更快的一个方法,这个只要规定descent,就就讲这个供货梯度呢,就必须先给大家讲一讲,就是整个正交坐标系。
就是我们有一组向量p,然后p呢是有一个有一系列的这个小vector,组成了cn,然后里面任意一个任意的di跟dg个向量,也就是p i d跟pg对一个pi trl a p g,他就可以这个a是正定的哈。
a是a是正定的,就是他没有零值跟或者值它正定,它是一个正定矩阵,然后对这么一个正定矩阵a,我们在这一个这一组向量,p这一组向量里面,任意找两个这么两个向量诶,然后我p i transpose a。
然后pg等于零,然后呢我们就怎么定义呢,就是p这个大size,对a这么一个正定的一个矩阵是共,是就是叫共轭,当然我们要对一个这一个,高维的一个函数啊,高维的函数那也是一样的。
这个对于一个高维的函数来说呃,我们就可以把这个就是简单理解为,这个这个p这个sp里面,这些vector都是正交的,对这个呃大家遇到这个正交,就是一个它是一个正交完备系,细数它的一个正正在往内吸哎。
勒让德这个系数,热,让德这个那也是一个完备的,一个正交的一个系数空间,诶这个这个有点扯远了哈,大家给大家继续讲这个规定,desc,然后比如说像我们嗯其实最后这,个a啊,就是a的特征向量。
实际上就是就我们这个a啊,正面去正面的一个max它的一个特征,它的一个特征向量就是一组供货向量,就是一组这个叫供货向量,然后我们对这个fx,就我们把这个3x,其实是可以当成一些数啊。
我们从p0 这个点开始哈,从p0 这个点开始诶,p0 就等一个,对这个residual的一个值对吧,然后我们从p0 开始,然后再把p1 p2 ,p2 p n这个全都推出来,然后推出来啊。
到一个这么一个正交的一个完备的一个系,然后呢,我们就可以知道p一就等于一个啥呢,第一就等于一个看好,这个应该是等于一个负的ds x0 ,加上一个贝塔ip 0对吧,我们是正交的,然后,给他加一个偏移。
然后因为是正交嘛,然后应该p,乘一个a然后它的transport乘a,再乘以,那个,他最后应该得到的是一个零的这么一个解,然后因为他因为这个是pg等于零,我就从这个地方连开始,然后求一一开始求二。
对不对,这个时候嗯,就可以非常快速的去解出来这个,然后我们把这个p一啊,跟那个p0 同时带入这个matrix,诶,我们就可以把这个贝塔i给解出来,就是这是叫贝塔一,这是第一步,就等一个啥呢。
等一个它的分母p0 ,transpose a好,dfx x一就是x1 ,然后这个是p their transport a p0 ,诶这个系数也算出来了,我们就可以根据这样一步一步,如,何去迭代。
但我们最后写出来哈,实际上就是实际上就是这么一圈,对recedure,它的步长跟他recedure就是这么求出来的,当然这个是广告梯度,其实并不难哈,大家求的时候就是稍微注意一点,不要把公式写错就好了。
这个可能就matlab写,可能也就个五六毫,这个实际上这个是这是贝塔一哈,这个贝塔k的等于啥呢,贝塔k实际上就是等一个pk减一,transport a date,等着开,每一步都是这么过来的哈。
你这个时候算的时候还要注意一下奇偶性,这个有时候这个图像这个奇数,偶数可能会出问题,这个大家可能呃写代码的时候就会注意到,到时候会给大家讲一,就有遇到问题了,会给大家讲一下,这个不遇到问题。
这个我也讲不出来,然后呃这个然后讲了这么多呢,就是本身这个cfb的规定,那有啥好处呢,实际上这是我们每一步都去找他,一个最就是正交的,去找他一个最最大的一个梯度,下降一个位置,就我每每个每个p啊。
p1 p2 p3 p4 ,他对这个正定矩阵a都是一个正交的,我们在这个正交的一个情况下,就是始终去找他,他就一个点,因为这个时候就呃比较好,收敛到一个比较好的位置吧,就是一般好像过过梯度。
如果要不是发散哈,就是他会在n次迭代就收敛,他这个收敛速度还是呃比规范design呢,还是好很多的,所以说这个规定,这个ctrl t gradient,本身是大型的线性求解器里面啊。
就是通常使用的一种方法,当然大家在解这个后面的优化函数,里面也会用到,也会经常会用到这些风管记录法,我建议大家同学们回去之后,可以找一个写一段代码,稍微练一练,然后好应应对我们下一次的作业的来临。
当然我们像光梯度本身一个好处啊,但我们每一步也只是用了一个简单的卷积,并没有去上一些很复杂的一个大型星星,在这个计算,我们每一步呢也只需要呃,基本上就是一个iteration,就每就每。
个etivation只需要一个conclusion,那计算量也是比较呃小的,但我们为了更快速的求解,这个就ctrl这个鬼脸的一个线性求解,去密的不问题啊。
那这里面也建筑到了一个mate view的一个思想,就是大家学图形学的时候,肯定会学会mm是吧,实际上就是在像一个金字塔型的,就是不断下采样这么一个过程,就是我们每一步,对下一步初始化的一个值呢。
都可以建立在一个更小的分辨率的一个,结果上来去求解,比如说像我们这儿这第一步哈,诶我现在一个最小的分辨率,就像这么一个金字塔,诶我在现在一个最小的一个分辨率,先求一个解对吧,这个像素很少对啊。
比如说可能是呃,就1/256或1/512,这么一个小一个像素上,比上这是512的图,唉这就是256128 64 32,假设最小是32号,我们就先用这个32个图,然后来求解这么一个f诶。
这个然后再塞上采样,上采样到上一个阶段哈,到f64 哎,把这个上采样的值,当成对64x64的这么一个ctrl里,规定一个初始化的一个值,诶再来对上太阳一次,再把这个迭代几次,然后找到一个128。
只作为下一步的初始化的值,直到我们的原图,这个时候是因为它整个初始初始的一个值,更接近他呢,我们最后的一个目标值哎,这个时候我们就可以非常快速的一个,converge,就是也就收敛到我们想要的这么一个。
就是数据上,这个会让大家试一试吧,这个非常好玩的,用每一步初始化的时候就用上,就用一个law resolution的结果来去做初始化,这个到最后,我们的大图迭代次数就会变得非常少。
当然我们要先这个时候让大家回顾一下,我们整个的一个就变分的一个问题啊,我们这个扩散方程大,考虑到我们这个边缘的时候,我们除了求解这个本身,让它这个两个方向的规定是match之外。
我们还要考虑到这个bb的condition,比,较dh来帮助,condition,就是我们对这个precise情,就是先对这个做一个预处理啊,就我们要就解决这个af等于b的一个,现金的一个问题。
就是如果我们有一个可以e的一个直径,p对吧,但是我们对这一个可逆哈,这我们对这个p左左右两边,就a f等于b各成这么一个immortal matrix,p的一个逆啊,实际上它不影响这两个等式成立。
对不对,理想的情况下,我们这个这个理想的情况下,我们这个p啊跟a是一样的诶,这个时候就是a了,这个就变成一个identity matrix是吧,这个我们这个题就解出来了对吧。
这个但这个是很难遇到这种情况,我们一般也是不大可能直接遇到,这么好的情况,大家都都不用求解了,当然就说平时是遇到的,但实际上哈,如果我们想要的是这个p的逆乘,以a就是我们前面这么一块。
它有一个我们想要最后这个值更稳定,就是我们稳定了,对一个matrix稳定来说,实际上就是它的一个condition number更加稳定,也就是我们对应的一个,就其一直啊,就mhy对角线上。
所以说我们这个线性的系统就会变得一个,比较稳定了,就数值上会比较稳定,就是说我们想要用什么样的一个p值,来对这么一个线性函数来进行初始化呢,来进行预处理呢,所以说一个标准的一种玩法就是贾克比。
就是我们用这么一个甲克比,就是这个甲比呢,实际上是啊a的对角线这么一个值,因为对角线求你很容易嘛,这个就直接分之一就完了,所以说呢这是这是第一种玩法,当然还有更一些更有效的一些非抗毒性的。
大家可以试一试,所以说当然了,这个加了这个贾克比,等于这个对角线的时候也不一定是最好的,当然啊大家可以验证一下,就是做一些不一样的实验来证明一下,这个贾克比等于它对角线的时候,就a的对角线的时候诶。
它对整个的一个呃就是condition number,有没有让它更好,有没有,回到这个问题,就我们之前啊,这个matrix要解这么一个p乘p的matrix,一个是m乘n,这都是图啊,可能就是1k乘以k。
他们再乘以个1k乘以k这么一个图啊,好家伙,这个有这个elements太多了,大家不大好解这么一个东西,那边缘的地方大家要注意啊,边缘的地方大家最好拍进一下,或者是做一个。
当我们考虑帮助commission的时候,呃,我们明知道一些地方是好的,我们就不需要去算它,对不对,所以说在我算之前,通常就是先搞那么一个mask,诶,我搞一个mask,把这些地方不想要算的地方。
比如说像s们在这些区域呃,就不用update,就把这些屏蔽掉,哎我只update我想要update规定的那些地方,那就先搞那个mask,然后呢,第二个思路是啥呢,就是我们用convolution。
然后去击败一个拉普拉,shmrx,实际上就是用一个3x3的一个小矩阵,就替代了一个mn乘m n的,一个巨大型的一个计算的一个矩阵,然后呢,第三个就是用古典desc来去快速的求解。
我们这个mask引过的一些地方,就是需要update的地方,比如说我们需要update嗯,这个omega跟这个这些地方,对不对,对不错,我们需要就是up的这些地方,然后其他的地方我们就嗯。
这就直接给他out了,就不让他们再继续操作了,然后我们就可以用鬼点design或者contribute,不点des来快速的求解,我们最后它位置的这个f的这个值,嗯这个时候可能大家都有点懵了哈。
这个这个也很正常,就是给大家想解释的一个是什么呢,就是大家要求解一个呃,特别大的一个问题的时候,我们要培养一个抽象思维,我们要把整个的问题先去像这种,big map是什么,然后再把比如说我们这几张图。
我们就可以用一个f来表示,这就是它的一个抽象表示,唉当我们把这个抽象能力先锻炼好之后,我们再去解一些这个抽象框架下的,一个具象的问题的时候,大家就会把这个问题做了一个非常容易。
就是也就是大家以前所说的一个,架构能力啊,就是说但是现在不可能是我们教育啊,还不是特别完善的一些问题,就是给大家抽象思维的培养啊,并没有从很早的一个时间来做这个事情,那也就是一个问题啊。
你越能抽象的简单,就你能把一个问题出现的越简单,也就是你能解决的问题就更复杂,但是我也希望同学们在以后的就是,无论是工作还是研究生涯中,都能去主动地培养一些这样抽象的思维,把一个更大的问题。
通过抽象层级表达的方式,先去把这个框架理清,那就跟今天解这个,比如说解解的ctrlated gram的例子,就是大家就从呃整个的一个抽象的一个map,诶,我们找到了一个正交,正交的一个向量向量组。
然后从第一步找一个向量,第二步找一个向量诶,让它在一个正交的一个区间里面去左下降,这个时候就可以最快速的找到,我们最优的一个解,这个都是一个嗯从抽象到具象的一个过程,因为古人已经把我们这个具象的问题呃。
也不是古人啊,就近代就很多问题都已经解决掉了,但现在就是比如说很多地方,就比拼大家的一个抽象的一个能力的,一个问题出现问题的能力,而现在下面给大家介绍一下这个pose。
image editing的一个example,就是简单里面这个这个叫healing brush。
也就是嗯大家就是做photoshop的时候,就把一个这个叫什么刷子类,有点想不起来了,这个叫healing brush,就是把一块另一块东西拖到这个地方,叫黑in brush。
对于photoshop里的一个功能,那这是我们第一种是pschloe,就是用ps的方式把一边其他的一些图案,就是融合到这些地方,当然我们还有一些更高级的一些方法,就是我们考虑到这个高阶的一个dt。
我们像之前规定的只是考虑b阶了,那我们要后面还还还想考虑一下一个,我们规定的一个走向,所以说考虑二阶的规定的时候,有时候叫covian chloe,这个当然我会看这个效果会更好一些哈。
基本上看不出来这个是真是假,但有些时候我们的比如说我们的目标函数。
就是我们这个原始函数g啊,倒数里面有g往往的目标函数,把我的目标函数,s往上贴的时候,哎我们这个g比较暗的时候咋办呢,就我们ctrl比较低,我们想要往有很亮的图上去贴,你就会发现这个贴上的图。
它的对比度这个丢失对吧,然后怎么解决这个问题呢,其实很多时候还是借鉴了这个人眼的一个,lock space的响应,这人眼啊,我们去把这个整个空间进到一个log里,就小值变得更大一些,大值也没有变得更大。
所以说就拉到一个比较好的一个区间里面,就跟人眼的响应,将近四楼要借助这个思想,大家做在这个log space做beni,就可以收获到一个比较好的一个结果,然后考虑到其他的,比如像我把上面这张脸抠下来。
一块图贴到莫娜丽莎上面诶,那直接copy f能达到这种效果,不是很自然诶,我们用com blame,就可以拿到一个比较自然的一种结果,还有像这个就是透明的一些问题。
我们这个source image是一个彩虹,那贴到我们这个蓝天白云上面,这个时候也是pbb可以干的一件事。
啊这还有一些呃考虑到这个像这个混合。
所以像这种嗯混合的问题啊,加上这个搭载f往这个背景上贴的问题,像我们直接去把这个color提取出来,贴上去之后你发现效果还可以哈,这个当然这个边缘的时候,有时候会有一些白的呀,像就是特别是过渡的地方。
会有一些不太好一些art ex,然后用一些sty,就我们把这个呃克隆过去,然后在一些做一些缝合的一些方法诶,就发现诶这好家伙,这块背景全模糊了,当然我们要这个时候聪明的人们就想着诶。
我把这个ony的一些背景,做一个1/2平均,是不是就显得更自然一些呢,当然这个都不是特别好,就是因为我们那个整个规定呢,是在上面找那些方法,就是max similar colony。
就可以得到这种这样的一个效果,除此之外,大家还可以做一些像图像的编辑啊。
比如说我们这个他给的是一个小黄花诶,我把这个抠一下,先把背景换掉诶背景直接换一个颜色,这个时候就变得非常容易,当然我可以也可以直接对这个target,给它变个色,就变成橘黄色的话。
这样的话就让大家呃的一个photoshop的一个世界,也就更加精彩,就很容易的大家去做图像的编辑,给大家看看这个收缩效果,你拖一下呀,什么磨下皮啊,这个大家手上只是一个操作,但是他后面还是做了。
我们呃非常多的一些相关的一些计算,但像这样就比如说这个玩法叫遮瑕,有时候大家可能也理解为像什么磨皮呀,这可能就是我没用过photoshop吧,这可能就是photoshop磨皮的功能,还可以看到诶。
左边右边这个把这个背景都磨掉了,诶右边这个本来是有一个喷漆,然后通过这个磨一磨,都可以把这个呃本身才是不好的tx去掉,实际上它是什么呢,就我把相似的区域哎,我通过呃这么一个选取拖拽的方式。
把那个背景就用一个另一块地方,用另一块地方tt给他补上,那个思想一定它就补能补,这个大家想想是能还能补点别的呢,啊这是一个text sharping,就是我们这个梨子跟这个orange这个por。
换一换,你看梨子,梨子上面可能会有很多锈斑啊,但橙子会很光滑,大家把这个橙子上面搞点梨子锈斑诶,就是可以右边这种感觉说这个图啊,到今天为止看的就是可能都是假的,就有些很难看到真图啊。
所以说这个还有一些像呃像是不动的,这种情况下也是可以的,就是我们想要把我们图像上一块tector诶,扣下来去来去补这个洞,那实际上嗯我们可以用破损problem,或者一个拉巴斯的一个方式。
来来把这个洞给堵上,这是也是整个规定to my processing的,或者是破损不灵敏本身啊,干了那么一件啊普通的这么一个事,大家有兴趣的话可以看一下这个论文。
就是规定的shop叫accordido,my opposition form of for image and video fury,诶这个地方讲到了非常多的,就是这个代购链呢里面操作的一些方法。
这个可能是1516年的一篇paper,好像记记录的很清楚了,但是我们最常见的一种规定的操作的方法。
其实是隐藏在我们生活中啊,叫我们是把这个flash这个闪光灯好好的用,那么一下是可以达到非常好的一个效果,然后这个闪光灯到底是怎么玩儿呢,就我们可以看到这两张图,左边这个图就是打上闪光灯拍照的图。
右边呢就是没有闪光灯拍照图,我们可以看到当有闪光灯的帮助的时候,哎因为它比较亮嘛,整个的性价比比较高,我们看起来图就是嗯噪声会小一些,然后呢边缘很锐利,当然了,它的缺点就是他这个人工的灯照上去的。
它这个光,谱跟人啊,人也看到了不是特别一样,但是就是有一种那种宅人路口的一种感觉,当然就没有flash的时候,实际上是跟人眼看到的是一回事,基本上那这个时候因为它很暗,就会有造成的影响。
唉然后就因为i嘛,这个边缘细节和对比度也会下降,但是它是通过本身的语自然光来照亮的,就是看起来实际上是比较真实自然的,但是我们就是一个手机拍照,或者一个相机拍照就开flash。
关flash我们都可以自己控制,有没有一种办法,就是我们又想要flash的优点,但是又想要就是not flash的优点呢,有没有,办法把这两个优点结合起来呢,其实这整个蓬松,本来艇也是干了这么一件事。
但告诉大家怎么在鬼地点,怎么去玩这个事呢,哪怕我们就像nflash image,我们对它做一个dnoise,这可能是b mtd处理了,看起来会好一些,但是实际上有些地方细节还是被抹不掉了。
哎这个是原图哈,造成非常严重诶,看着可能还可以哈,但是还不够好,大家怎么样能变得更好呢,我们的中心思想先让它变得好呃,就是我们要flash的优点,又要nflash优点,它的一个核心idea是啥呢。
首先我们要想我们的目的,我们要保留什么,就是对一个not flash image,首先我们想要the noise对吧,但是denise我们就想要保住它的一个边缘,那这个时候其实这个是挺矛盾的。
他这个始终这个这个噪声,它对边缘的一个频率是有干扰的,所以说这两个很难兼得,然后我们能不能把这个flash的一个,在规定的等待,去往这个not flash的地方去融合呢,同时也解决这个造成问题了,哎。
这个时候就是聪明的人类,就想到了非常有意思的方法,首先说一下这个我们自然光的图。
跟flash pad to有什么问题,各自有什么问题,就一个自然照亮的一个图,iphant light,我们也可以看到它是比较容易有反光的,对吧,比如说像这个大家放大了看哎。
这个地方就是有很明显的这个地方,就一个有一个比较明显的这么一个圆的,一个反光,那我们开了个闪光灯呢,闪光灯像那种镜面,它就是一个镜子呀,哇这个立马就来了一个像这种亮斑啊,在这个地方诶。
这个我们能不能把这两个结合一下,把这个reflection跟这个亮斑叫hosport,给去掉呢,这个怎么玩呢,我们想一想它的规定动脉到底是呃,发生了啥呢,我们对这两张图融合,我们想要的是啥呢。
一个好的一个图,em的照亮张图,没有噪声,又好又keep到的它的鬼点子,然后呢,就把这个reflection layer就给就给它的规定,它本身不相符的地方哎,就把它分离开。
这个时候大家把它叫成gradient,叫reflection the year,把这个好的全留下了,把这个不好的全都踢走对吧,这个怎么做呢,其实有一个就是非常简单的算法。
就我们无论是对环境光照亮了这张图。
还是一个flash,就是我们的闪光灯照亮了这张图,就我们知道这整个图像的拐点的,它应该是在一个方向的,就是我们对这个图像本身的内容,他应该是一个就是在一个方向的,对不对,大家仔细思考一下,环境。
光照亮可以flash光照亮我同一个物体的边缘,当然是在同一个方向,对不对,就是梯度,它就是在同一个空间的空间的方向,只不过只不过是我开了闪光灯之后,我的这个规定呢值会稍微大一些。
也就是我们这个vector稍微长一些,值大一些,但是不影响我们的方向是没有改变的,对不对,但是我本身的reflection和我flash那些hot sport,这些地方跟我原本想要的背景。
它的规定在零上应该是不重合的,对吧不重,合会发生什么样的现象呢,诶这个我们就可以看到这个reflected,ambili规定的facture,就是我们不是背景本身它的一个规定的哎,它会有这么一个服务值。
朝这么一个方向,对不对,然后这个其实就是很明显,大家可以看到这个反反射的这个位,当有这个reflection的时候,我们也可以看到你很明显的,它的这个规定是受到反射的,这个图像的一个影响。
它整个规定的方向会有改变,一般哈就是因为一个什么性质呢,就是我们图像本身还是有一个spa的性质,还有这个spark的性质,我们就可以理解为两个,就是这个所有的基本上不点的都是零哈。
所以说我们两张不一样的特殊点,它理论上他们的就是最后相乘的那个值,非常非常小,就两个无穷小相乘,就是二阶无穷小啊,那就基本上可以忽略了,对不对,其实我们用到的也是这么一个思想。
当然我们这个reflection的一个ambient light,这个时候就会因为它不可能综合吧,实际上就可以分解成两部分,这个规定实际上就是本身我们后面物体,本身物体造成一个鬼脸的。
跟我这个flash造成一个鬼脸的,我们我把这个reflection往这个flash,规定的上面去投影,哎你就可以拿到一个receive固定的,就是这个我们最后的结果呢。
就是这个黄箭头标的,我们就是想要的一个gradient vector,也就是我们实际上就把这个反光跟这个flash,都去掉了这么一种结果,哎这个时候其实计算量非常简单啊,大家两个图各自求一个鬼脸啊。
找一下方向不一样的位置,然后做一个投影,诶,这个时候我们就可以非常容易的,把这个我们想要的一个干净的,又有好的规定,又有比较小的噪声,同时也把反光跟我过曝的一些,拍摄了一个反。
这是一个非常就是简单实用的一个idea,就是可能现在有一些手机上已经用到了,这些功能,大家可以拍照试一试哈,就对着晚上对着这个呃镜子拍一拍,或者对着这个玻璃半透明的玻璃拍一拍,看看啊。
你们开了闪光灯的时候,你最后那个结果到底咋样,如果你这个手机去把这个反光啊,给你自己的倒影去掉了诶,这说明这手机计算摄影做的还可以啊,那本身做起来就非常容易,flash分别求x y方向的一个固定的诶。
然后对这个规定呢做一个投影诶,投影出来的就一个没有噪声,噪声噪声又小,然后呃那个规定,它也就是它的边缘也被保持住了,这么两个规定了,然后把它合成起来,哎就可以拿到那个挺好的,最后一个结果。
啊说了这么多啊,就是其实现在还有一些很新型的camera,就叫规定的camer,有这个时候鬼点子,其实呃实际上就是差分啊,我们为什么要鬼点子呢,就是我们很多自然界的信息,大部分都是保存在边缘。
这些位置就我们自然界的图像的边缘啊,通常都是稀疏的,特别是我们两个图像融合有反射去除,我们利用的就是规定,它本身假设它不重合吗,两个稀疏的它可能重合的可能性也不大。
所以这是一个非常好的一个nature prior,而且呢这个规律它因为它是稀疏的,就是它的值很少,我们要存储的数据量实际上是非常少的,也就是为什么有时候大家像人啊,或者是昆虫啊,他那个眼睛观测到。
对一些运动会会更加敏感,对不对,其实际上我们人眼啊,始终是对边缘更敏感的,就哪怕到了今天在自动驾驶领域,大家为了这个整个自动自动驾驶的一个,就整个视频呀,或者那个摄像头定了一个标准。
叫contrast detection probability,就说这叫cdp啊,这个是一篇硕士论文啊,但是目前已经成为工业界的标准,就是我们对一个后面的目标,特别是vision的一些problem。
就我们目标检测的时候,我们通常都是对这,些边缘更敏感,这也就是有时候,大家为什么想要一个规定的camer,这有篇论文啊,叫why i want gradient camera raspa写的。
首先呢为什么我们要记住鬼点的,首先规定呢它的值非常少,我们很多的图像传感器,它的一个速度啊,通常都是被数据传输的能力而限制了,所以说呢它传输的数据少了,我们就可以拿到一个更快的一个速度。
但是呢数据量也很小,只是一个边缘的一个数据量传出来了,同时呢它还可以有一个很大的动态范围,这个你们想想你们要有一个鬼点开门,直接拍到鬼点的诶,我们就可以直接利用这个拍到的鬼点子,用一个pm s。
而且重建一张图像,是不是,然后在这个matter的鬼脸呢,直接重建一张图像,但是有时候呃,大家说说这个有些非常多的一些论文啊,就这几年因为一份的camer这个语音的camera,大家组合到边缘。
但实际上拿着这个引文的camera,大家不知道干啥,就是顶多是做个插针啊,或者是提高一下这个帧率啊,诶这个当然这个本身这个event camera,它是有一个更好的速度,更大的更大范围。
这个我们要用好的话,还是可以有一些比较好的一些应用,当然是现在可能还在一些探索的一些,初级阶段,就是整个应用并没有铺开,所以说我们还是可以用破松shower。
来结合了这个event camera去做不少有意思的事情,大家说一下,我们要获得这个gradient有几种玩法呢,然后第一种玩法就是我们改变这个传感器,我们可以牺牲一个方向的分辨率啊。
比如说这个x方向的分辨率,然后呢把两个像素就当成一个组啊,像素组诶,我们用一个模拟的一个差分的一个放大器,模拟的一个差分放大器,我们最,后只把这个差分搞出来,然后通过放大呀,然后再a d c。
最后我们直接就可以得到,就两个像素之间的一个鬼点子,对不对,大家可以用四个x y方向你都算了,这个有啥好处呢啊这个有啥,先说一下缺点,缺点就是提升分辨率了,而且呢我们这个感光的区域也是形成一半。
还有俩像素倒腾一个嘛,而且呢,为什么有有时候大家想这个,直接用一个模拟的差分,而不是用最后数字的差分吗,就我们就第九还是第十节课,我们讲这个noise image formation model的时候。
我们会分析了噪声来源,我们这个噪声对,当然我们前面最基础的信号,我们就知道有前面有一个dark noise,还有一个photo noise,就是本身光子积分的过程,一个noise,这个时候。
我们后面的一些造成了editality noise,就在曾毅在我们最后读出的那个白噪声诶,在我们你想想,我们读出的数都是有这两个白噪声的,哎我们最后的数字图像做相减的时候,做查分的时候。
这个白噪声也会对后面的结果产生影响,当然我们把这个这一步放到前面呢,就我们只把前面那个噪声,就是前面那个我后面的噪声,是相当于只用了一次,我只有一次放大和一次a d c,来读出了这么一个家庭造型。
在上面,就说这整个事情就会变得更可控一些,就是整个editing noise就是减弱了,但本身哈我们做差分的时候,我们就可以降低一下它的倍数嘛,就是我们采样速度实际上是更快的,就是最理想的情况下。
就是我们达到触发条件的时候,我们就去踩这个图像,就其他地方不踩,我只踩一个触发,有这个差分够大的时候,然后再去踩它,这个时候就是事件传感器,当然这个事件传感器不是呃。
它是在temple the man in去查分,这个后面我们会给大家讲到,本身这个基底啊,就是刚才给大家讲了,就是你这个dark noise跟这个hoto noise哎,这本身都有不可避免。
但是后面editality noise哎,这个时候就可以避免一下,这个数字读出来之后,再详解引起的一个呃每个误差,那本身我们考虑到前面就两个像素做,差分的时候。
你知道这个dark noise跟photo noise,本身就是一个破充过程,对不对,就你这个两个扩充过程相加啊,它还是普通过程,就是一个新的扩充过程,诶这个时候他这个噪声来源上面两个扩充。
这个放大器来一个real noise,还有a b c noise,怎么来一个,后面这个咱不管了,都是假象造成的,能考虑前面的这两个噪声,破声,噪声相减就得到了啥呢,这个我们课上讲到了这两个破松造成相减。
我们最后实际上是拿到了一个,gm noise,这个叫gm noise,课上也给大家讲了,这个skin of noise到底是个怎么回事,所以说这个sclage是很头疼的哈。
就是大家这个我以前试过想剪一个优化方,可能解了个ska noise,就发现这个还有一些基点呀,还有一些不可丢的一些点,这个就搞得非常麻烦,这个schedule很头疼。
特别是这个在这个在time of flight camera,就是top c,其实top现在本身本质上也是一个像素,有两个b,一个像素,一个像素有两个b哈,在两个并积分的过程中也是破损。
造成这两个你一个top两个像一个两个,后面两个就是就是b啊,相减的时候也是两个方向的点,最后每个就是top本身的饶图诶,也是有这么个skylar noise,哎,这个时候就非常头疼了。
所以说整个模拟就是continuous wave的一个time,flat,就变得非常难做,他那个噪声模型啊挺难的,然后另一种玩法呢,就是我们通过光学的方式,来把这个边缘去给它搞出来。
就我们可以看到左边是一个,比如说我们去apply一些optif,然后我们有一个就是微透镜啊,然后呢下面就有一些他的age future,template,age future。
就是大家可以看到右边的一个age future,一个形态诶,可以看到横着竖着,然后就斜着呀这种的qq,然后后面底下呢是一个复to detector,就是一个就是一个探测器,但有病的时候。
这些这个这些微结构啊,就可以把这个光栅上,实际上就是有这个变化的时候,就是光栅在这个方向,就是光在这个光栅方向有变化的时候,这个时候就可以呃进入到这个传感器,然后没有呢就可以被拦住了。
这个时候我们就可以拿到,直接拿到这个result的一个固定map,当然这这种玩法也是有很多缺点的哈,这个缺点是啥呢,首先就是因为他前面加了规定的fter了,这个时候我们本身的进光量是降低了的。
因为我们已经挡住了很多光嘛,第二个就是我们不是就像做这种光学系统,也不是特别容易,但这个我们刚才讲到了一个规定的camera,就可以搞这个sensor或者搞optics来实现。
当然这个还有一种新型的一个temple,relievent camer,这个叫叫时间相机啊,它只能记录在事件发生的一个边缘,大家可以看到左边这么一个事件相机,它记录的都是一些边缘的信息。
就是边缘有变化的时候,我去触发让我传播过来的一个指示,触发边缘的一些数据就变得非常小,当然特别是这个有时候也叫dance cubation sense,也叫dvs,所以说这个可能大家会见到。
当然我也知道有很多嗯,像消费电子想用到这些东西,就是但是因为搞明白就用它干嘛,这个嗯我可以帮大家想一想啊,哈这个时间相机是怎么回事呢,比如说我们一个传统的相机,我要拍这个一个黑点。
在一个圆盘上运动这么一个过程,我们可以看到传统的一帧一帧的图像,哎每一帧这个圆点有一个变化,但事件相机呢我每一帧图和传送带的变化,只是这个边缘变化的过程,就是我们传出来的图。
只有这个边缘这么小一圈圈这么个地方,然后呢本身像我们如果我们不考虑这个,没有这个就不考虑这种鱼的一些信息啊,就没有这种游戏,信息就是没有,就是就是完全一个静止的一个状态,哎每一帧图出来就没有任何变化诶。
所以说这个时候我们这个规定的,本身没有拍出啥东西,就是最后一个no,问这个一是降低一个根号,二是速度很快,我只需要传我记录下来的一个事件,然后第三呢就是它本身可能就纯,大家很多时候就做了差分。
过的比较细就完了,所以他这个最后拿到的都是一些边缘,这个even的camera呢就是大家很想用,但是总感觉这个挺鸡肋,食之无味,弃之有肉,也就是其实现在很多学术界还是需要对,这个一定的。
规模进行进一步的探索,来发掘它商业上的应用,我相信就是有一天也不远吧,这个问的camera,还是会走进大家的日常生活之中,在这些文的camera,在一些robotics里的应用,我只救了这些边缘。
这是一些像盒子呀,像kitchen啊,物体啊这些一些记录一些边缘的信息,诶,有人也拿过呃,这个边缘去做那个图像的一些增强啊,边缘增强啊,或者是呃dex边缘增强啊,其实这个大家都可以自己想一想。
这个到底有啥用,这这同学说的,但愿这个希望是的,因为这个毕竟是仿生的嘛,我感觉他还是,后面我们那个整个研究基础上来之后,还会有一些仿生的一些应用吧,这个肯定是少不了的,那这是一些参考的一些文件。
大家感兴趣可以自己看看,今天就给大家主要分享啊啊这个boss的sober,大家记住啊,这个古典decent并抗拒古典,特别要想清楚这个control green,它的每一个一个reset p。
它对一个正经的矩阵内,确可是a它是相互正交的,这个大家要理清楚,而且正交的方式我是比较有把握,收敛到一个呃比较有机知识点,当然这个时候,我们今天面临的问题是凸的问题啊,当然还有一些就是非凸的问题。
大家有时候就会讲一讲,这个就是soft taxi固件descent啊,或者是呃就是统计的一个cvt固件的,这个大家后面应该都会遇到,然后给大家分享两个经典的应用,一个是psu mate action。
你这图像编辑,第二个就是flash的pop,诶,这个flash flog大家可以比较容易的去试一试,然后最后就是给大家讲一个有古典的camera,还有一个optics的方式,还有一个汉字分手的方式。
来实现这一点点的态度,大家可以仔细想想,这个规定到底有什么用,不定的carry了,哎希望大家有个愉快的11啊,今天的课程就到这里,大家有什么问题可以去快速问一下,大家有什么问题吗。
呃现在有很多用神经网络来做普通混合的,这个我见过有非常多了,就比如说大家不动啊,实际上干的都是这个破碎不连的过程,但我没有去看他哪个结果好啊,但是我知道是有的,其实这个大家很多时候用干就来嗯。
这个做这个pos bending,但实际上大家想一想啊,我用这个神经网络,神经网络是干啥的,本身我们前面的神经网络层次,都是在把整个图像的一个特征进行分解,我们把这个图像的特征去抽取出来。
后面的一些网络呢,实际上大家通常可以理解为是一个encoder,就是我们把前面提取出来的特征,再去给它组合起来,但实际上放松不能紧,实际就是你要别做这么一个任务的时候。
他就是对这个feature的一个重组,我们也是对一个feature的融合,只是提取的过程,是我在一个我们一个已知的一个prior,往下来进行这么一个提取和融合,就是大家可能后面接触的多了。
就会发现天下武功都是套路都一样,你无论是用神经网络也好,还是用这个那个就是我们优化的方式也好,它本身都是呃,基于它对整个成像过程的,一个物理过程的一个探索,同学们还有问题吗,好家乡同学没有问题。
那祝大家呃10 11快乐,这个那11,大家就11期间就不给大家布置作业了,就之前的作业在11期间会放出来,大家好好巩固一下,玩一玩,11过后,我们就给大家搞一个合同混合的,这么一个题去玩一玩。