13.引擎工具链基础 | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV11T411G7qB
欢迎回到games104,现在游戏引擎的理论与实践,哎呀我忘了拿我的遥控笔了啊,现在已经是哎你找到了,然后现在那个就是已经是6月下旬了,不知道同学们有没有开始进入暑假,我反正是有点不太习惯。
因为我以前印象中暑假总是在7月份开始,为什么6月中旬我们就进入暑假了呢,所以我要花点时间稍微试一下,但不管怎么样的话啊,我希望同学们有一个非常快乐的一个暑假,那首先的话呢。
回答一下我们社区女同学们给我们提的问题,那其实在过去的一个多星期吧,我们在社区里面大概回答了还是蛮多问题,大概有200多个问题吧,各种各样的问题都有,不过呢我们现在发现一个小小的问题。
就女同学悄悄的告诉我们说,那个有些问题,其实他们有些很简单很基本的问题,但是呢他们不知道这样的问题是不是合适问,或者说很怕自己问出来,显得自己好像我的水平是不是不够高啊,我非常能理解这种感受。
因为我以前也是这样的,我特别怕那个有人问有没有问题,我又问哎,我问了一个问题,大家都看见,我都笑了,其实这是很正常的一个担心,但是呢我觉得就是,这其实就是我们要克服的东西。
我反而觉得大家千万千万不要觉得,你的问题简单,每个问题都应该值得被回答的,只要有同学有问题,只要有同学问题不懂,那就是我们games104的责任,我们要跟大家讲明白了,跟大家去讲懂,所以呢有的时候。
我们真的想听到大家那些真实的问题,因为很多时候如果我没有得到大家的问题的话,我们会误判,我们会以为这个问题其实很简单,这个就这个那个公式可能很简单,这个方法可能是大家都好很好。
懂这个地方我是不是可以讲的简单一点,但是当我们收到了,同学们越来越多的问题的时候,我们就会意识到哦,然后那一趴同学们还没有基本的概念,我们需要给大家解释清楚,因为其实这门课程的跨度是蛮大的嘛。
就是从比如说大家看看有一点点编程基础,甚至是没有基础,到已经有从业了好些年的我们的行业内的同学,但是我讲的话就是说呃,其实每一个我们的课程的同学,你的问题都应该被尊重。
所以我特别鼓励大家把你的问题提出来,千万不要不好意思,因为我作为我来讲的话,至少我是很愿意那个回答这些问题的,而且这也是我们的一个责任,另外一个的话呢就大家也讲了,小引擎,大家阅读起来有很多困难对吧。
然后呢我们现在确实在一公在做一篇那个文档,做一个文档,就是试图结结合大家的问题,把小引擎中的一些难点,一些困难点给大家整理出来,因为最近在准备课件呢是压力特别大啊,今天我们这一节课的课件。
准备的是我们压力最大的一节课件吧,然后的话,所以的话呢实际上分给小引擎的时间不够多,这也是我们这个课程本身的挑战,因为104的课程,和其他课程有一点很大的不同,是说我们所有的东西都是现做的。
就是说它不像其他的课程,老师们都有在大学里讲课的课件对吧,游戏引擎这个东西的话,首先他的资料非常的分散,而且很多的技术啊概念啊,在行业内大家都是有debate,就是都是有争论的。
然后呢我们就会非常的小心谨慎,然后因为我们认为这是个中立的课程嘛,所以我们就会把各方面的资料都搜集搜集一下,然后基于我们对行业的理解,尽可能给出一个A记,这个相对中立。
然后呢又相对客观的一个一个一个描述,如果实在我们搞不清楚,我们就承认我们不懂,我们搞不清楚跟大家讲问题在哪里,所以的话呢就这个课程准备会花很多的时间了,那我们后面会把更多的时间分给我们的小引擎。
给大家更多的解释,我们在准备这个文档,那么另外一个的话呢,就是说其实同学们有很多问题,关于我们的小引擎呢,比如说我们最近收到最多的几个问题,比如同学问我们说,为什么你们要选用win这个API呢。
这个好抽象,好难啊对吧,这个同学们在学习图形学的时候,一上来学的是什么,肯定是open吉尔,我学图形学,我学的就open吉尔对吧,这个这个什么set一个VIEWPORT对吧,set一个gr。
You look at,一个最好最好用的叫GRUT,那个那个那个工具上来设置一个什么look at,就可以把所有东西全部搞完,那么为什么我们会选择win这么抽象,这么复杂的一个东西啊。
这里面的话呢我们要跟同学们汇报一下,就是我们的想法,就是首先的话呢,就是就像我在那个图TOGRAPHICS,那节课里面讲到的,就是呃104的课程,特别想让同学们明白,就是啊我们的游戏引擎这个行业。
它真正的未来的一个发展方向,那么这个毫无疑问的就是说现代graphics硬件,特别是有信心,我们会走向越越来越用户可以定制,可以自我去规划pipeline的这个时代。
特别像computer sor这些东西起来之后,所以的话呢像van像DX12,它的设计理念相对于上一代的graphic a API,比如像DX11对吧,那个open gl的早期的版本。
那是有有一个代际差的,所以呢我们就给大家直接打开了一个hard模式,就是说直接我们就看未来,因为同学们今天学的这些知识,你今天很难学不懂,没有关系,但是呢你至少你的foundation是正确的。
然后你未来如果你真的想在这方面精进的时候,其实你的基础就相当于你上来就直接学,学习这个下一代的东西了,就没有在这个浪费在这个前面的东西,就像我们国家造航母一样,对不对,我们直接上来电磁弹射了。
我们就不要搞蒸汽弹射了,对不对,因为那个技术积累的也没什么用处对吧,这个逻辑其实就是这样的,那么当然但是的话呢就是说呃选择,我可能还有一个点,就是说他是真正跨平台的,因为DX12和van其实是等价的。
但是呢DX12它主要是面向windows平台,那我们很多同学有的人在Mac,有的人在LINUX上对吧,包括在移动端上面,所以的话呢wen在这一点上是有很大的优势的。
那么接下来的话呢我们这所以在这节课程呢,我们给同学们提供了两个reference的这个网站,大家有什么关于motion的问题,在上面可以查到,具体的PICOLA的上面的问题的话呢。
可以直接问我们的课程组,那么另外一个同学问我比较多的问题,就是说哎我们什么时候能用开源,这个这个就是说我们的matt passer对吧,就是我们的反射的这个这个处理器。
那这个其实是也是最嗯应该就是难度比较大吧,就是其实这里面要用到一点点的这个LLVM呢,这些就是说这个这个这个C浪的,这些东西在里面,但这个东西的话呢,其实我们在后面首先要在课程配合课程。
因为我们这节课要讲啊工具,工具的高级里面会给大家讲反射,摆设里面会跟大家讲一下它的一些基础原理,应该是在工具这节课讲完之后,我们差不多同学们开始把这个代码开源出来,但是具体的时间的话呢。
也给我们课程有一点点点时间,就是我们要还要再做点准备,然后包括文档各方面尽可能配套的齐全一点,但是呢大家不用担心,这个地方我们一定会开源的,因为我们小引擎的精神就是开源嘛对吧,那么还有同学们就问我们说。
就是说哎呀,我的这个小引擎的环境好难搭建起来,这个其实我们非常能理解,因为呃实际上我们是一个两难问题了,就是一开始比如说像我学编程的时候,那我就是用那个简单的VC打开了,我就可以直接建个工程对吧。
那在那小引擎里面,其实对大家有一个很大的卡点,就是说你需要用一个SEMAKER去生成,你的整个一个project ution文件对吧,而且你都你如果是Mac,如果你是这个PC,它的方法都不一样。
这个呢跟之前我们的遇到的调困难也是一样的,就是说如果你想提供一个,跨平台的解决方案的话,我们没有别的选择,SEMAKER就是一个最好的一个选项,但是这就是我们的一个门槛。
所以其实呢呃我所以我的建议就是同学们,第一个包括我自己在聊,我其实因为小引擎最开始环境搭建不是我做的,是我们团队同学们一起做的,那然后我也是严格的按照read me1步步操作。
然后呢其中有几个地方的修改,还是因为我操作遇到了卡点,然后我们大家一起来修改它,那么另外一个的话呢,就是啊同学们的话呢就是可以查一些资料,我们这边也给大家一点点的这个。
environment setup的这个资料,那同学们其实如果以上步骤都用过了,还是有问题的话,就像我一上来讲那样,大家不要不好意思,直接就问我们就好了嘛,我们有那么多的微信群,大家就问我们。
然后我们课程组的小伙伴们,还是会非常的积极给大家回答,所以的话,希望同学们能尽快的进入到,皮克拉这个小引擎里面去遨游,那么其实皮克勒引擎的话呢,它本身的feature呢我们目前来讲。
经过这差不多有两三个月的发展机,特别是课程开始之后的一个多月,因为也收集到同学们的反馈,很多同学也在基于它开发,那我们基本的体系,其实已经构建的还算是比较完备了。
包括那个playing editor整个一个编辑模式啊,包括我们有基于forward ring的整个技术架构,shadow啊,我们的那个就是动画系统,还有我们最近刚刚接入的我们的物理系统。
有同学在问我们说,诶为什么你们要接joy这个小物理引擎,那我跟大家分享一点小小的背景故事啊,首先这个引擎呢我们是真的认真挑过的,因为我们要选择一个非常清亮的一个物理引擎,因为因为物理引擎的选项很多啊。
比如像我们以前啊都用过的,像havoc physics x对吧,那包括就是还有其他的一些开源的物理引擎,那为什么选择joy,就是因为它很轻很小,就是如果大家有兴趣的话,你可以进去读的,如果我没记错的话。
他只有几万行代码,另外一个的话就是这个引擎虽然小,但是诶人家是被大作用过的,就是然后像horizon地平线这样的作品都用过,它作为他的这个物理引擎,所以我觉得它本身算法呀,稳定性啊。
鲁邦性能没有什么太大的问题,所以的话呢我们就把它接进来,这样,因为我们认为,就是如果大家想做一个小小的游戏引擎,没有物理的这一趴的话呢,感觉就会差很多,那么在最近的话呢,随着我们大家一起努力。
我们把character啊,MOTO系统也都装了,装了进去,所以今天的小引擎呢,实际上呃基本上已经满完备了,它本身还能继续windows linux,Mac os,就像我们同学讲的是。
我为什么要学104这门课,我觉得你学完104这门课,至少有一点就是你在做毕设的时候,你去pica这个引擎做出来的东西,我保证你可以秒杀你的这个那个室友对吧,那么所以的话呢。
这就是呃我觉得一个非常有意思的,一个一个一个一个一个目标吧,就是我们的课程目标就是学完104,人均一个自研引擎,那今天的话呢就是先花10分钟,跟同学们回答一下我们前面的问题。
那接下来开始我们今天的正主了,今天这节课讲什么呢,我们今天就讲一个这个游戏引擎里面,我认为是最默默无闻的奉献者,就是工具链对吧,因为在游戏里面我们看到的都是,比如说把每一个游戏引擎,它在宣传自己的时候。
没做的时候,都说你看我有什么什么特别厉害的光照的效果,特别厉害的视觉效果,特别厉害的逼真的物理仿真,很少有人会讲说诶我的工具是有哪些进化,为什么呢,因为大家听不懂对吧,老百姓哪知道什么工具是什么。
但是呢你在看他的第二天,基本上基本上是第一趴的时候,到第2part的时候,才会跟你跟专面向专业知识讲诶,同学们,我们最近工具又做了什么升级,但是呢一般像我们真正做引擎的人的话,第一趴我们看看也就过了。
基本上5分钟就明白了,但是呢我们会真正花时间看的是,他在工具上做了什么变化,因为这才是引擎最核心的一个东西,好那整个引擎的工具链呢其实是非常大的,一个就是一个一个就是一个一个模块,那这个模块的话呢。
我们其实大家知道,我们最近课程的日程做了调整,本来工具链我们只有一节课的,但是我们做完准备之后,发现工具链一节课根本讲不完,所以我们就把它毅力是真的多加了一个课程,当然了,有另外一个模块被我们挤掉了。
一个课程我们就不点名了,好可怜,那个模块被我们挤掉了,那么我们工具链的话呢,就是我们今天第一趴先讲它的基础,就是说诶你怎么去构建一个最简单的工具链,怎么能解决他的资源加载,这个存储。
包括就是怎么能够让这些工序之间不要打架,能形成一个链条,就数据可以可以传递,怎么样实现一个最简单的就是那个what you see is,What you get,就是说所见即所得的这样的编辑。
包括工具链的这个plugin系统,这是一个工具链最基础的东西,那么到第二讲的时候呢,我们会讲一些相对比较高级的东西,第一就是说在一个实战型的游戏的这个这个,pipeline中。
这些工具到底是怎么在一起协同工作的对吧,你到底需要哪些编辑器,每个编辑器的实际的要点是什么,那么第二呢,我们会跟大家讲一些工具链比较深的,比如像反射,大家很关心的。
也是大家一直想问我们要的matt faster的源代码,如果你不懂这个反射的这一趴的话呢,那个源代码给大家,大家可能也很难看得懂对吧,包括在讲一些高级的概念,比如说像协同编辑。
所以的话呢我们把整个工序分成两趴,第一趴基础,第二趴高级还是我们的传统节奏好,那我们就开始我们的这个就是,首先给大家讲一下,游戏引擎的工具链到底是什么,首先的话呢,其实这是一个我们自己画的一个游戏引擎。
架构图吧,就是我们已经跟大家讲,就是说游戏引擎它本身的复杂度啊,真的像一个小型的操作系统,基本上现在一个游戏引擎都要达到,千万级代码的这个复杂度,那么在很多时候呢,我们看到的很多人都会把渲染。
或者把一个这个这个rendering当成一个游戏引擎,但其实游戏引擎渲染只是其中很小的1part,那我们会说物理仿真是不是游戏引擎呢,物理仿真也是其中的一趴对吧。
那好网络通讯这个状态模拟是不是这个物理引,游戏引擎呢也是其中的一盘好,你把这些东西全部合到一起了,你得到的东西是什么呢,是一个one time,就是它的一个我们叫做engine erra。
但是在engine之上有大量的工具,其实我们在第一节课也讲到了,比如说各种各样的editor对吧,比如说大家最常见的就是场景编辑器,我在这儿可以构建一个我想要的世界。
然后这里面的话我要编辑各种各样的游戏逻辑,像连电路板一样的,我们一般叫做graphic editor或者叫blue print一样,有些游戏里面叫blue print。
游戏引擎叫blue print对吧,我们还有各种各样的这个材质编辑器,SHADER编辑器对吧,还有脚本编辑器,各种各样的东西,那这一系列常常的东西啊,它的复杂度或者说它的整个体量,一般来讲。
如果对于一个成熟的商业引擎来讲的话,它的复杂度是会超过软弹的,也就是说我们觉得RUNTIME代码很难写,对不对,但是引擎的工具链的代码的话,它的总开发量,开发成本实际上是会高于引擎本身的。
这个是一个就商业级引擎里面的一个general practice,那么这么一个庞大的庞杂的系统的话呢,实际上它的基础最坏的基础是什么呢,我们叫做DCC就是DCC,指的是就是说各种各样的。
比如像3D max maya zbrush,就是PHOTOSHOP对吧,还有那个现在比较火的,像胡迪尼这些第三方的这些软件,它们生成大量的资产素材,这些数据都是易购的,它要经过我们的工具工具链。
然后呢行进入到我们的整个的引擎的pipeline,那这个地方的话有一个词儿,就是那个大家以前讲过的,就是那个ACP对吧,就是那个就是acid conditioning piapi。
那么工具链其实就在这个CP这一层好,那么工具链呢实际上它真正解决的问题是什么,这个也是我想让所有学过游戏引擎开发的同学,你将来拿去跟那些没有学过以前的同学去解释,你问为什么引擎要做工具,工具。
核心解决问题是什么,那别人如果告诉你说哎他只是为了做编辑,生成游戏数据的那会,我你就可以嘲笑他,说,不好意思,你这个讲的还是业余的,我给你讲一个最专业的观点是什么。
其实引擎工具它最核心解决的问题是什么呢,不是其实只是仅仅是为了造游戏,实际上是什么呢,它在调和几种不同思维方式的人在一起,协同工作的这么一个平台,为什么呢,其实我大家想象一下一个游戏团队。
他真实的情况是什么,最最简单的有三类人,第一类人呢当然是我们思维方式特别严谨,动手能力非常强的程序员同学对吧,那么他们就是每天加了个眼镜,穿着格子衬衫的程序员同学,那一定是非常严谨,逻辑性很强。
什么事情都要跟你讲逻辑,还有一类是什么,我们的artist artist,他不在乎你的这个算法是怎么回事,你的这个光照模型的底层数学物理,物理原理是什么,我要这个颜,这个这个山水更暖一点。
我看见那个更冷一点,对吧哈,我然后我要这个场景,这个角色动起来的话更有质感一点,好吧,这些语言和我们程序的语言是完全不搭嘎的,所以他对这个世界的理解是非常感性的,非常非定量的,但是呢它又非常敏锐的。
那么artist对这个就是游戏的这个,它的它的表达,实际上是一种用户体验向的一种表达,好接下来还有是理派人是什么呢,就是我们的设计师非常有创意,对不对,哎我希望那一拳打下去。
能够能够打出一个非常爆炸的伤害,而且我每一下打击的时候,我一上来速度要慢,突然一下子加速,我要的就是这种打击感,我要的那种刀刀,这个什么刀刀入肉,拳拳入肉的那种感觉。
那designer的想法又是不一样的,他很在乎就是游戏的打击反馈,很在乎游戏的这种数值的合理,那这三类人在一起的话,其实他所需要的这个就对于同样一个游戏,这三个人打开各自的工具的时候。
看到的东西是完全不一样的,对程序员看见的是各种数据在跑这个场景里,有多少个静态,有多少个公仔舞对吧,而艺术家看见的是什么,诶,这个色彩我要调,我上次在上节课给大家讲的color grading对吧。
还记得吗,就这个就是artist,非常符合artist的感觉,我要的是这种感,这张照片的这种这种年代感,完了程序员就疯掉了,但是artist明白他怎么去表达这个世界,那他需要有自己的工具。
当然其实跟真正需要的更复杂,那么designer看见的是什么呢,一堆的这种这个这个策划数据,比如说我打击出去的P,我打出一个叫什么攻击体,就是在我的角色前面画一个形成一个方块。
你的每个刀回过去的地方形成一堆方块,然后哪些是暴击区,哪些是轻机区对吧,然后哪一个地方我能把对方打出硬直,所以其实我们的工具实际上是让这几种,说完全不同语言的人在一起,能够共同演奏一首乐曲。
所以我经常把我们的一个游戏团队,想象成是一个乐队,是一个交响乐队,然后呢游戏引擎的话呢就是调和啊,游戏引擎to chain,工具链,就是调和这种不同设定的人在一起工作的。
这样的一个基础的foundation,就是呃基础的这样的一个基建的一个东西,所以这是我们理解就是说这个游戏引擎啊,two chain在整个游戏研发中的一个定位就是它,所以它在设计中的话。
他要充分考虑到不同的使用者的这个思维习,惯和要点是不同的,这个需求不同好,所以的话呢其实以这个为例的话,大家看见这个引擎在就是这个工具链,这是我们选的real为案例吗。
就是从一样输出的白魔的这样一个关卡,那你们看见artist,它会在各种各样的工具里面换来换去,它一会儿构建你的材质,一会儿做一个小的物体,然后迅速的去摆放,最终的话呢能形成自己这样的一个世界。
这这其实这里面就看到,这大概将近30秒的这样编程里面,其实它已经involve了很多,很多的工具模块在里面,我在后面会详细详细讲到这里面,比如像particle有这个材质的那个party蓝图对吧。
各种各样的东西在里面,这里面还更多的只是展示了artist,实际上策划那边的话还没有完全展开,那么工具如果我们想要做工具的话,那首先最难的一个东西是什么呢,是各种各样的GUIJI是什么。
就是这个graphics user interface,就是说其实啊我们的无论设计师也好,还是美术也好,当我们面对这个这个游戏引擎的时候,面对我打开工具链的时候,我要输入大量的数字,我要调很多东西。
稍等我喝点水,然后其实呢,你就会有大量的user interface的东西在里面,那这个在最早期的时候,大家知道我们啊,应该大家可能还不记得最早的这个月,人机交互界面是什么,全是文本对吧。
在最早的叫有一个操作系统叫DOS系统,到那个DOS时代,然后逐渐变成了windows时代,而现代游戏引擎,我们的工具链,用到的GOI其实是非常非常复杂的,那么有各种各样的控件在这里面。
这么丰富和复杂的UI的话,其实你要作为一个游戏引擎的工具链的时候,你首先要会驾驭这么多的GUI的东西,那这个事情简单吗,其实非常的复杂,那么这里面的话呢有两大类,大的这种实现的方式。
第一种呢我们叫做immediate mode,就是直接模式,它其实非常简单,也很淳朴,就是说OK我想画一个这个编辑框,我想画一个下拉框,我想画个按钮,OK我就画吧,直接画上去,你决定画就画这样。
每一帧的时候有游戏逻辑,直接告诉我的这个GOUEI系统,说我要画上我的控件,那这样的话呢就直接打到这个空间上去了,而这种模型呢其实是非常简单和好用的,它的好处就是直接直接简单,而且的话呢也非常的这个快。
非常容易去剖了胎,但是它的坏处是什么呢,就是说扩展性是有限的,另外一个的话呢,就是说其实他会把很多的业务压力,压到了我们的逻辑这一点,那么其实在其实现在有些引擎呢,就是它的GI系统部分还在用。
比如像unity的UGI对吧,包括像OMGUI系统,包括像我们的小引擎的GI系统,也是这样一个直接模型,它比较简单,但是因为它实现起来比较简单嘛,但是呢另外一种,当我们去做工具gr的模型的话呢。
我们一般会用什么呢,叫RETURMODE,这个return mode的话,大家解释一下,就是最简单的一个理解,就是当我要决定画什么什么东西的时候,我并不是直接画到屏幕上去,我是先说诶。
我要画画一个box,这个box是大小尺寸是什么,我把这些所有的信息全部交给一个一个一个,其实很像我们讲的graphics里面的command,buffer一样的,我把我所有的这些指令全存储在这儿。
然后到了那个GUI的自己绘制的,那个逻辑的时候,他自己根据我已经存的这些指令自己去画了,这样的好处是什么呢,我相当于把这个游戏的这个逻辑和,和这个rendering好吧,把这个就是这个UEI的。
这个不就经常讲的游戏会混了,其实工具它的这个GUI的话两个分开来了,那么这个模型的话呢,它的好处就是说扩展性非常的强,而且性能也很好,为什么,因为你的这些命令全部catch到一起。
它不会是逻辑执行到一层,他就画一次,而是说全放在一起统一处理,另外一个的话呢,就是说如果你不去改变它,你就不用再去更新它的指令,这个其实呢也是非常符合我们的这个游戏,架构的理论模型。
所以说其实目前大部分的游戏工具,用的GI模型的话呢,实际上是这个return mode,那么比如像unreal的这个这个UI啊,比如像最著名的WPF。
就是windows的那个那个presentation foundation,就是windows的那个就是他做UI的那个框架,包括像大家特别喜欢的qt,我知道在大学里面同学们做很多课件。
做很多实验的时候特别喜欢QQ,因为我也蛮喜欢qt的对吧,其实也是用这样的一个模型去做的,所以说这其实是我们在搭建机UEI系统,最主要的两个大的方式,那我们肯定会推荐大家用这个return mode。
那么因为GUI是我在做工具的第一个房间,就是我首先性能画绘画空间,我不会画空间,那怎么给大家做工件呢,做工具呢对不对好,但是这个return mode实际上再往深处去讲的话呢,它有很多的叫设计的细节。
这个细节是什么,叫我们叫design pattern,就是你的数据怎么去组织,你的绘制,怎么你的view怎么去组织,所以这里面同学们如果学过design pattern,女同学的话。
一定会想到说诶这个地方我们是不是要讲一些,比如说MVVM啊,MVPMVC啊,啊对你猜对了,其实这个地方是非常重要的,就是在我们在讲design pattern的时候。
就讲这个就是整个工具的UI系统的构建的时候,其实design pattern非常的重要,否则的话呢你很容易去写诶,一个两个工具,写一个两个功能,当时当你写到一个工具里面有上百个功能。
然后十几十几个工具在一起的时候,如果你不去遵循或者遵守某一个design pattern的话,那至少以我的开发的经验来讲的话,基本上一定会炸的,这也是做游戏引擎很有趣的一件事。
就是说它是一个非常考验我们的,就是工程架构能力的这样的一个软件开发,那么在这里面的话,最著名的几个pattern的话,比如说我们称为鼻祖的叫VC这个model对吧,这个是这个就是1978年提出来的。
这个是真的很早真的很了不起的一个model,它其实最早要解决的问题其实非常的简单,就是说哎以前我在做UI的时候,我UI中有大量的代码去修改我的数据,数据中间有很多逻辑,那你这个UEI万一改错了怎么办。
而且数据要改逻辑,你们的那个叫view要改你们逻辑你的数据,然后逻辑又要改UEI的呈现,它两个代码系统就全绕合在一起了,所以说在40多年前,大家就提出了MVC这个模型,这个模型其实我个人的理解啊。
就是大家很多人对control理解每个人都不一样,但我个人的理解就是,我认为他其实把这个数据流清晰化了,也就是说你从model是单向的到view,然后view呢不能够再反过来写model。
所以所以所以说你可以认为,就是model这个把数据输送给view了,但是model本身不会被弄脏,然后呢,你如果想修改这个model里面的logic的,这些数据的话,你只能通过control。
它会进行各种处理,各种过滤,然后再去修改你的model这样的一个结构,这个环流的话因为变成单行线了嘛,所以很清晰,很容易切断,很容易管理这个就像我们城市里面交通的时候,如果都是双行线。
然后全交错在一起的时候,你就很难管理交通,对不对,你们会发现诶,有些地方为什么实现了一个叫这个这个,单行线的管理,其实也是这个逻辑,那么其实这个MVC的话呢,实际上是一个最经典的。
就是一个把这个就是view和model decoupling,开来的一个架构,这个架构的话呢实际上现直到现在吧,在web前端还有很多用处,而且的话呢大家也是就是对他做了很多的变种,很多的眼镜。
真的它的变种是我目前知道是最多的一个,一个pattern了吧,那么在MVC之后呢,另外一个模型的话就是MVP模型,其实我比如说我在我在当时大学VC的时候,我的第一反应就是为什么我这个时候还要把view。
还要去知道model呢,对不对,我view可不可以完全不知道model的存在诶,我后来等我学到MVP的时候,我就发现哦,原来我这个笑话别人老早就想到了,其实MVP我可以认为是一个更彻底的一个。
把view和model decoupling的一个模型,就是说OK,你view完全就不知道数据的逻辑的存在了,那么这里面只管这个他自己的各种展示的空间。
那么presenter呢他负责从model里取数据,然后呢呈现给view,也负责从view里面的这个用户交互反馈给model,这样的话他这个好处是什么呢,就是像我们这种超大型的软件工程。
我有很多的功能模块嘛对吧,其实我们最大的一个需求是什么呢,就是unit test,就是说我要做单元测试,比如说我要测试你的逻辑,对不对,那你你的UI做还是没做,你做成什么样。
其实跟我的这个model的正确性没有太大的关系了,大家想想对不对,比如说我的model里面一个叫学生成绩排名系统,我的model里面有学生,这个学校这个什么三好学生评判系统。
那和你在view中怎么去展示三好学生的话,是不是没有什么关系,那这个MVP模型里面的话,就是说他把这个就分得很开,那这个的话呢,其实是一个我个人认为更干净的一个摘取,那么这个摘取的话呢。
实际上它当然它带来的代价是什么呢,就是他把所有的复杂度扔到了presenter,this presenter变成什么了,就是他得既听得懂model的语言,又听得懂view的语言。
你看就是他在这中间人是最辛苦的,他得懂两种完全不同的语言,这时候view也轻松了,model也轻松了,其实MVP模型写不好的话,其实presenter经常会写的非常的臃肿和肥大,但是呢。
其实呢在目前的整个工具的实践中的话呢,我个人比较推荐呢是第三种模型是MVVM,就是说哎这个名字听上去,很多同学应该非常熟了,因为这个我如果没记错的话,最早是微软提出来的,那么你可以认为就是说。
其实它跟MVCVP都有很深的关系,但是我个人认为它有一个很深的一个,有一个很重大的一个决定,是他非常了不起的一个决定,就是说他第一个像MVP模型一样的,就是他把view和model也是彻底分开了。
他只是把中间那一层它不再叫这个,就是presenter了,它叫什么呢,叫view model,它它这个关系呢不再是用代码哎,写死了,就是说我在V那个presenter里面去。
基于query view的这个API,E l corn model api,他用了一种机制叫做founding的机制,这个绑定机制就非常了不起,就是他观察到一个非常重要的一个事实,就是什么呢。
实际上在我们去做各种各样的工具的时候,就跟刚才我讲工具的价值一个道理,就是说你是要把几种完全不同设定的人,放在一起工作,比如说我去设置一个工具的整个UI的时候,实际上它是什么呢。
它是ux designer,交互设计师,他不会写代码的,他也不想写代码,他在乎的东西是什么呢,就是哎我这个按钮放在这是不是合适,我这样按钮按下去,他就下拉框还是个滑动轨,这样更合理一点,更好看。
我应该用什么颜色一点什么呀,所以他希望一个完全独立的一个ecosystem,一个环境里面去定制自己的用户交互,因为他只对用户交互和体验负责,所以的话呢其实那个view的话,他不要再去写什么逻辑。
也不需要知道别人的东西,他希望用最简单的,比如说用XML或者是那个ZA这个语言,我直接表现这种就是这种cascade的这种类,要的东西对吧,而且这里面的话呢我们尽量实现,要实现他们想要的所见即所得。
然后view model的话呢是程序员写的,我要把这个数据绑定起来,但其实只是定义了一种简单的绑定关系,那么真正复杂的model,那我自己去写我自己的数据,那么实际上这里面有一个非常大的好处。
就是说那个model和view,真的是彻底彻底的分离开来了,那么这样的一个系统的话呢,它非常的干净,但是这就要求你如果想实现MVV的模型的话呢,你必须要在已经现成的框架里面,比如像WPF。
他就给你提供了很好的框架,就是很多设计师你用那个就是啊ZARA这个脚本,或者用他的编辑器,就可以自动生成各种各样的UEI,然后呢你写一些非常简单的c#的代码,你就可以把这UEI全部就可以做出来。
所以说以前我们在用C语言,C加加语言写UEI的时候很痛苦,而且很难debug,经常是UEI就崩掉了,但是今天大家用c#的话,你会发现哇非常的灵活,非常的方便,而且别人写好的空间。
我也很容易的思路都用起来,这其实就是MVI模型这个很大的一个好处,灵活性,当然了,这个模型的话呢,其实他也有自己的一个困难,就是第一个,我认为它是需要在他自己的那个生态里面。
就比如说你要去做这个这个MV模型,在windows的情况下,你最好的选择,目前我看到的还是WPF对吧,但是你这样做完之后,就以前像那个mono啊,像这些东西做的不够好,比如现在那个DNA的那个框架。
在LINUX上支持的不是特别好的时候,那我想把它清迁移到LINUX呢,我想把它迁移到Mac上怎么办,那就很很很痛苦,所以说这个时候你实际上是,你对这个环境的要求就比较高。
第二个的话呢就是对于一些比较简单的,极其简单的UI需求的话呢,这个框架呢它本身的就是这个可维护性,或者叫DEBUGABILITY,本身也有一点点挑战,因为其实大家特别容易在哪个地方,在邦尼那个地方出错。
因为这两个无论是view你去定义它对吧,view model你去定义它,它两个呢你只是做了一些declaration,当然这个逻辑到底是不是真的是对的,这个逻辑之间的关联是不是真的是有效的。
你不把整个系统跑起来的话,你是没有办法验证的,如果这里面的数据出问题的话,就debug起来是比较痛苦的,但是呢这毫不妨碍,就是MVVM的话是一个在商业上已经被证明了,非常成功的一个模型。
当然这个模型其实现在也还在不断的演进,因为啊确实我们现代软件系统越来越复杂,所以说其实我们再去思考,就现代软件系统的时候,就是比如说做到to train这一块的话,我们一般跟大家去讲。
就是说尽量不要自己去造轮子,因为我们的关注点首先是游戏引擎,游戏里的东西,所以我们在做two chain的时候,在我们写我们to change的GI这个体系的时候,首先to change的GI体系。
刚才再强调一下,非常的重要,而且呢它需要需要有非常强的工程可扩展性,你才能够支撑你全部的需求,那我们的建议就是说大家不要自己造轮子,选择最成熟的结构和方案,比如说我有有些小引擎,你如果真的急了。
你想用qt去写,其实我认为也是可以的,但这一定比你自己去写一个要靠谱的多,对吧好,所以的话呢就是说讲到这儿,大家首先明白,就是GI大概以什么框架去构建呢,那么如果你在windows下的话。
如果你不考虑跨平台,那WPF肯定是个比较好的一个选项,那那你就follow mv m的这个模型,这样的话你能够快速的构建各种各样,你想要的工具,你有了这样的一个东西的话,接下来你要面对的问题是什么呢。
就是数据对吧,我们有在这个工具链里面,传递的就是大量的数据,那数据第一个需求是什么呢,就是哎load and save,就是我加载或者是存储,因为数据我不太老师在内存中放的对吧,那么这个事情呢。
其实等等我们真正设计这个工具链的时候,它并不是一个很trivial的问题,就并不是一个非常简单的问题,那么首先跟大家讲一个学术名词啊,这个名词其实非常高大上。
这个叫serialization and deserialization,序列化与反序列化,听上去好像非常的高大上,其实就是啊这个save and load就反过来。
serialization就是存出去,把它变成一个可以传递的一个二进制的块儿,this alization就是把一个二进制块,把它变成一个我能够内存中可以解,可以处理的这样的一个数据。
那么但是呢就是这里面大家特别容易犯的一个,一个误解什么的,就是SATION和DISORATION并不只是单纯的指的是文件,实际上这两个概念是很广泛的,比如说SATISATION。
它不只是存成我的磁盘上的文件,我还可以存成我的数据库里面的一个block data,就是说因为我很多数据,比如说我一个对象的描述对吧,我一个object的GO,大家记得我们游戏讲一切都是GO。
其实我的CEO的状态,可以把它serialize成一个二进制的数据块,我可以把它存到数据库中,我用object id去引用它,这样的话我随时随地可以去访问它,还有呢就是我还可以把它存到网络上去。
就是说啊这不叫疼,叫传输了,就是说我的客户端A向客户端二,或者向服务器发送一个消息的时候,实际上我要把我的一个机油的那个所有的描述,也要把它serialization乘一个二进制的数据流。
然后通过网络协议传到另外一个客户端,另外客户端拿到这个二进制的数据流怎么办呢,他要对他进行DISCIALIZATION,然后呢把那个机油再构建出来,其实我们的整个游戏特别是网络。
我们后面还有一张会跟同学们讲,那个就是networking,就是说怎么去做可以互联的游戏的话,会跟大家详细的讲,这里面有很多有意思的东西,但是selection disciation的话。
也是networking的一个很重要的一个foundation,所以这两个概念的话呢是啊,可以讲是现代游戏,现代系统,特别是现代游戏引擎吧,我们认为是个非常foundation的概念,因为在工具链。
在游戏引擎里面,就是我们每天面对的就是数据的,你把它打打包好,解包打包好解包,就是我们每天日常干的活儿好,那其实呢这个打包的方法,最简单的方法是什么呢,是text文件,哎大家不要笑啊。
text文件虽然非常简单啊,但是其实实际上在最早期的时候啊,比如说我们讲那个网络之间的通讯,大家想象一下是怎么做的,诶我们可以用text铭文做的,大家还听我相信同学们看见很多,这就是互联网的八卦。
就是某某某这个很牛逼的,这个什么这个这个某某国的重点什么系统,结果呢,它的这个重要的信息都是用text铭文存的对吧,所以你看这件事情,是不是让大家都觉得笑掉大牙,但实际上这是个很常见的一个事情。
就是说其实TT它有很多好处,第一个呢就是说它本身是非常容易,就是理解被人去赌的,第二个的话呢,你用任何一个工具就能打开它,这样的话你去debug,你去追踪,你去分析特别的容易。
那么实际上的话呢TT在最早比如说啊,同学们如果学那个就是学图形学的话,最早应该接触过一种格式叫点OBG格式,这个是个非常古老的格式,那这个格式里面它就是真的很淳朴,说哎V打头机表示我是个vertex啊。
接下来三个三个text是告诉我的顶点坐标,然后呢我好像记得是T打头还是什么打头,就表示三角形还是M打头,我有点忘了,就是呃应该是T打头还是什么打头,它表示一个三角形,然后就表示三角形对吧。
index123456789十,那么其实这些呢最古老的text format,真的就是每个程序员自己想到一出,是一出就定了的,但是呢等到后来大家就会发现啊,我们这样胡乱定是有问题的,后来就出现了一些。
更多的一些就是我们叫结构化描述语言,比如说XML对吧,XML包括像HTML这些语言,其实XML是个非常了不起的一个发明,就是说他意识到了就这些文本,它实际上是个容器,然后呢它通过一个树状的一个标注系统。
能够把任何一种结构化的信息都放进去,那么这个东西的话呢其实是很多系统的一个foundation,那当然后来大家就发现就是哎呀,XML这个废话特别多对吧,每个描述都一大堆,那个标号啊,间号一大堆。
后来有人就提出了更轻量的一些方法,比如说像JASONJASON就是它的功能跟XML非常接近,但是呢JASON他的这个语法,就是它的这个文件大小就会小很多。
另外一个呢它的passer就是它的处理也会快很多,那么像包括像那个压秒这些语言,所以其实啊就是text file,如果大家在做引擎,做工具链的时候,如果你做的体量不是特别复杂的时候。
我倒是非常推荐大家先用text file去上手,因为你一开始写的时候会有很多的bug,这也是同学们问我的问题,就是为什么这个PICO我们选择了JASON这个语言,其实就是为了方便大家阅读和理解。
比如说我如果用二进制的格式的话,同学们根本不知道那个数据里藏了什么东西,而且它的数据的读取也非常的抽象,然后最后进了引擎之后,数据正确了不得了,谢天谢地,数据错误了呢,你就觉得哎呀完蛋了,我我都不知道。
无从下手,因为大家如果debug过,对那个二进制的数据的解析的时候,你就知道那个事情真的是非常的痛苦,所以的话呢我们当时就选择了,就是说用JASON作为我们这个数据的语言,那当然其实类似的选择。
比如像unity,它也提供了一种就是A纯文本的方式,去存储你的S的,包括像那个就是那个corue engine的话,它也有一个就是类似于用那个CHARML或者,JASON的这样存储模型。
其实我如果大家在写这个引擎的时候呢,我会推荐大家就是首先支持text f,这样的话,就相当于给你的引擎加入了一个debug mode,就是哎你任何一个数据错了,你先把数据转成那个textbook md。
然后debug1遍,如果没有问题,你才转成八点后买的,这个其实是一个非常好的一个option,那么第二种呢也是大家很自然会想到的对吧,我这么这个这么蠢的,存了那么多的。
这个这个这个这个这个文字肯定是最慢的嘛,那我直接用BUE去存,那这个其实呢就是它的存储容量,肯定是很有优势的,比如像unity他一上来啊,Unreal,它的所有的模型里面基本上都是binary的。
比如CRYIN也有binary mode对吧,所以的话呢,这个呢其实我认为是很自然的一个东西,就是如果你有了一个基于text的一个结构的表达,你把它转成二进制的话,实际上也是非常自然的一个表达。
那么这两个的好处呢,我相信不用我讲,同学们也能猜到,就是二进制会小很多,举这样一个模型的例子的话,同样是用FBX就FX的话呢是行业,你现在特别特别通用的一种,这个数据模型的表达格式,对不对,他就很聪明。
它提供了两种format,一种for binary,一种for text对吧,这就是for deparability,那么你会发现就是text的这个文件,基本上接近于这个binary的十倍以上对。
而且呢大家都知道就是我读二进制的时候啊,我几乎不要进行语语法处理,但是我要读文本的时候,实际上我要做语法passing什么意思呢,就是说我得把你的逗号句号尖角号,然后要做包括你的注释。
我都要做语法的语义的过滤对吧,我要生成一个ST,然后呢基因的语义我再把你keyword build dictionary,我要做很多很多的处理,其实那个text的加载速度。
应该确实比巴黎人慢的就将近十倍不止,所以呢这个就是一个debug很好的mod,但是呢确实比如说像我们的真正的,你要做一个上线的游戏的时候,那你的资产包括你的整个asset的格式。
一定是要换成BINNER的,还有一个点是什么,你不想被别人破解,所以的话呢其实我们如果再讲一下的话,那asset其实有的时候我们需要加密的加密,那就是另外一套很神奇的算法了,今天就不展开了。
那么其实呢在这个资产里面,我们会发现很有意思的一件事情,就是说其实我们打开一个游戏的关卡,你会发现你们很多资产是重复的,那么那怎么办,那我们最自然的想法是什么呢,诶我们其实把有些资产。
比如说一栋房子变成另外一个资产对吧,比如说我要表达一个场景的时候,我这个场景里面有1000栋房子,但是一千一千栋房子可以用20种房子去表达,所以呢这个时候,其实在我们定义我们的数据结构的时候。
我们要引出一种很重要的东西,叫做asset reference,就资产的引用,这个其实当我们在定义一种,就无论你是二进制的还是text format的,这样的一个S系统的时候。
你一定要支持就是cross five的这种引用,因为你有了这样的引用之后,你才能把这些重复的东西全部给提取出来,这也是当我们去做一个引擎工具链的时候,实际上你面对的不是一块巨大的数据,你面对的是什么呢。
是成千上万的离散的文件,而且这些文件之间呢它们彼此之间是关联的,比如说你做个特效对啊,你觉得特效就是我自己的,对不对,诶不好意思,你做个特效,你首先可能引用到一个诶特效的蓝图对吧,如果是real的话。
你可能会用到什么呢,你自己的本身的这个texture,我需要用到这个动动画的texture,我可能要用到那个的animation,所以它的过程其实蛮复杂的,这就是游戏引擎。
就是游戏引擎reference,为什么重要,就是你可以认为游戏里面是上上万上10万,上百万的这些资产文件,他们是像一个出网一样的,彼此关联在一起,所以的话呢这也是reference的引用驱虫。
实际上是我们的资产系统,最核心的一个底层逻辑,也是工具链的最核心的底层逻辑,好,那么你有了这样一个reference的话,有一个最简单的做法就是诶,我在一个尖顶的房子,在我的场景里出现了十次。
我只需要放它十次的引用,那么这个十次都是这个房子什么的,我们叫做instance,就是它的一个实例,而你那个房子本身的定义本身叫什么呢,它是它的definition对吧。
这个我在之前好像在instant deapi里,反复跟大家讲这个概念,但是呢当我们在做工具链,特别是因为工具链,会直接影响到你底层的数据结构嘛,那其实你会遇到一个真实的情况,就是在做实战程序游戏的时候。
其实很多时候artist诶,这个时候就反映出artist课,程序员思维方式不同了,比如说这个artist把一个房子,比如一块地板,我考了十遍之后,那作为程序员的想法就是,哎你我都已经让你能考十遍了对吧。
而且我还只用了一份的存储空间,我已经很厉害了,对不对,但是说不好意思,我觉得考了十遍,虽然它分散在各个地方,你提供了让它旋转放缩各种变化,但是我觉得还是不过瘾,我想把其中五个的贴图给换了。
换成其他的贴图,这个程序员就很抓透了,他就说啊,那你只要换了他的这个比如说它的贴图,那就你应该做一种新的定义呀,但是呢诶不好意思,就是作为我们的艺术家,他不会这样去做,因为他在那个编辑环境里面。
他希望所见即所得,就是我看见这个贴图不爽,我马上就要把这个图换掉,那这个时候呢,其实我们在工具链中对每一个对象,对对它进行实例化的时候,我们要给他做各种各样的,就提供一种叫做warrens的能力。
就是做它的变种的能力,那这个时候呢实际上就会要求我们啊稍等,其实呢就会要求我们说诶,我能够直接在工具链中,把一个物体做出它的变化,那最简单粗暴的做法是什么,诶,我把这个物体在我的这个关卡里面。
再拷贝一份对吧,然后你想改啥就改,大哥你牛你你你考完之后,随便你怎么改,但这个做法的话,显然从数据处理上呢,它是一个低效的做法,为什么呢,因为你可能一个物体的描述,我有成千上万的数据对吧。
可能是比如说几百个数据,你只动了一个,比如说它的颜色,它的一张贴图的纹理的这个路径,那其实你改的东西很少,还有一点,就是说,比如说我向总体上对的东西进行一个调整,比如说我把他的一个网格做了调整。
我希望其他的他的分身都要相应的发生变化,但是一旦你拷贝之后呢,他们之间的关联就彻底断掉了,所以呢这个时候我们引入了一个很重要的概念,叫什么呢,叫做DINHERITANCE,这个的话呢。
实际上也是工具链一个非常重要的,一个底层技术,就是说我们当用户在这么多工具中,来回走的时候,它会产生很多数据嘛,其实数据是可以继承的,对数据是可以继承,大家在学这个就是啊高级语言的时候。
大家在学C加加对吧,我们定义了一个类,我们的类的派生,它就是继承于它的父类,对不对,好像就是我的方法,我的很容易可以继承,那么数据可以继承什么意思,就是诶我一个111个structure的一个实例。
比如说我把它的长宽高的设了个数值,我另外一个数据呢是既乘以你刚才那个,比如说长高一个一个正方体的box,但是呢我长宽都不改,我只改你的高,诶,我这个数据就是给你继承的,而数据继承的话呢。
也是我们在做这个引擎工具链的时候,一个非常重要的一个方法,这个方法其实你说它难吧也不难,也就是说,实际上就在于我们的定义这个数据资产的时候,定义asset格式的时候,大家刚才讲的。
比如像我们这个用的是类似于CHARA的格式,那实际上你加入一些相应的属性段,描述说,哎我这个数据它其实是继承于哪一个那个数据,然后呢但是我哪个field我要改掉了,我就把它改掉,那这样的话。
当我们工具链或者我们的引擎,读到这一块数据的时候,我就知道先把原始数据朝拷过来,然后呢根据你的修改的部分把它修改掉,这样我就造出了一个新的数据,所以其实非常的有意思啊。
这个实际上在你去大家去理解工具链的时候,实际上工具链玩的全是数据,就是它实际上是各种各样的数据,在各个工具之间流来流去,那么怎么去深刻地理解数据,怎么样的保证数据的这个灵活多样性,但又不会混乱。
实际上是我们在做to chain的时候,一个非常核心的一个一个发力点,这个概念还蛮好玩的,那我们把这些数据我们知道怎么去存在的对吧,我们把这个数据存到硬盘上,就是那个其实刚才我讲了那么多。
我只是把serialization part给讲好了,怎么样,我的标题叫low and save,但其实讲了半天,我只讲了如何定义数据,如何save数据,那真正难的问题就来了。
这个磁盘上的数据我怎么去漏的,他呢就是我怎么去DCALIZATION呢,唉这事儿其实并不简单,这个呢如果你不去做引擎的同学,大家不用太关心对吧,反正format的人家一定好,我直接用就好了。
但是如果我们games104的小伙伴,大家想做自己的引擎,想定义自己的工具链的话,那这一盘的话同学们要去听一听了,诶实际上这个事情其实是我们对一个asset,加载进来之后,我们并不是像大家想象的。
我沿着文件一通读就完事儿了,实际上它是一个passing的过程,什么叫passing课程,大家想象一下我们一个场景文文件,它里面有很多的数据块,每个数据块有很多field。
有些field的话呢它有不同的value,不同的type对吧,那你怎么去处理它,实际上呢你是要对整个文件进行,不不是说依次去读它,你要对整个文件进行扫描,然后呢扫描的时候的话呢。
你要去去检查每一个field是不是存在,比如说你检测到一个一个key value,它的名字叫什么好,你接下来说诶我找到你的值了好,我把你的名字值type,我就把你放到一块,变成一个pal。
但是有的时候我我说诶,你你指向了你们另外一块数据,但那块数据呢其实我还没有没有读到,大家想象一下,我我们看一个数据的时候是一个完整的,就是整合在一起看,但是其电脑大家讲记得我以前讲过图灵机,对不对。
图灵机是什么,是一个纸袋,他这样只能一次一次去打,但是呢它有一个小小的memory,这个纸袋一直打写memory memory是另外一条纸带了,那我看到一个是一个数据库,比如说你现在要用到这个你这个呃。
比如说吧你这个动画啊,不说错了,比如说你这个角色,他的第三个动作是要用到动画305好,305动画还没读,那我再继续往后读读读读,读到后面的时候诶,我动画305的那个动画我才能读过来。
读过来之后我才知道这个数据是什么,所以说其实这里面的话呢,我并不是一上来把所有的数据全部加载进来,而我一上来是先要把这个数据拆分成,一个个的语义,然后呢把这些所有的关键的key,这些value。
这些type全放在一起,它会生成一个什么样的东西呢,哎大家看我们最后生成一个所有的field的这个key,然后呢它是什么类型,还有它的这个值形成一个树状结构,大家如果去分析一下所有所有的像XML。
像JASON这样的语言的话,你会发现它无论多复杂的这个文件,这个asset它都是个树状结构,其实在我们在做游戏引擎的这个资产,asset的管理的时候,我们也是用了这种结构,就用树状结构。
其实这个很像什么呢,很像那个就是那个大学那个编译器的时候,那个a s d tree对吧,就是你写了一段很长的这个,文本的这个源代码诶,其实交给编译器的时候,他管你写的这个这个这个妙笔生花。
给你生成了一群非常抽象的s d tr,AST长什么样呢,大家稍安勿躁,我们在下一节课给大家讲反射的时候,会让大家见识一下,那个这个这个这个很就是让你觉得大跌眼镜的,STT长什么样的这个结构。
但今天我们展开,但是呢它的逻辑上其实也是像这样的一个结构,其实这就是我们对世界的表达,就像我们去理解这个宇宙,理解这个世界,其实如果我把对象一个个都罗列的时候,我们是没有办法理解这个宇宙的对吧。
那我们怎么去理解这个国家很简单,我记得我在上节课的,在前几好几节课讲过这个概念,就是诶我们构建一个树状结构,我们首先第一个题,第一个根节点叫什么叫国家好,我们把国家怎么分呢,诶我把国家分成审审。
分成市是在分成这个就是每一个区诶,这另外一个呢我在这个市里面,每个区里面我在分人,但每个人怎么样,然后这个国家另外的一趴,比如另外一个业绩点是什么,我是按企业啊,行业按部门按部队这样一个个分诶。
我用一个树状结构,就可以把一个极其庞大复杂的系统给表达出来,而且这里面的话呢,他们彼此之间还可以相互引用对吧,比如说有一个个体的人,他属于哪个神啊,哪个市哪个省,哪个市的一个人。
但是呢他又属于哪一个政府部门对吧,他又是从事什么职业,然后他和谁谁谁又有什么配偶关系,所以其实啊这样的一个树状结构,它就彼此之间能够相互引用,实际上就是我们的一个asset的一个,真正底层的结构。
那么这个时候如果我们去加载一个,就是text format的话呢,实际上前面需要一个非常复杂的一个passing课程,比如说大家去理解一下,就看我们的小引擎。
我们不是用JASONJASON作为我们的数据载体吗,你可以你如果读那段代码,你会发现我们首先调用的是那个第三方的库,它把JSON的文件就变成了这样,一个一个一个tree的structure。
然后呢他们也它也可以叫做dictionary一个字典,然后呢我要任何数据我就问他,然后我就可以通过他的第二次处理,我可以拿到我想要的我的资产,但如果你是二进制的话呢,其实一般在二进制的头部。
我们会把这个树状描述存下来,就比如说我有多少个field,它的名字叫什么,他的type,它的它的位移在哪里,就是数据在那里,第二个就是他到底什么态度,因为我知道tab就知道我要读多久。
我先把整个这个二进制文件的描述放在前头,那接下来的数据我就可以快速的去处理了,所以的话呢,这个其实当我们去做DESERIALIZATION的时候,这是一个非常重要的一个方法,OK好。
那么但但是呢如果我们用二进制做distortion,特别是我们在做真正的工具链的时候啊,大家要特别特别注意一个事情,就是ending这个词是不是大家觉得很很神奇,这个ending中文叫什么呢,说句实话。
我也不知道中文叫什么,反正而且这个东西在我个人看来是我,我我是满满满觉得这个头疼的一个事儿,就是说呃大家知不知道,就是在我们计算机这个系统的早期的话,有两派之争,一个叫big ending。
叫leader,你这个很像甜豆浆和咸豆浆之争,真的是特别特别无聊,但是给我们惹了很大的麻烦,就是说同样一个比如说一个整数,你是把第一位存在前面,比如说把个十百千万第一位存在。
但是二进制里面是倒不是个十百千万对吧,就是低位我存在前面,还是把高位存在前面诶,这两派就打起来了,那么比如像INTEL的X86架构,它就是一个little ending对吧。
但是呢比如说像IBM的power pc架构诶,它就来了个big ending,你说这有意思没意思对吧,但是呢没办法,这就是事实,比如说我们要兼容LINUX不同的这个硬件平台,我们要兼容这个Mac。
还兼容那个就是说各种android的,还有还有就是那个游戏主机,还有那个就是PC,哎我们就得要解决这个很奇怪的问题,但这个问题呢你说它复杂吗,也不复杂,我跟大家讲一下。
就是说在当我们做游戏引擎工具链的时候,我们实际上呢是这么解决这个问题的,就是说在工具链里面,我们一般会约定好我整工具链,比如说我们一般是去PC作为它的这个编辑器嘛。
那我全部统一锁死为lut ending对吧,然后呢无论各种编辑器里面我就用,但是呢当我在做DISCIALIZATION的时候,也就是说当我加载这些数据的时候,比如说我突然发现诶。
我好像是在一个PLAYSTATION上面去解压缩我的数据,对不对,我用一个swapping,就是把所有的little ending的数据,把它变成一个beginning的数据,但这个过程其实可以离线做。
就是说当我去给PS5打包的时候,我把这事给做好,这也是可以的,但是呢就是当我们去写引擎to chain的时候,这个确实要注意,包括我们现在都已经遇到这个问题了,所以的话呢就是同学们如果做引擎的时候,诶。
知道跨平台里面,这个ending就是一个很头疼的一个小问题,好那么讲到这儿,大家就会觉得哎呀,我基本上虽然我好像听得半懂不懂,我好像已经知道这个工具链基于此,基于S系统怎么去构建了对吧。
我既知道GUI怎么做了,我也知道这些数据怎么去组织了,接下来我接下来的问问老师,怎么去构建这些编辑,我基本上就能做,对不对,哎我现在跟大家讲一个更有意思,也是,其实我一直认为是做工具链最难的一个问题。
就是说你怎么能做到,就是说资产的这个版本的兼容性,哎这个大家就很难理解了,为什么还有一个版本兼容呢,比如说同学们,你们在用word的时候对吧,有多少人意识到其实word是个非常难写的软件。
比如说我是2010版的word对吧,然后呢我编辑了一个文档,诶,这个时候我假设是一个2019版,2020版的这个word,现在应该是2023了吧,版本的这个这个word出来,我还要能打开。
2015版本的那个那个word文件诶,这个向下兼容大家想想怎么写,而且大家想要哦,这很简单嘛,我就check一下版本号,衣服你的版本对应20142010,我怎么怎么样对吧,那当然你这个做法也是可以的。
但是我们在想更偏激的做法,就是假设你这个资产是啊二,这个这个文件是2023,编辑完了,那你二零这个一零的版本能不能打开,那现在反正沃特的处理是很糟糕的,实话实说,他基本上是没办法打开的,他说哎呀。
你这个好像是版本号更高,我打开不了对吧,但实际上的话呢,其实在我们在做游戏引擎工具的时候,我们要支持版本的兼容性,就是这原因是什么呢,首先大家想象一下,一个游戏真实的研发过程有多久,大概是3年左右。
那么在一年在3年前,大家做了很多资产,比如说我编辑了一个很漂亮的动画对吧,我做了一个很酷的场景,那我引擎会不停的升级,我的工具也在不停的升级,我会加很多很多的数据,我可以删掉一些数据诶。
那难道我们的美术3年前做的那个场景,就不能打开吗,那你想想看美术是不是要跟你拼命,对不对,人家工作了几个月的成果,你以为你老人家版本升级,大家就就就完蛋了对吧,那么还有一点是什么呢。
就是说诶就是我这是就是过去的数据向,就是叫我们叫这个叫做backward compatibility,就是向后兼容对吧,那我们在讲for compatibility什么意思呢。
就是说诶在我们一个团队里面啊,其实大家很多时候,版本工具基本上每隔一两天就升级,但有的时候同学们呢它的工具还是老的工具,但是呢他要打开未来的人类,就未来的同学们的版本创造的这个这个素材。
这个情况其实是有的,那我们也希望这个工具不要崩掉,这个引擎还继续能跑,其实这个需求呢大家会觉得诶,好像如果我做好这个团队的管理对吧,我用老的平台跑未来的数据,这个事情应该不需要,但事实上呢在很多环境中。
特别是在我们叫做分布式部署的环境里面啊,这个需求是很刚需的,这个特别像同学们特别想知道的什么,元宇宙对吧,我个人一直认为元宇宙这个概念现在很不成熟,因为就是呃他就有大量的这个问题。
就是说比如说我几年前开发的一个应用,我未来来的数据,比如说我来自于啊未来这个别人生产的那个application,产生了一个虚拟人,他怎么进入到我3年前开发的一个,就比如说一个虚拟游戏场的这个环境,诶。
他在我这也能玩,我不能因为这个他的那个application,我再去升级我的游戏,常因为很可能做了老的application,那个团队他已经他已经解散掉了对吧。
其实在METAVERSE上会有很多这样的application,它实际上是跑不起来的,但这里面讲的就比较深了,但是我想跟同学讲了一个概念,就是说,其实当我们定义一个真正的一个,商业级的游戏引擎的时候。
事实上这个就是这个资产的版本的compatibility,实际上是一个非常专业,非常重要的一个东西需要思考的,那这个问题怎么解呢,那我们先讲一下你可能遇到的情况,其实他讲起来也很简单。
就是你会遇到两种情况,一种就是你的一个field其实被人给删掉了对吧,比如在这里面我的这个transform被人干掉了,对不对,还有一种是什么呢,唉未来我系统越做越复杂,我就越加越多。
但是呢你的数据文件还放在那,你得把它打开来,对不对,那怎么办呢,其实这里面的话呢,有一个比较这个简单粗暴的做法,就比如说我们看一下荣耀怎么干呢,他很简单,他说呢我每一个资产我程序员手写版本号对吧。
那我就检查了,说哎我现在已经已经升级到7号版本了,但是你的你的你的资产还是6号版本,我就知道有一个数据,你就是那个没有的,那好怎么办,我给你塞一个就是default value对吧,塞入一个一个缺省值。
如果你你你的数据多了,那我就不读,你把你那个数据我虽然还读,但我不处理它,把它跳过去,这个方法实话实说啊,我个人啊不是特别敢苟同,就是我个人觉得方法处理的不好,因为这个随着一个系统有有3年。
4年以上的发育的话,你会发现你要兼容的这个版本的,这个这个这个version number就越来越多越来越多,这个是很糟糕的一个方法,这里面的话给大家推荐一个做法吧。
这个做法的话呢实际上是这个啊google提出来了,就google他们也遇到了这样的问题,其实我特别想,因为google它是全球可能最大的一个分布式系统,的这样的一个应用场景,那么他就肯定会遇到这种问题。
因为在他的平台上要跑成百上千种,不同生态的这个软件,这些软件的话呢都是有不同的开发商开发,对不对,然后呢版本也各自有不同的频率在在在更替,然后之前的数据还会来回通讯对吧,那这个张三的软件更新了。
李四的软件没有更新,网络的软件又更又又又又又又回退了好了,那这里的数据的通讯就全部完成,全部全部全部完蛋了,那么google就提出了一个叫po buffer这样的一个format。
其实他的想法我个人认为又简单又好使,其实非常简单粗暴,就是说它要求你在定义每一个数据field,就是一个属性的时候,你给它生成一个unique id,这个id呢你保证它是一直单调递增就好了。
这样的话就是当你的数据一直在更新的时候,我就比较说你这个id有没有发生变化,是不是很简单很好使对吧,但是呢实话实说啊,我我很想吐槽的一件事,就是他的这个就是语法定义,让我觉得真的不敢恭维你。
大家看一下就上面写了,就是说哎这个string GUI d等于一,string file name等于二,哎我的天,我当时看到这个我的,因为作为一个这个这个这个有点强迫症的C加,加的这个开发者的话。
我会觉得大哥你这不是让我再付这个缺省值吗,我我我觉得如果像我们这种插面空的话,或者JASON控的话,我会说你给我加个冒号,什么什么UID什么,这个这个等于一我都好一点,我都能忍。
你让我这个这个feel的直接等于一,我就会觉得你是在负确认值,但是呢可能大家习惯了也就好了,他肯定我相信姑姑大大,他她这么做一定是有他的道理的,我不懂,只能说明我的水平不够。
所以呢大家可能可以无视我这段点评啊,但是大家可以去学习他的这个思维方式,就是说这个方式其实非常的好,因为这个就是当你面对大量的,就是我们的一个游戏引擎啊,它实际上跟google面临的环境是有点像。
因为它有大量的模块,都有不同的开发者去开发和维护他的版本变化,很快它会产生,像比如说一个像一个商业级的游戏引擎,它的数据format格式,格式可以达到几十甚至到上百种,而且呢。
这每一种格式都是由不同的团队,去开发和维护的,然后但是我们的artist他在打开一个工具的时候,比如说打开一个地图编辑器的时候,他可能会同时面对几十种完全异构的数据,那我们怎么能保证这个整个工具体系的。
鲁棒性的话,在这一点上就是叫这个版本兼容性的话,是一个非常重要的一个核心指标,其实在网络环境下,在分布式部署情况下,这个问题会变得更加的复杂,所以我一跟同学们讲,我就说游戏引擎是一个大型软件工程。
其实这个时候大家应该有一点点感觉了对吧,你想你要伺候那个成百上千的这些,我们的艺术家,老爷我们的设计师老爷的话,实际上是要求你这个系统做的还是相当鲁邦的,那接下来的话呢又又到了,我刚才已经点到这个词了。
就是如何让你的工具变得更加鲁棒一点呢,你要知道就是当我在做一个游戏引擎的时候,昨天跟大家讲就是游戏引擎,做游戏引擎是在整个游戏团队里面,大家会觉得我们的地位是不是很高诶,实际上你们错了。
做游戏引擎的团队是地位最低的,为什么呢,因为我们在服务所有的人,包括程序员,因为程序员要基于游戏引擎开发游戏嘛,就是给你们举个例子吧,比如说在我们这个行业里面,如果一款游戏失败了。
这个大家首先想到背锅的是谁,不是什么策划,不是美术,不是程序,一定是游戏引擎,对不起,我的游戏引擎选错了,所以我这个游戏就失败了,诶这个所以游戏引擎的话,大家如果想做游戏引擎的话,一定要有这个觉悟。
就是做好背锅侠的准备对吧,那作为我们这种背锅侠呢,我们就这个非常小心谨慎,我们就说诶那既然我要背那么多锅,那我就索性这个把我这个做的再鲁棒一点对吧,这样少挨点骂,所以呢其实特别是工具链来讲的话。
它的鲁棒性要求是非常高的,因为实际上游戏引擎一旦工具链出问题的话,对整个团队的影响是非常大,大家想象一下,如果你的游戏引擎工具崩了,那你几百人一上午什么事情干不了,等着你把这个bug修好。
你想想看你作为一个引擎开发者,你的内心压力有多大,反正我们是亲身经历过的那种感觉,真的是如坐针毡,你会觉得欠了大家很多很多钱的感觉,所以的话呢让工具的棒易用,其实是工具链的一个非常核心的点。
那作为一个游戏引擎开发商,怎么让工具变得鲁棒呢,那首先的话诶也是大家最需要的东西,就是undo redo,对这个东西听上去,其实当我们一开始在做一个工具链的时候,比如像我最早在做编辑器的时候。
我会想到很多粉丝的feature,比如说我要做个很酷的这个植被,刷一刷子刷过去,山川河流都给你变出来对吧,然后呢我要做最酷的悬崖峭壁,这个这个各种各样的东西,我要做这个刮风下雨。
但实际上你会发现artist跟你讲,诶大哥我刚才做了一个误操作怎么办,你把这个数据删掉,重新再来一遍对吧,你你就疯掉了,你会发现就是所有的编辑器,editor到最后最核心的功能其实就是这个安度锐度。
而且呢对于游戏引擎来讲的话,安度锐度其实非常的复杂,为什么,他的就是他的很多数据编辑是correlate的,举个例子啊,比如说我现在改了一个房子的颜色,诶房子没问题对吧,我我绕着房子旁边种了一些树。
也没有问题,这个时候我突然决定把地面往上拉,个这个这个34米形成了小土坡,然后这时候这个房子和树啊,它都会相应地发生变化,然后呢我看这个房子不错,我在旁边在自动释放是吧,生成一些这个DECO。
就生成房子周边的那个一圈的那种诶,这个往外延拓的这种这种沙地空白地的感觉,唉这个时候当你要undo的叫你undo的时候,你会发现你有些难度会影响到其他人,比如说你首先把那房子给干了。
那个旁边那个地那一圈低调可能就有问题,当你把刚才地形的山山山地调整的去改了之后,你刚才种的那些树,可能它的角度很多人都会发生变化,所以说其实在游戏引擎里面,这种undo和redo的话。
彼此之间是有很深的correlation,而且很多肽,那么另外一个的话呢,就是你做的再好的工具,你都会什么呢,你都会crash,然后你crash之后。
人家艺术家他这个编辑了一个小时的东西对吧,人家也不会想着去存盘,然后突然就crush掉了之后,那怎么办,那就是要你的命了,对不对,还我数据,我怎么还,我又不会画画,我又不会那个做关卡,这个时候。
作为这个游戏引擎的to chain的开发者的话,实际上这个东西就是我们一个非常需要花时间,去想明白的一个一个问题,怎么去解决,诶,幸好我们有伟大的一个design pattern来支持我们,这个问题呢。
其实在这个软件体系里面是一个will study problem,就是一个被研究的非常透的问题,大家今天用word对吧,用POWERPOINT写PPT,然后用word写文档,你们知道就是当你挂了之后。
你再打开的时候,他会告诉你有个recovery,对不对,然后呢redo难度都会非常方便,其实呢它就是一个非常标准的叫command,这个pattern,也就是说我们把用户所有的操作。
把它分解成无数的小的command,然后呢我这小的command它就会逐渐累加,然后呢它会非常原子化的头发,但注意啊,这里面讲一个细节,是不是每一个用户的操作对应一个common。
实际上有的时候用户的一步操作,我们会分解成好多好多common的,这是有一定道理的,就是我们尽量让come on的原子化,那么这个时候呢,我们会把这些command定时的存到我们的磁盘上。
这样万一我系统挂了的时候,我从磁盘上去找对吧,当用户突然响了,诶,我要去undo的时候,这其实就是啊我们叫做简单的说法,叫做这个revoke和invoke,就是暗度学术的做法,我们叫in revoke。
那好那我把刚才内部操作给回退出去,所以呢这个pattern的话呢,也是非常符合人的直觉,但是今天如果同学们要加自己的to chain的时候,我会非常建议在很早期的阶段,就把这一套结构架好。
因为你这套结果一开始的话,你在早期架的时候,你随着你的工具链的功能越来越复杂的话,你在不断的丰富和完善它,那你这个系统就会比较稳定,你千万不要就to change,你做的已经比较大了。
你再开始做这套系统,那我告诉你这个事情非常的痛苦对吧,因为我们自己是经历过这个痛苦的,我们知道这个事很麻烦对吧,那真的是一天上百个bug扑面而来的感受,我们大家想象一下,这个是压力很大的好。
那么其实呢common definition,比大家想象的要简单的多了,最简单的描述就是每个command,你要给他一个UEID,我待会解释为什么你要有UEID对吧,然后呢你要有一串data。
然后这当然得command,你要它是一个interface,就是你每一种的command要自己去定义的,那么接下来最核心的就是两个函数什么呢,一个叫invoke,Invoke。
就是诶我这个come on要去执行它对吧,还有一个函数叫什么呢,叫river这个函数我退出了,我不干了,我退回去一步,那么还有两个函数呢,大家可能被注意不到,教serialize。
Deserialize,但是大家仔细想想,这个其实也是有道理的,就是说哎我把这个command我存到磁盘上,怎么存对吧,我从磁盘加载怎么加载,当然有的时候呢。
其实我们一些比较多的这些come on的操作的话,我们甚至会存在自拍,就是在内存文件中,甚至会存在内存dB中都是有可能的,所有的serialization和DESSERATION其实很重要,还有一点。
这个待会我们在下节课会讲的,就是说诶如果我们要做协同编辑的时候,这个东西是不是也是有用的好,那我们接着往下讲,就是为什么我们要一个UE对吧,为什么每个come on我们要给个编号呢。
其实这个编号呢首先它是唯一的累加的,当你这种command在不断的累加唯一性的时候,大家意味着什么,这是不是就意味着一种诶隐含的序列,这个东西为什么这么重要呢,因为当我在进行回退就是revoke的时候。
当我进行recovery的时候,我是希望他的执行要严格地遵循原始的顺序,这就是大家知道就是在真正编辑操作的时候,大家会知道很多操作,如果你执行的顺序不一样的话,它的结果是不是会完全不一样对吧。
这个大家很好理解吧,所以的话呢其实UID就是一个保证这个顺序的,就是单调递增的一个核心的一个点,这一点的话在写common系统的时候,大家一定要注意,那么另外一个的话呢。
其实在这个common系统中的话呢,一般不是common系统自己写的,而是什么呢,是由那个数据自身提供了这个标准的思路,ALIZATION和第四人类线的方法,这样也就相当于比如说我一个GO对吧。
我要说aleue object,我加一个GO,那好那这个机构资深,它要提供诶,我把我当前在内存中,我这个角色,比如说我这个character全部的状态,能够series下来的这个方法。
那么come on,系统就说OK我现在决定创建一个角色好,这个角色所有的数据调查,那个角色数据就是character,那个GO的那个里面的就是game object。
你们的serialization的方法,他把这数据给存下来了,所以这个呢也是,当我们去实现这套common系统的时候,它也可以变相的逼着我们,把整个引擎的系统都写得非常的干净,这样能让我们的引擎。
所有的操作都能够原子化好,那么其实呢就是在command系统里面啊,其实目前人大家总结下来其实就是三类的,command是最标准的,第一类呢我们认为就at,就是其实你就创建一个诶一个对象对吧。
它可能是个极有可能是别的东西,第二类就是我们把一个对象给删了,第三个呢我们对对象的一个值进行改变,就是改变对象的一个field,比如说哎我改变一个一个对象的,它的速度,一个大小一个field。
其实你会发现,无论多么复杂的这样的一个API系统,用这三类的command基本上就能表达了,其实大家去研究,如果有有空去研究一下,那个就是那个文本编辑器。
其实文本编辑器它的所有的revoke invoke的话,基本上就是用这三类操作就能解决了,这是非常了不起的一件事啊,就是增加一个text,删除一个text和呃,更新一个text,基本上就能解决。
这其实也很有道理的一件事,所以呢其实这个实际上就是我们的工具链的,一个基础的开发的逻辑,你发现没,我讲了这么多,没有讲一句话,这个到底工具链怎么写,为什么呢,因为每个工具的写法都是不一样的。
但是呢大家这个foundation比如像S的系统,像这个command系统,像这些这个GUI的体系要答对,实际上大家是在做图称最重要的基础,这也是就是让大家不要去急着写,我经常看到有些同学会说。
诶我做了一个编辑器,做的特别帅,你看我这个地图可以拖动什么东西,做的很好,是的,你这个东西单独做一个是很容易,你做十几个功能没有问题,但是你真的开始面对一个editor,你面对上百工的。
然后你有十几个不同的editor的时候,你会发现如果前面的这些事情没做对的话,你会非常痛苦,好接下来呢就是为什么这件事情那么重要,就是因为我们要构建的不是一个单一的工具,我们构建的是什么呢。
是一个two chain,对工具链,我们有很多的工具在一起好不好,他们彼此之间是有血缘关系的,要彼此通讯,彼此联系,互相说的话,互相能听得懂,这就是一个很挑战的一件事儿。
那么其实呢这个to chain就像我前面讲的,它其实是面对完全不一样的user对吧,那每个月的需求不一样,那么如果我每一个to啊他单独去写的话,实际上这个工具链它是没有可扩展性,也没有可维护性的。
因为这些数据全部都是异构的,大学刚才我虽然我讲了很多ACS怎么去定义,对不对,但是这asset之间每一个工序长得都不一样,那我们彼此之间我的编辑器怎么写啊对吧,我的我我。
我一会儿要编这个这个这个一个一个点光源,我一会儿要编一个角色动作,我一会要编一个场景的这个低调的分布,那么这个其实每个数据我都知道怎么定义,但它彼此之间是异构的,所以呢这里面呢就引入了一个非常重要的一。
个思维方法,就是我从各种各样的这个都要心中找出共性,那么当我们打开一个数据的时候,你会发现诶其实再复杂的数据,它都是有很多简单的building block构成的,比如说我们去描述一个点光源的时候。
你其实有的是什么,很多时候都是诶他的一个vector3的,一个它的坐标,它的点点的位置,它的方向也是vector3诶,他有一个什么呢,它有一个颜色对吧,各种各样的颜色,比如说NB的DIFFICKER。
对不对,这其实都是一些非常基础的一些building block,在这里面我们就观察到一件事情,就是说其实任何复杂的数据,我们可以把它描述成一些简单数据的集,这个像什么呢,就像我们现在物理学。
虽然这个世界非常的复杂,但是我们会找到基础的原子,108种原子,我就可以通过它的组合去表达,这个世界的任何一种物质对吧,那么好,如果这些原则我们来找到,接下来我们需要什么呢,哎我们需要一个东西。
这个东西叫什么呢,我们叫做schema schema呢,其实我觉得这是这个词很有意思啊,就我这是这个标题,是我自己写的,就是a description structure,就是说是一种描述的结构。
用一种更简单的话去讲,就是说啊就像刚才我举的原子这个例子,那么这个schema更像什么呢,更像分子式诶,这个有点意思了吧,就是他描述的这个物质是由哪些原子构成的,就像今天我要定义一个长方形啊。
第一个长方体其实它的描述就是三个量,就float x y z代表了它的长宽高,对不对,如果我要表示表示一个圆的话,其实我就一个量float2他就表示出来了,那么这个float加一个东西。
这个结构就是一个schema,那你按照这个schema写出的数据,它就是一致的,所以schema系统的话呢,是游戏工具链最核心的一个底层,就是说所有的在游戏这个工具链里面流流转的,这样的一个数据的话。
它都是要用schema统一的描述和定义的,这样的话我的数据彼此才能解读,比如说我一个啊,比如说地图编辑器打开了一个角色,这个橘右进来,那角色他如有,如果有了CHEMA,我就知道哦。
这个character name叫什么,这个character的这个这个这个声,它的放缩是多少,他用的是哪个mesh,他用的是哪个动画,那这样的一个角色一拖到我的编辑器里的时候。
我编辑器在那个panel里面就会出现他的名字,他的动画,然后呢你点那个动画的播放诶,这个角色他自己可以就可以动起来了,这些代码全部不是他的code,它全是通过schema告诉各种各样的工具。
你该怎么去理解这个数据,它每一个数据的语义到底是什么,那么好,那么其实呢就是说,schema是一个非常重要的表达,因为我用这些简单的building block。
我性能表达一些high level的数据,举个例子,比如说我们的一条curve curve是很重要的,在游戏引擎状况,就比如说我们在粒子系统中,我们怎么去表达这个一个色带的,随着时间的变化对吧。
那我可以把它RGB通道变成客户,那其实呢在schema里面你可以表现成什么呢,哎表达成一组这个点的这个集合,那么在scar你就可以表达出来,那么其实你用这个最简单的元素。
用schema去构建出了各种各样,你想要的HILIP这个数据,那么就是说其实schema呢它本身是非常复杂的,但我记得里面给大家讲几个概念,就是说第一schema的话呢,你要设计它的时候。
它需要有继承关系,这也就是说,这个其实这个是非常像我们高级语言的,这个类的派生继承,因为schema本身就描述了一种类嘛,比如说我们定义的一个东西叫做啊,人人的schema有什么对吧好,我有他的身高。
他的他的他的长相,他的这个这个这个这个体重等等,所有的数据好,这是我的第一个一类数据叫什么呢,叫军人好,这个军人这个schema其实你不用再重写一遍,你其实可以从人的这个schema派生出来。
你再加两个field,比如说它的战斗力是多少对吧,它的血量是多少,对不对,这些数据你就有了对吧,你再派生一个,比如叫商人,商人送人派生的唉,你可以说他有钱有多少,他的这个经商能力是多少。
其实这个schema的话呢,实际上就非常像我们的高级语言,你们的角色对应,所以在这里面的实现有两种流派,有一类流派,它真的就是用高级语言直接定义的哦,待会我会讲到。
那么还有一个呢就是在schema里面的话呢,我们要允许他去互相reference data,就在前面EEE我也讲过了,就是reference data非常重要,比如说我去定义一个车的描述的时候。
我就会说有些field的,它是指向了另外一个资产和数据对吧,所以说其实我们这些asset之间的关联的话,有一个是动态的,就是数据之间真实的就是S之间关联,还有一种呢就是类型之间的关联。
你可以看到一个比如说我去表达一个角色,这个角色呢它会引用到一堆的文件,比如说网格啊,动画呀对吧,行为数啊这些文件好诶,我在这个网格,这个就是我的这个这个mesh这个文件里面,又会影响到什么呢,哎纹理啊。
贴图啊,这些文件就可以全部的这个就会引用到,所以这个也是非常有意思的,就是说其实我们在数据定义层面,也会形成一个关系数,所以当我们在这个游戏引擎构建的时候,首先大家一定要构建一个schema系统。
第二呢你在设计schema系统的时候呢,我会强烈推荐大家去建立,schema之间可以去继承,这样的话,我可以不断的去去派生出各种各样的变种,第二个的话,在中间我要允许用户去定义,各种各样的数据应用。
那么刚才提到,就是说schema的定义它其实非常像高级语言,所以呢它就产生了两个流派,有一类流派呢,他就是诶直接用那个类似脚本的这样的语言,或者用XML用什么语言,JASON其实也可以。
我就直接定义了schema,OK完事,这个这个数据很干净对吧,那么的话呢他用一套方法,直接把这个东西反射成这个引擎的代码,让引擎直接根据schema,就知道怎么去读资产文件了,包括资产文件怎么读。
怎么写,怎么编辑,它全部自动生成对吧,这个地方我就不展开了,其实这里应该画一张更更有意思的一个图,还有一种方法是什么呢,其实就是大家非常熟悉的,比如像unreal的做法是什么。
我其实定义了一个C加加高级语言的一个类,但是呢我通过一个红去描述唉,说我这个东西是一个matter的一个数据,我可以反射的好诶,我接下来就这个我这个对应的数据有,然后这里面,但是呢它里面定义了很多变量。
对不对,我也不用所有的变量,我看见这几个变量,我是希望他在那个就是文件中是有反射的对吧,包括一些方法我都能反射,其实大家回想一下,我们的QA引擎用的是哪个方法对吧。
我们pk ue引擎用的其实是defined in the code,其实我们跟AL的方法是一样的对吧,但其实我们另外一种话,我们也写过哪种方法,哪个好哪个坏呢,啊这个说句实话,我是很难给出评判的。
因为我个人觉得这两种方法各有利弊,那首先比如想这个用stand alone的文件去定义呢,它的好处是什么呢,就是说他非常非常好理解,而且呢这个就是说他真的是彻底的。
把这个数据的定义和工程实践彻底剥离开了,但是它比较麻烦的一件事情是什么呢,第一个就是说它需要有一个就是自动的代码,渲染器,叫代码生成器,根据你的chema passing生成各种各样的代码。
它很容易出现一个问题,就是说你的schema版本可能是过新的,或者过老的,但是呢你的引擎二进制呢可能跟它版本不一致,当然我们有很多方法可以检测啊,比如说他发现4K码是错的,那引擎就拒绝启动,对吧。
死给你看,那你说啊,我知道了,我schema文件配错了,但有的时候对于非技术性的同学,他就觉得这个事特别的蛋疼,所以这两个之间版本不兼容啊,实际上是这种方法是经常会遇到的问题。
那么第二个呢就是经常会遇到的问题,就是说在这种文本方式的话呢,我很难定义,就是说比如说这一个人这个角色,其实他有很多的接口,它可以做很多动作的,比如说我们叫做API,那你其实你没有办法去定义的对吧。
但其实当我们定义一个东西的描述的时候,其实我还可以描述它能做什么事情,那这个时候呢啊实际上这个分开的文本方式会,其实他可以做,你真的强行去写,通过反射,我把函数名写在那对吧,我在加C加加你反射一下。
我总是能找得到的,对不对,但这个事情就显得有点笨,所以一般来讲,如果你真的把它剥开了的话,我们真的把它彻头彻尾的变成一个数据的定义,那么这一点的话呢,反而在引擎就是用code代码直接定义4K码。
反而是有它的优势,就是说它可以直接的,就是说把一些方法也包进去,另外一个的话呢,因为它它的数据定义和它的引擎是高度匹配的,所以你一编译完之后,他整个就一套全全下来了,所以他不太会出现两个版本不兼容。
但是他的问题是什么呢,他的问题就是比较复杂,就是经常特别比如举个例子吧,比如说像那个虚幻引擎,就大家用很多,很多使用者会发现一个问题,就是说当你去真正去动这些引擎代码,改变一些数据结构定义的时候。
经常已经就死给你看了对吧,编译说诶就挂了,或者编译可编的过,但是跑起来就挂了,崩了之后你就要花很长时间去debug,而且如果像我刚才讲的,如果你的工具链炸掉了的话,那么这个对整个团队的影响就会非常大。
当然这个我们会通过一些UE,UE来来尽可能的覆盖嘛,所以的话呢一般来讲就是在code中定义的schema,对于这种巨型系统来讲的话呢,它对你工程的稳定性和架构的鲁棒性,要求是蛮高的。
否则的话特别容易把整个引擎加,工具链一起搞死的这种情况,所以的话呢两种方法你很难说好坏,但各有利弊,所以啊同学们可以根据自己的选择去选择,那我们这次做PICO的时候的话呢。
呃我们是想教给大家一些有意思的概念,所以我们就选择了这个就是这个这个,这个这个就是again的这个方法,这个方法的话呢,其实大家一直很想知道那个matter pasa,怎么work的嘛。
实际上你你看懂了metaphor这个机制的话,你就不会觉得像虚幻引擎的反射,有那个就很难理解了对吧,其实它的核心底层逻辑是非常接近的好,那其实呢就是说,其实我们schema也反映了一件事情是什么呢。
就是说同样一个数据在我的工具链中,在我的整个这个游戏的生产体系里面,它有三张脸,他的第一张脸呢实际上是给硬盘的,就是我存到硬盘中了,刚才我讲了,你可以存成二进制的,你也可以存成这个。
就是那个文本格式的对吧,反正呢它这个它的存储空间很大,随便你怎么存都可以,但是实际上如果一个真正商业级游戏的时候呢,我们还是会很在意它的存储空间,因为啊,比如说你几十个G和上百个G的体验。
是完全不一样的,而且那个如果上百G的文本加载那个速度,那可是非常感人的,这个这个应该没有任何一个商业级的游戏公司,会这么干,那么在内存中呢没有的选择,他一定是二进制的,但是呢它的核心都是什么呢。
就是以这个处理为目标的,第三个还有一张脸是什么呢,哎在整个工具中给用户使用的,它也是第三张脸,那么在这个就是说那个内存中的话呢,我们一切是以这个数据以高效处理为目标的,所以说呢我的数据结构定义的时候。
都是为了各种数学变化,比如说加减乘除,比如说拷贝添加删除速度快为为他的依据,那么在这个内存中的话呢,就是在存储中的话呢,我们一般会尽量以节约存储空间,这里面举个例子,比如说像那个一个矩阵。
我们的投影矩阵,很多时候呢,其实你只虽然它是个4×4的矩阵啊,但实际上你能用到的一般是四,4×3或者是3×3,那哦33×3加一,那这个时候呢,我们一般就会做很多数据的压缩处理。
这个也是一个非常重要的一个方法,但是最有意思的我们认为是工具的这个view,工具这个view,那么这里面讲一个细节,就是说我们实际上schema定义的,比如说一个color,你看到的就是三个。
比如说整数,但实际上在工序里面,我们就会把它变成A大家可以看到的颜色,这边你看到的是几个不同颜色的标记对吧,实际上你在点开来之后,你可以看到一个,非常符合人的理解的一个调色板。
这就是工具最核心要解决的问题,就是我要对不同的人展开不同的view。
举个简单的例子啊,比如说在设置一个引擎数据的时候,很多时候我们会设置角度角度,在引擎中,一般我们用弧度,为什么呢,在所有的那个数学库中,它的max,比如说sign cos。
tan的这种计算全部是基于弧度的对吧,因为你们如果理解计算机里面怎么算,是数学运算的时候,你就知道弧度是最基础的计算方法,但是唉你跟artist讲说,你输入一个3/4派二次,怎么算不就封掉了嘛,对不对。
那这个时候实际上我们输出的全是欧拉角,比如说270度对吧,180度,360度,45度,这时候大家人人类就非常好理解,其实类似这样的东西啊,在整个工具链里面非常重要,这就是我们在设计工具链的时候。
一定要把这个数据变成一个,人类可以理解的一个view,那同时的话呢有些数据它非常的复杂,怎么办,我们可以提供两种UE,一种view是default,简单的view就是我只放必要的,你可以调的数据。
有些地方呢我会放一些比较丰富的展开的,这样的一个view,其实也都在解决这样的一个问题,所以这个其实在做工具链的时候是非常重要的,这就意味着当我们在第一schema的时候,我们对于每一种数据类型。
实际上我们要提供一个可以为他定制,不同view的这样的一种能力,这也是当我们再去做to chain的时候,很重要的一种方法,那么最后呢给大家讲一个就是大家很小啊,这这不是最后就是哎也是个很酷的名字。
就是WYSIWYG对吧,现在是个缩写,满天飞的东西,就是大家看见这个肯定会觉得哇,这什么玩意儿这么长,这么诡异对吧,不有没有YYDS那么传神,但这个呢其实是一个很酷的一句话。
叫what do you see is,What you get,就是所见即所得,这可以理解成,就是说,在我们构建整个工具体系的一个核心精神,那为什么这件事情很重要呢。
因为其实工具啊对于我们的这个artist来讲,它是一个非常重要的一个,就是啊一个一个preview的一个东西,就是说其实最早以前很多游戏引擎的工具,它是独立去写的,早期的时候。
但是为什么后来artist不满意,因为我不能够接受,就是说我在你的编辑器里调出的效果,比如说它的光光照,它的材质质感,这个人物的动作和我在真实游戏,跑起来的东西是不一样的,如果这两个是不一样的话。
那美术的校呢艺术家的效能将极度的下降,所以说他要求在这个工具链里面,实现一比一的百分之百还原的一个preview,就是我要知道这东西讲什么呀,否则这个东西材质我没法做。
那么对于designer来讲是什么呢,工具链是一个非常重要的一个,game played prototype的一个工具,它要在这边最快速的方法去prototype它的工具,比如像这里面。
比如说诶我快速的决定加一组墙去阻断,这时候我要感受一下,我这个人玩家拿到这把枪的时候,我射击的感觉,我的整个能看到什么,我不能看见什么,这个地方设计师也是需要我最快的速度,最低的成本去尝试不同的。
比如说关卡的layout,这就是就是大家无论是设计设计好还是美,艺术家也好,对工具链提出的要求就是我希望所见即所得,那之前怎么做呢,就这里面要讲的就是工具链,在整个引擎里面的架构方法。
其实最早期的架构呢,我们一般是把工具链独立放在一边,因为大家知道工具链的逻辑是非常复杂的,它有很多的编辑啊,你想象一下,比如说一个简单的物理,你对它进行拖动和移动操作。
他知道那个简单的那个那个叫那个小旋钮,旋钮叫gadget,实际上协调的逻辑很复杂,为什么它要实实现那种自动吸附啊,然后呢旋转的时候要按整数角,比如五度与旋转呢,而且自动alignment。
而且你这个快捷键切换在旋转那个平移放缩,来回切换,而且你还要自动对齐,大家如果用过vile,用过word这些软件,就知道这些细节其实非常的多,这里面有很多很脏的代码,而且非常的这个special。
所以你最自然的感觉就是诶,我需要保持一个非常clean的我的引擎对吧,那你呢可以给我共享一些代码,OK但是你的工具链这些脏的,比如说如何编辑一个动画,如何做这个这个行为树,如何去去管理这种资产的。
比如说做这种摆放这些东西,你全部给独立的,它是一个独立的工具链,但是这种架构呢它会出一个比较严重的问题,就是什么呢,就是说诶你特别是在artist那一趴,真的所见非所得。
那么对于designer来讲的话呢,你虽然能够帮我快速摆放,但是我没有办法直接在游戏中去play,一模一样的东西,所以这种方法现在的话呢,在商业级引擎中用的已经越来越少了。
现在大家真正用的比较多的架构是什么呢,就是诶我把工具整个架在游戏之上,说白了就是我在工具里面直接调用的是游戏,大家首先想到的是什么,就是场地图编辑器,对不对,我在地图编辑器里面,我可以直接编辑这个场景。
然后呢哎我一键就可以去play,那我肯定需要这个,但实际上我给大家讲,比如说不只是地图地图编辑器啊,比如说我做特效编辑器,那我希望呢他一上来也是游戏引擎好的,OK不好意思,他也是游戏引擎。
那么其实的话呢,包括像那个就是比如说大家像动画编辑器对吧,还有一些cinematic,就是比如说像艾瑞亚,你们最著名的sequencer这个编辑器,其实下面跑的就是一个游戏,那这样的好处是什么呢。
就是说哎我调好的材质,我做好的动作,我调好的光,我设计好了一个特效,我我在游戏中看到的东西,和在编辑器里看的东西是一模一样的,所以这个方法呢它本身开发起来啊,其实从设计架构上要求是蛮高的。
因为要求游戏引擎,它能够向上兼容编辑器的需求,但是的话呢它带来的好处,特别是对于生产效率的帮助是巨大的,所以说在现代商业级游戏里面的话呢,我们一般都会采用这个架构,包括PICO。
其实用的也是这个架构对吧,叫硬件这个模型,那这个应变模型的话呢,它实际上就会要求在引擎的RUNTIME上面,我们要加一层asha thing,就是编辑的这个场景,这里面和管理我所有编辑的整个逻辑。
这些这些,比如说UEI编辑相关的各种各样的,中间的这种数据和状态,然后呢再往上呢,我会生成我独立的编辑的UEI,就刚才我讲的GI,它这个体系就往一层层上去了,所以这个结构其实你维护起来的话呢。
是比较复杂,但是呢我们会给同学们讲的,就是说如果你们想做一个好的,这个就是游戏的工具链的话,我们会非常强烈推荐大家用这个模型,当然未来这个结构被淘汰了呢也是有可能的,肯定有人发明更好的结构了。
目前为止的话,行业你大概会觉得这个结构是最好的,因为它能真正实现我们的所见即所得,那么这个时候的话呢,另外一个很重要的概念是什么呢,就是playing editor,就说这个呢也是符合这个。
特别是对于啊其实不仅对设计师吧,其实对艺术家来讲也很重要,就是说呃我做好了一个关卡,实际上我去编他的时候,和我真的去玩它的时候感觉是不一样的,对不对,比如说我作为一个关卡设计师,我做IPS对吧。
我做了个关卡,我想感受一下我在里面打枪穿的感觉,所以我希望一键就能play这个功能,叫做API,就playing editor,那么APIE呢,实际上是现代游戏引擎很核心的一个需求。
但APIE呢有两个实现的方法,第一个呢是我在编辑器里面直接就可以play了,对吧,就playing editor,还有一种呢是什么呢,就是当你去点这个API按钮的时候。
我会形成一个专门的叫API mod,你可以理解成,就是把我现在编辑的所有的东西再拷贝一份,我启动一个游戏,然后呢在里面再跑一份,那你显然第二种方法是不是很麻烦,对不对,第一种方法是不是更简单。
实际上的话呢这两种方法各有利弊,比如说就是我直接在editor里面去跑的话,它其实这个结构就比较比较简单,而且呢它是非常容易实现的,就等于等于说我把编辑的状态,直接就可以无缝的去play了。
比如说我们的皮克勒小引擎,就是这个模型,大家在我上次跟大家讲的就是学了小引擎,有个特点,就是你现在如果这个角色你跑跑跑,跑到一某一帧的时候,你突然说诶我要编辑了,你会发现在编辑器里面。
这个角色他就停在那个位置,他就在做那个动作,这其实就是playing editor这个结构,这个结构呢它的优点是什么呢,非常的简单,但是它的缺点是什么呢。
诶editing的这个数据和游戏的这个引擎的数据呢,它有的时候会混到一起去,混到一起会出什么问题呢,给大家讲一个简单的情况,就是比如说我们editor里面有大量的数据对吧。
它会污染游戏play的逻逻辑的数据,但是理论上我们会认为分开对不对,但你写这么复杂的系统,有的时候你分布的分布分布的特别清楚,那这个时候我们可能会出现一个问题。
就是诶这个玩法在editor模式里面没有bug,没有问题,但是呢当我编程独立的游戏的时候,诶编程那个release版的时候,突然你发现了遇到了一些问题,反之亦然,就可能有一个问题诶。
你在这个就是editor版里面有问题,但是在那个就是那个在游戏里跑团又没有问题,但这个其实你可以认为是个bug,但实际上确实你很多时候那么复杂的系统啊,你很难把它加在临清。
所以呢就是比如说像unreal,他采取的模型是什么呢,就playing piano word,就是说我把现在所有的editing的世界,整个把这个物体再在一个pie。
那个一个一个沙盒里面全部重新创造一遍,我把环境全部重置一下,然后呢,这个时候我在这个APIE的mod里面去玩这个游戏,相当于我多花了一些内存,给这个世界做了一个单独的player的分身。
这个逻辑呢其实它能解决这个问题,而且呢它本身更能模拟游戏的单独的一个环境,其实呢这个结构呢,我个人认为就是,如果你要做一个大型的复杂的游戏的话,我倒会建议这种模型,这种模型的话虽然你会浪费很多内存。
但现在内存还好对吧,我们像我们电脑配个60多G的内存,也能配得出来,实际上的话呢是一个比较好的一个方法,所以的话呢大家在下这个游戏引擎,工具链的时候,大家可以在这两个模型中自己去选择。
就是选择适合你自己的模型,如果你做的是个小型的,比如说啊不是特别复杂的一个游戏引擎的话,那我觉得就是那个playing editor其实基本上就够用了,但是如果你真的希望能够商用级的。
给很多很多人用起来的话,而且面对是个复杂的一个游戏系统的话,我们会建议你会考虑就是playing API的这个模型,会更好一点,那么对吧,这个这是我们真正的最后1part了。
就是one more thing了对吧,plugin对,这个真的是one more thing,为什么呢,因为讲到这儿,基本上你所有的工具该怎么做,你都知道怎么做,那为什么我们还要做plugin呢。
因为是这样的,就是说其实啊我们做一个游戏引擎,你要知识的游戏是千变万化,完全不受你控制,你根本想象不到,作为一个游戏引擎开发者,你根本不知道你的用户会用它做什么样的游戏,然后它需要什么样的功能。
我们我们从来不会自大的认为,我们做出了所有我们用户需要的工具,这是不可能的,所以我们一定要允许我们的用户,他自由的开发各种各样的工具,比如像这里面这是UE的一个插件对吧,是一个第三方开发者。
他可以自由的开发一个完整的一个,水体交互的插件,你水的这种各种各样的属性啊,它都可以在里面去调,他怎么去模拟,怎么去仿真对吧,其实这个实际上奠定了现代游戏的,我们叫stability。
就是它的可扩展性其实非常的重要,那么其实插件呢实际上是现代商业引擎,最重要的一种开发能力,所以我们经常在讲的就是,现代游戏引擎的本质是什么,我认为是个up,就是它是个平台。
在这上面的话可以集成各种各样的功能,这都是由第三方开发者去开发的,举个例子,比如说大家去打开3D max maya对吧,比如像胡迪尼,像那个ZBRUSH,其实呢它都有大量的插件。
就是提供了丰富的功能给大家,就是能快速的完成功能,因为能适应你千变万化的需求,所以插件是个很重要的一个系统,那么插件它对于我们整个引擎的要求是什么,特别工具链引擎,实际上我们需要提供大量的API。
这些API的话呢能够开放给第三方开发者,他通过我们的接口能够注册各种各样,他想要的功能,并且定制他的药药的UEI,然后呢能对这个世界进行自己所想要的偏激,那么其实呢在这里面的话。
这个这个API的设计就非常的重要,比如说我们要在我们的to b上加一个API,E的按钮,对不对,那我就要说诶,我知道你的API我要注册,把我的这个plugin注册进去,然后呢把我的按钮创建进去。
这个时候我的pluck manager就会帮我,把整个这个世界给构建起来,那么其实今天当我们去设计一个游,戏引擎的时候,其实你的可扩展性,plugin的这个方便的能力,其实我们认为是个刚需吧。
就是说所以的话呢就是比如像这里面,就是说你的arrow ue里面去,你家加入在它,在它的主MANUE中加入加入一个你想要定制的menu,其实是非常简单的,这个地方的话就是现在的成熟的商业引擎的话。
知识方面发展的真的是非常的好,同学们如果想真的想做引擎往前走的话,我会非常建议大家去向这些引擎去学习,看看它怎么去提供这些接口,让我们的这个引擎变得真的有可扩展性,那么这也反过来啊。
对我们的整个引擎架构提出了一个要求,就是说你要尽可能把你的各种功能API化,你自己的这个编辑器功能,比如说我们做一个level editor,我想做地编,我想做产品编辑,我想做自动grouping。
做prefab,我尽量通过调用这些API的方式组合起来的,那这样的话呢,当别人去开发我们这个引擎的插件的时候,我们彼此是平等的对吧,你用插件,我也用插件,那这样的话。
就是说他至少不会受到太强的这样一个限制,所以的话呢这也是就是说现代游戏引擎的话,在做架构的时候,一定对它的可扩展性,对于他未来的这个无限的扩张的很兼容性的话,提出了一个非常高的一个架构性需求。
所以同学们如果励志啊想做游戏引擎,大家肯定会希望我说我,我我知道各种各样很很厉害的算法对吧,我会做很多很多很多的效果,但是我希望同学们意识到一件事,就是说做现代游戏引擎。
其实它是一个软件工程学的一个问题,然后呢它最核心的东西就是你要搭一个平台,能够让成百上千甚至上万甚至上10万,这些优秀的工程师,这个创造者和你一起来工作,这样的话你的这个平台才可能会成功,所以的话呢。
这个就是我想,就是当我们第一章讲基础工具的话,我最后想跟大家讲的就是可扩展性,是工具的一个很核心的一个诉求,那以上呢就是我今天的这个,就是这个报告的内容,那今那个按照我们的惯例。
那我们最后可以和大家分享一下,我们的一些reference,就是我们找到了一些,就是在准备这篇课件的时候,我们准备了一些参考文献,那接下来的话呢,就是也感谢一下我们课程组的小伙伴,大家真的是非常的辛苦。
非常的感谢,其实哈昨天夜里两三点钟大家还在搞,然后今天是到最后大概不到30分钟吧,我们才把今天的课程定下来,之前的话真的所有人头发皮都已经快抓没了,都快都快抓掉了吧,所以说压力其实非常大。
但是希望同学们能对我们的工作满意好了,那大家有没有什么问题问我们关于这节课哇,这个第一个问题是问的很很很大啊,就是工具链开发需要的能力是什么啊,其实这个这个问题是蛮有意思的,我个人的理解啊。
就是工具链开发第一个需要的能力,就是说你对游戏的这个基本的制作,有一个基本的理解,你最好有时间可以参与一些游戏的真实的开发,你真实看到就是设计师啊,艺术家怎么去工作的。
这样你能理解就特别理解我前面讲的那句话,就是但他大大家的这个思维方式,真的差别非常非常大,很有意思的,但是每个人都是非常合理的对吧,那么第二个的话呢,就是说你对软件架构,软件工程特别感兴趣。
你并不一定需要知道很多很精深的算法,但是呢你要有非常好的这个软件系统,架构师的这种思维方式,因为工具链最核心的是软件架构,就是说一个功能,你用你有十种不同的方法做出来,但是好的真的只有那一两种,为什么。
因为好的方法它在未来有真正的可扩展性,所以的话呢我觉得就是说,如果你有一颗励志做软件架构师的心,然后呢你本身又对游戏很感兴趣,我觉得你就可以成为一个非常好的,工具链开发的这样的一个一个开发者。
好还有没有问题,诶这个能再说一遍web前端什么,唉这个问题问的很有意思了,就是女同学问我说,工具链用外部前端做的多不多,诶这个是一个非常前沿的一个讨论啊,其实我自己现在也没有下最后的结论。
就是我们内部已经做了很多场讨论,首先的话呢现在工具链的话呢,用web前端的好像还不多,比如像大家很熟悉的,比如像aa unity对吧,包括像一些其他的事件引擎,但是呢随着现在外部。
比如现H5越来越强大对吧,包括外部的开发效率越来越高,懂的人越来越多,其实我自己现在也一直在思考,就是说基于web的这样的一个前端的这样的一个,工具的开发的话,是不是也是一个为了很好的一个方向。
因为确实它的底层逻辑,底层结构很多东西是很接近的,特别是基于刚才那个就是说啊,就是那个in game mode的这种方法的做工具链,其实你最比较复杂的东西,我们是全部交给了引擎来处理吗。
那其实跟用户的交互,比如那些UEI对吧,那些逻辑衣服逻辑用web前端的方法去做的话,其实效率说不定还是挺高的,所以这一点的话呢,我现在更prefer就是它是一个open question。
如果同学们对这事情有兴趣的话,我非常希望大家能够拉我们的教研组,那个课程组,我们一起讨论这个,我去我我我很想把它变成一个RNG的课题,说不定我们可以去外部技术,做出一个完全不一样的。
那个一个工具链体系出来,对啊,比如说我们拿PICO下手,对不对,我们PO真正的工具链体系,可以全部web的技术去做一做,我们看看这里面有没有什么坑,因为确实确实啊就是这种专业的游戏软件啊。
专业的软件选型的时候,很多时候有很多很性感的技术在那边诱惑我们,但是很多时候大家会啊考虑到,就是很多的工程上的不确定性,因为一旦一个决定下了之后,它的成本是非常高的,所以我们会比较谨慎。
但是呢这毫不妨碍我们大胆的去想象一下,用一些前沿的技术去表达,哇这个问题就问得更有意思,有同学问我说协同编辑有没有很好的实现,那首先的话呢以目前行业来看,我觉得实现的还在一个早期阶段。
包括像aria five,最近的它最大的卖点就是协同编辑嘛对吧,也提出了很多的概念,那么那但是的话呢我觉得就是首先内容的话,我们会在下一节课跟大家简单的讲一下,就是协同编辑怎么去怎么去实现。
如果大家有兴趣的话,其实你就算基于PICO引擎哈,你都可以做一个非常简单的,协同编辑的一个实验,这个当然了,我不会把它做成作业,因为这个话有点有点难的,但是的话呢就是说呃我认为协同编辑这件事情。
它的重要性也是一个在非常快速的提升,包括大家的方案也会越来越成熟,我个人很相信大概在5年左右吧,协同编辑这个问题,其实会得到一个非常好的一个解决,那么这里面它的基础理论已经基本成熟了。
接下来就是大量的工程问题需要解决,因为无论任何一个商业级的游戏引擎啊,现在都是千万行代码的这样规模,所以呢它是一个很复杂的一个系统,你让它全面的支持协同编辑的话。
那么你又不想又想保证这些功能不会丢失的话,其实在工程上的挑战,比如很多向前兼容的这些问题的话,其实还是蛮复杂的,举个例子,比如说大家都觉得word很厉害对吧,word实际上是啊。
非常成熟的一个一个一个文字编辑系统,那么但是我们一旦把它word云化,让大家协同编辑,你会发现他被迫要做很多的减法,包括这个系统,我们也看到在过去几年就发展得非常快,那今天的话我们用各种各种网上的这个。
协同编辑软件,那么现在感觉已经越来越顺手了,大家看到这个过程的话,可能需要三到5年的迭代和完善,但直到今天的话,你在本地区编辑word的那种强大性,易用性还是会超过协同编辑的那个网上那个word。
其实呢这一点其实很能反映我们的游戏引擎,将来要面临的问题,好OK好的,今天时间那个控制的比较好,大概是一个半一个小时45分钟,那那个就是首先那个谢谢大家,那我们下一节课的话跟大家讲一些game in。
那个game游戏引擎里面的工具链的,更有趣的一些内容,好的,那我们今天就到这。
谢谢大家。
13.计算工具箱:图像模糊 | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1qe4y1v75r
好欢迎同学们回到计算成像的课堂,其实前几天呀就是自从我上节课讲过了那个flash跟not flash葡萄过费,也就是我们整个图像,我们手机拍照的时候要拍两针,先把我们最后那个反射去除掉。
这个这个很不幸啊,我试了市面上大部分手机这个都不行,这些功能都没有的加进去,这个还是希望同学们以后步入工作呃,相关的要做相关的工作呢,可以把这个功能加进去,我们是找了好多同学。
就是把市面上主流手机都测了一下,就是打开闪光灯,我去拍照的时候,他并没有对这个就是这种玻璃啊,表面的一个是flex进行纠正,所以说这个这个还希望同学们以后啊多多多多努力,最近昨天啊,昨天还是前天啊。
这是我们在上海嘉定开了整个计算成像的会议,也非常多一些新的内容嗯,也是非常有趣的一些内容啊,还有它在应用上都有非常多的一个进展,希望同学们也关注一下这个计算成像会议,嗯,应该是现在已经是开完了。
就是大家可以在整个计算成像官方的一个网站上去看一看,大家最新的内容,就我看到了有非常多有意思的内容啊,这个已经达到了几赫兹的这么一个速率,这个非常惊人,我感觉这个单光子的一个3d成像已经非常接近极限了。
非常接近极限了,这当然这也非常有意思,但目前为止就是嗯我们看到了很多就是单光子的成像呃,也像3d成像,当然本身啊这个我们最后都是基于一个新的器件啊,叫spd,也就是单光子雪崩光电二极管阵列,诶。
我们这也有单点的,也有单光子的,就是现在嗯世界上有非常多的一些小公司啊,已经开始用了,第一个真正的一个大规模应用的就是iphone 12 pro啊,那是上了一个一个小的expect之列。
当然它的设计比较精巧,他在照明的地方就是做了一个很科学的一个调制照明,就是我最后拍摄的还是一系列的点阵,然后呢它是通过一个vexcel一个成功的一个vcr管,诶,这个这个vs管子。
它不像我一个简单的一个只是点亮跟灭的这么一种reaccel管,它是有很多个引脚,这个引脚可以控制一下这个照亮照亮这个点的一个微微的变化,诶这个时候我就可以通过一个电控的一个扫描诶。
来最后呃通过一个时域的一个呃牺牲一点时间啊,就来扫描一个比较大的一个呃,点云精力当然也不是特别大哈,因为手机很多地方都局限于功耗问题,诶后来呃目前国内的一些产品上呃,还是没有用到这些3d成像。
当然以前嗯大概1617年吧,就是可能是哪家公司,我忘了,可能是oppo,但是用了一个etf的技术,后来apple用了一个t top,但这几年可能是就这2年吧,就是大家并没有找到在一个手机上。
这个3d成像到底能怎么用,所以说呃这一块就是整个市场上有有一点渐渐萎缩的趋势,当然我们呃整个的一个成像链路来看,就从低维向高维发展永远是一个趋势,就是我们也不至于介怀,整个市场就稍微有点下滑。
但也可能是受经济影响呃,它的整个整个的一个趋势还是向低位向高纬的一个呃趋势迈进,哎我们这个six d f呀,或者是更高维度的一些这个信息捕捉过来之后,诶,它实际上是我们后面构建这整个元宇宙的一个基础。
唉这个课前再给大家锤一扯,就是现在的一个目前的市场态势,当然要同学们要看到什么新技术的话,也欢迎在群里啊给大家共享一下,唉后面就是给大家掰扯一下,就是这个作业啊,马上下周出吧,我会把下一次作业或者出去。
就关于前两次作业啊,其实难度不是特别大哈,就是特别是第二次作业就基本上对是第一个对第一次作业的一个延伸,那第三次作业难度也不是特别大啊,因为我觉得这个毕竟是一门公开课嘛,如果不是太难的作业。
可能呃会影响同学们的积极性啊,所以说i s p嗯,第一节课给做的是i s t,因为i s t每个环节都不是特别难,但是可能大家会堆在一起之后,发现各种各样的bug就出现了,当然这个也不是啊。
这个地方是比较难的哈,因为工业里面呃用的环节多了,它就会出现各种各样的可能性,我们那除了想解决最后一个效果问题的时候啊,也是要解决一些corner case,这些collar case,比如像鬼影啊啊。
或者像一个呃快速的一个自动变焦啊,这个地方是没有给大家呃加进去的,因为这个只拍一个图,就没有办法给大家做一个像工业一样的一个s t,但是这整个链路我相信大家都已经是比较熟了。
这个时候嗯相信大家工作以后也会比较有帮助对啊,整个东西有一个完整的一个背,叛那后面呢呃我们后面的课程里会渐渐的涉及一些优化的方法,还有一个学术界使用了一些算法呀,那整个计算成像的课题哎比较多哈。
这个我们也不可能完全覆盖到,但主流的方法跟解决方案,这个大家会给大家覆盖到,其实大家想一想,这个计算摄影其实挺简单的,就干了两件事,第一个是光学编码,第二个就是用算法把编码的信息给提取出来。
哎无论是你想要把它变得shop一些呢,还是去个now,去个造呢,还是高级一点,我要做个呃image editing,它本质上都是调制和解调的这么一个过程。
就是说诶这个时候大家可以总结出来一个自己的套路哈,这解条里面有哪些算法可以用,调制过程,有哪些方法可以用诶,这个时候大家对整个的领域就有一个big plan,嗯好了,时间差不多了。
就是今天呃正式的给大家分享一下,就是我们computing toolbox里面非常重要的一个环节,就是image blue,这本来是想放在一节课讲的,但是后来看到这个。
因为这不乐跟迪普勒两个一起讲一点内容太多了,所以说呢就把嗯这一堂超长的课就拆成两节课,嗯诶这个时候其实啊伯乐大概我们总结一下基本的一种地面就不乐意,大概有四种成因,实际上很多时候就是因为手抖引起了诶。
我们物体的运动也会引起不,还有本身呢我们透镜的一些缺陷啊,还有加工的缺陷,还有衍射极限诶,这个时候也会影响我最后成像的一个不落的一个过程啊,其实最后呢还有一个就是auto focus。
我们知道我们无论是怎么样直接拖进这个透镜,都涉及一个谨慎的问题,所以说呢就我们大概总结了这个image ber大概有四种啊,image brea成一诶,我给大家今天这节课给大家一一的拆迁。
为什么我们的这个这个图像会产生这个不乐,然后我们这个blo那怎么解决的呢,啊解决的话我会给大家留到下一节课,下节课我们会啊介绍各种各样的一个deep乐的一种方法。
这个时候就给大家引入一种新的方法叫half codc splitting啊,同时也会给大家来介绍一下呃,transformer的方法,呀啊优化的方法呀,那针对这个布莱尔,它有各种各样的一种解法。
其实到最后大家应用的过程中就会有啊一个自己的一个想法,我们对于什么样的场景,对什么样的一个br诶,我们这个是怎么用它,当然现在有很多博乐啊,我是想对这个video,特别是比如运动相机。
唉我想对这个video直接debuted就是real time的,对我捕捉过来的video deep,这个时候又该怎么办呢,诶这整个blur and the deep这个过程中。
大家就会对整个的一个模糊啊,就跟去模糊诶,有一个非常完整的这么一个直观的一个解决方案,就在脑中,脑大,家脑中要有一个完整的一个解决方案,要抽象这个问题,然后去解决它,就刚才说到了,我们有四个b乐的来源。
还有加工的曲线,其实这个很简单啊,就可以理解为我们这个相差,还有它本身的physical limit,就是透镜,它本身都有口径嘛,怎么样,我们都是有一个演示的限制诶,我们这有这演示的限制呢。
就会生成一个像爱理班一样的这么一个点扩散函数,这个时候是会引起唉我们图像的一个不,那后面还有camera shake,这个是大家可能特别是手机摄影里面最常面对的一种ber,就是在拍照的时候。
手不大可能像三甲将一样这么稳,所以说这个时候唉通常我们的一个手机啊或者是一个相机啊,通常是会有些抖的,这个时候就会产生整个相机的一个blog诶,我们去怎么样去呃,就做一个盲选盲区卷积呀。
或者是怎么样是dj做这个模式理论诶,这个后面会给大家一一掰扯清楚,后面就是cd不了就运动的物体,这个很简单,还有就是受限于透镜本身的一个,还有一个depth of fi的一个问题。
什么叫depth defocus,这种引起的不是,先说一下有这个途径设计加工,还有物理的一个限制哈,我们知道对一个理想的一个透镜来说,我们想要嗯就是物空间的一个点,屋面上的一个点。
我要想要呈呈现理想的情况下,我会在下面上形成一个点,对不对,无论是啊尾炎的一个光轴呢,还是在一个比较大的一个啊这to view的一个情况下,我们理想的情况下都是可以从下面的一个点汇聚到呃。
这个雾面的一个点,汇聚到下面的一个点,当然这个实际的情况下,我们真正的一个透镜呢,通常情况下我们一个点一个在路面上的一个点诶,到了下面的情况下会成为一个班对吧,这个没有办法,就是我们本身这个真实的透镜。
它就是这种性质,就是,在一个点在一个图像上,它不再是一个点,它而且它是一个呃这么一个模糊的一个班的情况下,哎我这个时候我图像拿到的应该是什么样子呢,就实际上我们最后捕捉到了一个图像。
通常就是有一种blur的一种感觉啊,就是最后模糊,这是它的一个直观印象,我们的一个直观印象,当然我们可以看到它这个和的大小啊,就这整个对应的这一个班,我们就说叫他不乐克隆,通常像这种情况下。
哎我们有这个shift verance,就是随着空间深度变化的跟不变化的两种波兰的核,那大家都非常喜欢这种不随着市场变化呀,会随着深深度变化的一个不是各种诶,当然这种很难存在哈。
就一般好像我们这种这个这种布莱克的啊,通常都是随着市场变化的,唉当然也有特殊情况,比如说像我们这个camera shake,一般在这整个画面都是随着一个方向啊,记不对,所以这个时候解反而比较容易。
当然说到这个length imperfection就是有透镜的不完美,就它大概有两个来源,第一个就是透镜的相差啊,那不考虑加工问题哈,有突进的相差,之前我们也讲到了啊,这种低级啊高级相差,向散场曲畸变。
子午会差不是会差诶,还有一些像那种就是彩色matic oration,唉,这些地方都会引起我最后图像了一个模糊,但是我们就很喜欢一些叫shift emt的一些呃相差,因为他这个最后底部的情况下。
我这个和就已经知道了,比如说举一个例子哈,比较讨厌的地方,比如像会差会查这个这种想法,就特别讨厌诶,我随着整个市场随着不一样的一个距物体的一个深度,哎我这个点头呢还是都在变化。
这个时候对大家解这个去补乐的时候就变得非常困难啊,所以说大家通常对这个会差是非常讨厌,非常反感,哎,除了这个本身相差的一个问题,衍射也是啊形成不乐的一个重要原因,比如说像就是我们左下角这个意思。
当我们有一个透镜口径比较小的时候,诶这个时候衍射效应就比较严重,这个时候大家也可以参考一下这个小孔成像诶,你发现这个小这个孔特别小,特别小的时候,这个光透过去,这个它不再是直线了。
它就会受到一个演示的影响,当你这个小孔成像特别大的时候,这个孔啊它最后成像也会模糊,对不对,所以说这个小孔成像啊就是挺鸡肋的诶,他没有办法无限的小,因为会受到衍射的一个影响,诶它也不能太大,太大的话。
诶这个时候就会有一个本身就是小孔比较大,难以在光,就不是延迟性传播吗,诶它本身,而且他自己哈口气都特别小,我只能通过那个小狗的光,所以说小孔成像啊就逐渐被历史淘汰了啊,右边那个就是啊。
举个例子就是平面波穿过一个比较大的一个一个孔,这个时候我们就发现诶这个整个波扩散的不是那么厉害,我们可以这么理解哈,它一个大的一个这个孔的时候,我们可以理解为上面每一个点都是一个小孔。
唉我一个一个单点我会产生一个球面波,经过也是会变成一个球面波,但是有这么多个点,就是这么多个球面波的一个叠加对吧,但是我们这个时候就会慢慢写的,其实屏蔽一下能量更汇聚一些呃。
这个会给大家后面做一个详细的一个解释,这个给大家展示了一个呃,因为这个衍射极限产生了一个ps,但我们不考虑这个这个情况下,我们不考虑这个相差哈,我们只考虑这个衍射引起的问题,这个衍射是被什么限制住了呢。
实际上衍射是被口径限制住的一种局限,也就是说我们的布洛克诺啊,大概就像右面长了一个像一个一个环一样的感觉,这个叫衍射环,这个有时候大家如果要呃这个也就是也可以,大家认为这是一个爱理班。
他实际上就是整个口径的一个分裂变化,就是这个关系也挺明确哈,因为像我们透镜都比较长了,你就可以理解为它是一个原厂的一个颜色诶,这个时候整个透镜的口径跟这个后面的一个bloco的一个关系。
大概就是一个复利叶变换的关系,这个这是单透镜的情况,多透镜的情况下,通常呃就是一个action,就是孔蓝的一个自裂变换,这个在后面的一些就是coded action的那个章节的话。
会给大家详细的讲解他们之间的关系啊,这个也不是特别难哈,但这里面嗯我们要给大家分享一下,就是演示的一些基础知识,就我们用这个弗朗和费衍射呃,来描述我们整个的一个就成像的一个过程。
因为本身大概分镜衍射是一个进程衍射,然后弗朗和费衍射是一个原厂颜色啊,这个具体的分界线哦,我记得不是特别清楚了,应该是你可以理解为大于100个栏目的,好像是100哈,我记不清了,大约100个兰姆达。
你就可以认为是一个呃弗朗和费衍射唉,这个时候你最后发现这个数量和分演示的公式啊,除去前面那一大串乱七八糟的一个系数,后面的真正的变带变量的地方实际上就是一个数列变换,你甭管它系数是多少。
后面就是一个数列变换,哎这个时候大家变得非常喜欢啊,然后第二个就是我们假设我们用的是一个非相干光,就是我们这个假设我们这个最后测量的光,它不是激光啊,这个时候就我们正常拍摄,他也不会用激光去照明。
当然也是这种,当然也有这种特殊情况,就像我们那个time of flight camera,或者是我们呃就是做这种深度测量的时候,我们通常是要用激光照明的,但也有一些结构光也是需要激光照明的,这是特。
殊情况啊,这个我们会在一个特殊的例子里面会给大家举报这个激光照明的情况,那我们考虑到比如说我们举一个e d的例子,就是我蛮地的defection,我们有这么一个呃方波吧,就是沿着中心轴对称的一个方波。
假设单位的一个呃单位高度的一个方法啊,我们做一个分离变换,首先我们做一个分裂变换诶,然后那个方向呢我们做一个自相关,我们这两个拿到了一个是什么样子呢。
同学们可以告诉我我们这个一个方波这么一个方做了一个穿复列变换,我们最后拿到的是一个什么样的函数呢,大家可以打在公屏里面去说一说是一个什么样的函数,然后我们做自相一个,方波做一个自相关。
他拿到了又是一个什么样的函数呢,对诶这位小朋友,这个三只龙哥,这位同学诶就可以快速的反应过来了,这是一个think方式,我们大家做自相关的自相关,就是大家也很简单哈,这个直接就是一个tt一个方程。
只要这一个方变成一个叫三角三角波,对不对,我们这个时候比如说我们对这个think function,就是我们给它做一个平方,这个时候拿到了一个图像,诶,跟这个三角波做一个分裂变换,诶我们可以拿到诶。
这个很神奇哈,我们最后拿到了一个function,就是整个think函数的平方,但这个实际上大家学过信号与系统,这个其实非常简单,就是频率的乘等于11的绝,11的长等于p的卷,对不对。
我们可以看到比如说第一个上面那个那那个分支,刚开始我们做了一个数列变换,来我们在频域频域相乘对吧,我们拿到了最后的一个sc的平方,下面我们是在频率先卷卷完后再分裂变换,实际上跟下面整个过程就是等价的。
当然同样的一个原理,我们也可以延伸到二维,当然我们可以想象一下,我们这个方波稍微大一些的时候,哎就是我们这个周期变得更长了,我们这个sc方式应该是变得怎么样呢,想象一下我在我的食欲里面。
我这个周期变长了,对不对,也就是这个x变成了一个,乘一个系数就成了阿尔法对吧,阿尔法x,然后这个think变成阿尔法x,有think的这里面变大了,也就是说这个就变成一个呃它的分之一。
这实际上就是大家可以看到哈,比如说这个阿尔法等于1/2诶,我这个时候我整个think函数就变得更窄,这同学回答的很对,在下面的呢你发现这个方波更宽的时候,这次点击它的整个三角波也变得更宽了。
实际上就是一个呃频谱展宽了,哎频谱展宽之后,这个这个不是啊,这个整个时域展宽了,时域展宽之后呢,我的频谱就变得更窄了,最后最后拿到了,一个think的一个平方实际上就会变成一个更窄。
哎大家加上我们这个更宽的情况下,我们可以看到这个好家伙,这个频率这个做了分离变换,频率里面变得更窄了,那我我们也可以想象到无线宽的时候,对不对,大家就这个阿尔法现在是1/10。
这个阿尔法变成无穷分之一呢,然后这个think就变成了一个dfunction对吧,也就是变成一个呃冲击响应,做分离变换之后就是一个冲击响应,然后呢,当然你这个无线宽之后,这个三角波也变成了一个平的了。
对不对,无论怎么自己卷也是平的,对不对,哎做分裂变换,平了之后还是一个呃德尔塔波,就是,无限假设这个泡沫无限换的一个情况下,但这种情况下,当我们延伸到二维,比如我们的口径是这么一个圆。
我们这个口径给自己做一个自相关呢,我们就会拿到一个像中间这一个不乐的一种感觉,当我们对它就这个不乐的,可能做一个分裂变换来,我们就可以拿到一个就是在飞机刚关非相干光照明的情况下。
诶这个ture就我这个呃action对应的一个点扩散函数就可以拿到了,但我们也可以很容易的想到我更大的一个口径,我最后的点扩散函数实际上就是越小的,就是我能量就越集中。
这个时候因为点扩散函数引起了一个blu诶就会更小,所以说啊有时候大家就特别喜欢那种超大口径的透镜,特别是在天文探测里面是吧,比如说我要看到一个几亿光年外的一个星星,这个时候口径就直接决定的分辨率。
因为其他地方的相差啊已经非常小了哈,这个时候我们整个望远镜的口径啊,就直接决定了最后分辨的极限是多少,当然像这种啊,因为就是衍射而限制的这种呃,defer就是要限制分辨率的,就也发生在显微镜里面。
就是大家显微镜里面通常啊这个有点不一样啊,这个显微镜里面是用一个new micro aperture来表示这个课程没讲过了,怎么样去提高显微镜的一个分辨率呢,所以聪明的人类就想到了汽油这种方法。
就我增加就我物镜跟我sample的一个之间的一个reflecting index,这个时候它的一个new map app就会相应的变大,实际上它的衍射极限就会有所提升,也就是他的一个点上班就会变小。
分辨能力也上去了,但有一些聪明的人类啊,甚至把这种方法用到了光刻里,就是我最后我那个光刻机做芯片的时候,要把那个图案投影到我们这个加工了一个违法上,也就是晶圆上。
这个时候也是有效的提高了一个new micracture,也有这种清叶的方法,这个是可能是90年代尼康提出来的一种清洁的方法,所以说那个时候呃这种制成啊,那时候紫光源不是特别好啊。
就大概是呃极紫外光源可能还没有做出来,大家想要通过现有的一个紫外光源来提高它的一个分辨率,也就是提高我正常能力,这个时候就会选择汽油嗯,来解决极限,还有这么一个问题,大家可以看到诶。
我把这个这个这个口径调大一些,我们就可以看到之后,分辨能力就有所提升,呃大家思考这么一个问题哈,我们为什么想要一个这种圆形的,一个我们想要为什么想要一个圆形的口径,这方的不行吗,三角形的不行吗。
右边形的不行吗,为什么大家更倾向一个圆形的这么一个app,大家想一想这个问题啊,这个方形的是不是也挺好诶,我加工一个方孔好像没啥问题,六边形呢也可以啊,大家想一想,就是我们是第几节课。
第二节课就课前给大家分享了一个新闻,就是我们那个微博万境,他的那个透镜啊,就是一个六边形的透镜,大家想一想,六边形的透镜最后成像产生了什么样子呢,这个为什么我们更加倾向于圆,而不是一个六边形的透镜。
对不对,再想一想,其实这个很容易呃,解答就是我们可以看到我们这个action对应的一个点开的函数啊,实际上大家可以理解为是一个带系数的分裂变换,我们一个圆形的一个分裂变换。
它还是一个就是这种中心对称的一种布料,当然我们像当然比如说举个例子,我们拿到一个这种方形的一个孔径诶,我这时候做一个分裂变换,他就可以拿到一个各项异性的一个点空调函数。
这个时候对大家去做底部链其实是呃挺不利的这么一个情况,就是他不乐能量,它在某一些方向哎太集中了,其实这个对后面视觉观感呀,还是后面处理就不是特别好处理,当然就举一些极限的例子哈。
比如说像我们这种十字形的这种点光的函数啊,右边这种十字形的点光的函数,在遇到那种过曝的情况下,就是有有一个灯特别特别亮,就我这个能量过于集中在x y两个方向的时候,就会非常引起周边的一些像素饱和掉。
这个时候对后面的算法处理是非常不利的,就是我那些好的一些像素被因为你这个饱和了,好家伙,这个最后大家都没法处理了,那圆形的啊,这个最后干扰的一些像素的一些额数量会更少一些,当然除了这个,比如像韦伯万境。
我们看到的是一个六角666芒星一样的一个地方的函数,这都是一个各项异性的一个bl的内核,当然在这个计算摄影里面啊,我们有时候也会故意的设计一些这种各项硬性的一个blo呃,来,就比如保留一些高频呀。
或者是一些什么情况下在里面对我们后面的信息恢复更加有利,当然这是啊另一种情况,这是我们故意设计,它是成这个样子啊,一般的话大家还是想要一个各项同性的这么一个不赖的内核。
诶这个时候大家可以看到我的一个actor圆形的孔径。
那个action,诶,这个时候我们其实是可以生成一个optical transer function,唉我们通过这个optical transfunction,就实际上也就是这个孔径在一个f f t。
实际上实际上是f f t啊,大家然后在我们这个相面上就是f f t平方,就是我们这个项链它只能并且只能这个拿到最后的一个intesting嘛,实际上是拿到一个整幅强度,这个时候有时候大家也叫艾米班。
这个实际上就是它整个成像的一个过程,我这个大小不可能的大小,就取决于我最后整个透镜的一个孔径的一个大小,还有行动,唉当然我们受限于当这个衍射极限的时候。
这个透镜啊自己啊实际上就表现为一个optical law fast future。
就是光学上的一个低通滤波器,就是我们受限于这个顶峰散函数了,我们在频谱里面实际上就是pp里面画了个圆对吧,就我们这个外面的一个圆,外头这个高频啊全都被我这个孔径给限制掉了。
就是说有一些高频的细节会受到影响,但我们这个怎么表示呢,其实表示也很简单,就是我有一个自然情况下理想的一个高清的一个呃这种图像诶,我经过这个套件之后,经过这个of table lost future。
我最后实际上就是跟我这个点光弹数相卷积到频域里面,就看我们两个频谱相乘,简单的一个点乘哎,就是就是它了,我最后就拿到了一个blue的这么一个图像,就我们17号就是blur的图像,我们记为b啊。
这个卷积核我记为c perfect,这个图像我们记为x就是我们要求的图像,我们观察到图像,我们在这个图像传感器上刮察到的实际上是b对不对,这个不列的一个图像,我们这个blocl呢就是模糊盒。
实际上也是可以通过一个标定的方法去来获得的,所以说这个通常情况下我们是知道了b知道了c,我们想要求的呢是这个x我们是怎么样去求他呢,但我这节课只是把这个呃formation列出来。
下节课我会给大家讲一个详细的解答方法,诶下面说就是第二个呃。
这个blog来源就是camera shake,就我们就是也就是相机抖动,或者是理解为手抖也可以,没问题,这是一个重中之重啊,这是本节课的重中之重,这个也是呃很多手机相机厂家做那些光学防抖啊。
或者是电子防抖的,然后都是为了解决这个camera shake的问题,说到camera是个本身我们会形成一个motion的一个psf,也就是我运动的一个点,换上函数诶。
这张图就给大家呃说出来了一个啊这么一个就整个motion的一个过程,大家可以看到整个纵向的轴,实际上就是我最后在图像传感器上积分的能量,它是一个跟什么相关的函数呢,它是一个呃速度分之一。
你可以理解为我这个特别高的地方向红的地方诶,我移动速度特别慢,我就是在这个时候我接他的时间更长,所以说这个地方会高高了低了,xy方向就是就是正常的一个空间空间分辨的方向。
所以说我们这个motion的一个点空的函数,运动的点空的函数,它是一个关于什么的方程呢,第一首先它是跟我这个motion的一个路径,就是我手抖啊或者相机抖动的一个路径相关的。
第二个呢它是随着一个motion的一个speed,也就是我整个相机或者手就抖的哪个地方快,哪个地方慢的一个函数,所以说我们这个纵轴啊,它虽然说是能量,实际上它呃也就是一个速度分之一啊,就是速度快的地方。
我这个地方能量积分就小一些,速度慢的地方,这个能量积分就多一些诶,它是关于这个数分之一的这么,一个函数,那我们实际的情况下就可以看到一个camera motion啊。
就是中间这么一个motion的一个情况,像这个地方就是速度比较快,我在这地方抖的时候速度比较快,他这个能量就少一些,像这些比较亮的地方呢,就我在这个地方抖动的比较慢,这个时候能量积分的就更多一些。
其实要是大家对整个就是物理学的多一些哈,就是大家会观察到,就我这个motion path是拐点的地方,通常是能量比较大的地方,就特别是变向我抖动变向拐点的地方,这个时候它的能量是通常比较大,的。
同样我们可以描述整个b乐的过程啊,就是一个呃就是一个干净的一个图像,x跟几个black kernel c卷积形成一个啊shake的一个模糊的一个图像,b实际上我们要求的还是这么一个。
知道了c跟b求这个x这么一个过程,嗯嗯大家直接从这个图像想要解他哎是不是不对,c做个逆卷积是不是就行了,当然这个情况下我们很多呃这种点击的过程中会有信息的损失,我们直接做一个节点机呢。
比如像维纳滤波通常会有一些不好的artifex,那这个时候我们通常是要加一些物理学的约束,就我们自然界的图像是什么样子,通过这些物理学的约束和同系的约束来来,最后实现我们想要的一个结果。
因为我们最后要产生这么一个ber的图像。
不是有可能有非常多的这么一种情况呢,就比如说我这个图像本身就是糊的,我这个布料看着好像是一个理想的点,我这个时候也会产生一个古乐的图像对吧,像我有这么一个乱七八糟的一个呃,就是能量分布的时候诶。
我卷积了这么一个大的一个盒,哎我也是可以产生这么一个blog image,对不对,那还有一种情况就是我们就真实自然界发生的情况下,哎我们这个非常清晰的图像卷积了一个呃布料的和。
这个时候我就也会拿到这么一个bug,实际,上我要解一个逆卷积的时候啊,就非常拿到非常非常多的一个flotion,就非常多的解解空间比较大,就我们可能拿到非常多乱七八糟的结果,不是我们想要的。
但是这种解空间比较大,它本身是一个一个病态的一个问题,就是他有一些信息的损失,我们要想要解出来这么一个病态问题,那个解空间比较大,我们要怎么办呢,实际上就是加约束,首先呢那加一些哪些哪些的约束呢。
我们可以做约束的地方有两点,第一个就是图像本身的一个约束,就是我们这个首先啊我们是想让奥姆的图像更加的像一个nature的,一个自然的一个图像,对不对,然后第二个就是我们的这个科隆。
因为这个camera shake引起了克隆,它应该像一个motion p s f,唉我们是用这两个b来去进行再进一步的抽象,我们就可以拿到根据这两个我们这个方向来拿到他的一个图像约束。
进而来约束最后的一个解空间,就是我们考虑到这个自然的一个图像,就我们自然图像会有一个什么样的一个情况呢,这是一个红色的这个图像,红色的这个曲线是自然图像一个鬼脸的一个分布,我们可以看到这个横轴啊。
就是我这个整个图像的一个规定的一个值,我们自然的图像通常是一个比较长的尾巴的,这意味着什么呢,就是我们这个统计的一个指的就是就是我们有很多高频低频的地方,它的一个分布规定只是小的地方当然是比较多啊。
因为我们本身这个就是比较sparse的一个图像,当然我们在一些鬼脸特别大,就是梯度特别大的地方也是有值的,那这个时候有时候有时候也会把这个呃标记为这么一个,嗯标记为这么一个hyperlaution。
就是就是hyper拉伸的这一种表示,就是这个图像这鬼点的一个方向,大概是一个0。8的这么一个一个hyper拉拉伸啊,说到这个hp拉伸啊,这本身的这个,拉普拉斯的分布是怎么样的呢,就给大家画了一下哈。
这个本身的一个拉普拉斯分布啊,它大概就是,这个这个是x你可以理解为一对吧,当然你要像这种呢,就是,这二阶的那我们要本身啊,像我们这个规定的分布大概就是一个0。8,这个叫hp拉拉。
但是我们也可以看到就是我们不认的图像,它的一个不点是咋分布的呢,因为不乐嘛,我们会有一些高频的损失,特别是一些大的鬼点头就会被模糊掉了,所以说我们在特别是一些比较大的一个规定的情况下。
我们这个时候通常哎我们这个统计值就会有点衰减,实际上我们最后要优化的一个图像的目标,就是我把这个蓝色的这个br的一个图像恢复到跟这个sharp的图像,sharp的自然的图像,这个红色的分布曲线一致。
这个曲线响应大概是0。8哈,是从很多自然界的图像中统计出来的,就是大家就认为这是一个自然界的规律就好了,所以说我们从这图像本身的一个角度出发。
我们这个整个图像的拐点的分布啊,也就是我最后的一个hla的一个约束,也就是呃round x0。8这么一个,这么一个约束,然后考虑到最后的这个点cos函数呢。
就我们要让我们的这个点风散函数更像一个motion kernel,首先一般好像我们这个手抖的地方,它是有一个路径,实际上也就是在我们这个路径上,每个地方划了一条线,其实我们像这种布莱克诺啊。
一般它都是有一个稀疏的一种情况,因为我就是在一个面上画了,在一个呃运动的面上画了几根线嘛,就是我这个点它就是都是线,所以说这个时候它本身应该是稀疏的,这个时候是可以作为约束的。
哎而且第二个点呢就是它本身是连续的,我抖嘛不可能中间会有断断续续,我这个相机啊,它的运动的一个过程肯定是一个连续的,这是第二个对这个kindle的约束,然后第三呢就是我们因为它是一个速度分之一的函数。
就是它没有负值啊,它都是正值,所以说我们就有了从图像上这个层面,还有从这个brother ko两个层面的约束,但是我们用到这些information,我是怎么对这个图像最后来实现了一个嗯。
就ban就是decaution呢,这个时候我们该怎么办呢,哎我们从先从统计的地方先说一下,这个还是先说一下这个整个的一个image formation。
就是先假定我们最后图像传感器上观察到了这个ber image,我们记为b啊,blur kernel就是c,然后sharp image就是我们要求的一个x,实际上是我们已知这个不断克隆跟b的情况下。
就是我们观察到的是b,我们要估的这个值就是x观察到了b,我们要估这个x它是一个关于什么的函数呢,首先就是我们可以把这个理解为,首先这个把这个把这个前面这个概率拆分,我们就可以把b估出来。
这个是最大自然估计,也就是本身就是data term的一个约束,就是我们这个普莱尔玩的图像要跟sharp image叫对应上,就是我们这第一层关系,然后第二层关系呢就是整个图像传感器。
就是整个自然图像它自己的一个约束关系,也就是image prior,就是我们刚才讲到从image那个层面就给他建立了一个约束,那第三个呢就是我们从这个博乐克隆来建立的三个约束,他第一是他是啊永远是正值。
第二个就是它是稀疏的,第三个就是呃这个是连续的,这就是不乐方向的一个prior,最后我们怎么样去把这个方程建立起来呢,实际上我们最后要解的一个方程啊,我们在图像传感器上诶所拿到的就是一个,不料的一个。
b然后我们这个c也是已知的,然后我们要求的就是这个x这就是我们的一个dterm,那么有时候也叫data facility,就是无论我观察到了b啊,我这个要求的x跟这个估出来这个bloco做卷积之后。
这个时候他一定两边要相等才对,要是不相等的话,就说明我们要求的这个latent image x就是有问题了,那第二个点呢就是一个hp拉伸的一个约束,这个它是符合一个0。8的一个分布。
也比较符合就是自然界的图像的一个分布啊,这个当然有时候大家也会说是0。5~0。8哈,当然大部分就是默认的情况下,0。8是最好,那第三个呢实际上是啥呢,为什么让这个c最小呢,实际上c就是不带坑呢。
它本身是稀疏的,这个地方我们只呃做了一个稀疏的一个约束,因为可能我们要再加一个那个连续性啊,这个这个不大好解,这个这已经挺复杂了,这个这个时候解的时候一定要已经要把他这个拆做迭代,然后再解了。
我们再加一些东西,可能就就就不大好解了,所以说这个时候通常人们也会有选择性的忽略,当然我们这个每一项对应的这个我们已经讲到了,当然它在就我们刚才那种图像里面,它应该是怎么表示呢。
就是我们的data term,就是意味着我这个sharp的一个image,我这个dimm就给他这个shop image跟这个我估出来的这个blocal,就做一个卷积。
就会拿到一个buried image,然后呢呃同理就是我们第二就是nature image pro,就是自然图像的一个呃这一个呃分布诶,为何如何获取c啊,其实这个c啊在我们解的这个过程中,他是不知道的。
就是我这个c跟x都是一个变量,我要解这个方程,我要同时优化x跟c,所以说就因为x这个c本身是稀疏的嘛,我们在后面加上这么一个运动项,我们最后来求解这个就是这个cost function的时候。
我们是把这个x跟c同时解决出来的,所以说这个我们在解这个sharp image,同时也把这个c估出来了,然后这个斗六八同学问图像辛焱为什么可以这么加约束,因为它自然分布确实就是这个样子。
因为我们加了之后,这个就是符合它本身的一个自然界图像的一个统计规律,这个时候我们是可以把它加进去的,来,大家可以理解为,连续性约束可以用lost box表示出来,比如说啊大家要求这个你可以求一下。
就是这个整个uber color每个点沿着它就是法线,就是它那个法向量的一个连续性诶,这个时候如果不连续的话,这个地方也是可以表示出来的,当然这个时候就不大好解,有时候加这个就是这种系数性的已经够了。
你再加多的话,你就可能不收敛了,这个我们也经常遇到这种情况,你就解着解着乱七八糟东西加多了你就不收敛了,这个就就不大好,所以大家理解为这个nature image trial,大家可以看到就不认识图像。
它通常一些高频就大的规定的会有损失,然后这个shop图像呢就是它一些大的规定呢它是比较多的,大家加这个约束,实际上就是把一些不利的地方,它那个对比度强行拉上去了,可以这么理解。
实际上就是整个对比度进行增强,所以说啊,为什么我们要把这个蓝的这个blair的一个分布曲线,拉到跟这个shop里面的一样,是不是,然后同时这个时候呢我们前面又符合这个data term。
data pdity,这个时候就可以解出来一个比较好的结果,但我迭代的过程中也把这个布莱克l也给解出来了,后面下节课我会给大家详细的讲解这个这个这个优化方程怎么解啊,这个cos方程到底咋解。
那我们来验证一下哈,然后我input的一个图像长这个样,是不是我们只是简简单单的做一个就解解卷积的时候,比如说,只是做一个就是deconclusion,这个时候我们可以看到做一个简单的地图。
我们不加任何约束,可能看到的呃,这个非常难过啊,这个就各种artifact都解出来了,实际上也就是我们最后想要勾到了一个物理模型本身啊,就是这个bloco的模型跟这种真实的长得不太一样。
这个时候我们这个整个受约束的一个cost function这个目标函数啊,就会呃很好的解决呃,这上面的一个artifacts的问题啊,实际上就是它让它更符合自然界的一个分布规律。
大家可以看到这个呃这个inverse laws,就我们这个cost function的,就跟那个pixel dency diy的一个关系,我们可以看到我最优的一个解啊,就inverse lose。
这个就是cos方cost方式的分之一,这个点实际上就是它的一个第一个最优的点,我们可以可以认为嗯它是一个optimal的一个速度,也是最佳的一个c跟x解出来了。
当然啊我们也可以看到我们最后这个pixel intense,就是像素密度更大的时候,我们也会就可能会产生一些不好的一些解啊,就是解出来各种各样的artifacts。
所以说我们这个有时候有这么多解的情况下,我就不好办了,不办好办好了,就是这个时候咋办呢,实际上有时候大家就给出这么一个方案,对那个是最大值,那不是那是分之一啊,cos分之一实际上是最小值。
对就这对这个cos function来说是最小值,所以说有时候有这么多解的情况下就不大好办,这个咋办呢,就是有时候同学们就会就是会想到这么一种哈,就是我不太好对这个极值点直接拿到。
我就干脆搞一个wet average,就我对这各种各样的一个solution哎,做一个简单的一个加权的一个变换。
所以说我们可以看到通过一个我们通过一个加权的一个变换,我们就可以拿拿到一个比较接近最后一个真实的一个kernel的一个情况,所以说当然这个也不是特别好哈,我们这也是没办法,你不大能确定那个值是最好的。
所以说你这时候做了个加减变换啊,加权的一个相加,就是拿到一个呃不是特别好,也不是特别差的这么一个结果,所以我们对这个这artifacts本身啊。
还有这个最后布出来的那个盒,他有自己有非常多的一些呃对应关系,比如说举个例子哈,像上面的一些就是本身我们最后估出来了一个block对吧,下面这个呃实际上就是我们最后对应的一个image pting。
大家可以看到啊,这各种各样这个布莱克隆产生了一个图像是啥样子,然后另一个来源呢就是我们说到第三个呃。
这个motion这个blog来源就是整个motion blur,就是就是场景object的一个运动的一个问题。
但这个呃就非常经典了,就是当我们就哪怕是我在理想情况下,如果把这个相机啊干脆就固定在那,就我用一个三脚架固定在那诶,这个时候但是我那个曝光时间比较长,因为有很多像拍电影啊,你这个时候我就是24帧。
每一帧曝光时间就那么长,诶但是我这个运动速度比较快,就会有一些motion b到,特别是我们舞台表演,左边那个图是我们一个舞台表演的一种情况,诶这个时候就发现这整个人都模糊掉了。
当然这个呃模糊的路径呢也会跟着这个物体运动的路径而变化而变化,但这个smotion是比这个camera sh更复杂,因为我不能限制这个整个c像camera一样,它有一个固定的一个不认路径对吧。
像我们人体它有比如说举个例子哈,有人呀脑袋呀,手啊,这种身体啊,你各个地方运动的一个方向都不一样,所以说各个地方都会产生对象的不认,这个地方是比较棘手的,所以说通常大家会分派式去做这件事。
也就是估一下在不同的一个位置,我最后的motion kernel到底是怎么样的,哎所以说在有些时候大家也会想到这种h264 h2 v265 编码。
我们也是要把这个motion reaction都算出来了,这个有很多底层图像处理啊,有非常多的相同之处啊,右边这个是一个呃这个这个开球的这个motion ber,就大家可以。
当然从这个motion pl大家可以看到哪个球运动的快的,英军能慢,这个也是一目了然。
那最后一种不论产生来源呢,这个大家给大家之前讲过哈,这个是叫因为景深引起了一个呃defocus的一个问题,这个有时候也叫autumn focus bar。
让我们回顾一下这个auto focus blog是怎么产生的,比如说像我们这vocal plan,在这个focban上,我们理想的一个点可以在我最后的双向传感器上形成一个点。
但是我们把这个物体放得比较近的时候,我们在这个图像传感器上就形成一个弥散圆,这个弥散圆我们把它称为这个circle confusion,他这个离散元,当然这个弥散盐只要不超过呃一个像素的一个大小哈。
这个我们还可以认为它是清晰的,所以说呃这一个像素在前面跟在这个focal plan的一个前面,跟后面对应的两个点之间啊,我们就可以算出来这个景深对吧,当然对应的我们也可以啊。
根据这个弥散圆的大小把这个胶真给算出来,这个都是呃跟那个像素,跟前面这个口径和息息相关的这么一个像,这是另一种情况,就是在交钱交货,我们可以看到都会形成这么一个呃focus of blur。
这种就没有办法,这个是所有的透镜都会有这么一个谨慎的问题啊,这也就是out of the fox的一个问题,这是我们之前一篇文章里的图哈。
像这个so lab,第一个是so lab的一个啊非球面镜啊,他是啊其实也是比较好的,单投进了基本上算是是一个非常好的一个单透镜,就ai i50 ,我们对焦的地方,我们看到1米的地方。
它呃有一个非常小的一个点光的函数,能量非常集中,也就意味着我在这个1米的地方,我最后看到的图像是非常清晰的,但是哎在不同的一个对焦位置都会产生一个不一样大小的一个bloco。
同理的像呃我们这种ac 254,它是两个非全面镜的一个组合,特定啊表现稍微好一些,稍微好一些啊,无论是呃对这个胶面还是一个就离交的一个位置都是比较好,但也没有特别好啊,这0。5米跟1米的地方。
大家看到这个布料都非常严重啊,这个颜色也不是变哈,它是这个能量是不一样的一个波长,它对应的这个点光的函数就会有变化,而后面我们其实当时是设计了一个嗯这种一个景深延展,一种透镜啊,这个但是目的就是1米的。
看着更不清,这是啥意思啊,哈哈当时就设计了这个景深延展透镜,也就是让中心的能量啊,就也不能说一样好吧,就是各个景深一样坏,但是我这么坏的情况下,我这都能解出来的,那这个文章那时候是21年发表在cpf上。
就是端到端的一个复杂透镜的设计,当然我当时我们是用这个呃米苏吧兔呃来做一个deep reducing,就是说这个时候嗯大家就可以啊,用这套工具来直接用物理模型来设计这个整个复杂的透镜。
那这也不会有一些像我们之前工作呃,有一些像单单词的衍射透镜啊,那个时候通常就是禁酒啊,单面啊,这,个时候我们就可以对复杂透进行设计,这个时候也就是一个对一个谨慎的一个应用。
大家有兴趣的话可以自己去看一下。
我们desu default本身啊在我们日常生活中非常常见,就我们比如说简单了下左上角,我们各种各样的小小小灯泡拍成一个点,有时候叫broken,这个大家在摄影领域啊,非常喜欢有这种聚焦啊这种感觉。
实际上啊这个虚焦可以强调本身物体啊,在我们这个场景里面的一个重要性,这个时候它本质上就是啊我们这个tax defocus的一个问题,就是我对焦的位置是清晰的。
李教授这个模糊大家爱摄影的同学也会经常看到诶这么一种画面,大家尤其是嗯拿着手机或者相机拍一些近处的一些花呀啊,或者是,那个小虫子呀,或者这种情况下哎。
这个时候都会有这种很明显的这个呃depth defaults的问题啊,这个有时候当然也特别是一些微距透镜,可以拍微距的,这就叫marco length,这个length可能会比较贵。
支持mark lins的一些途径嗯,反正大家买手机会买买买买这个呃相机的时候就可以注意一下,maro lx是比较好的,比较贵,好今天的课程就分享到这里啊。
主要给大家分析了整个emmamage bro的来源,也就是从两个方向,第一个就是我设计跟我设计的相差,跟我加工出来产生了一个图像偏差,诶。
第二个就是这个衍射极限比较重要的是camera shake这个问题,camera shake啊,因为手抖这个每个人就不大可能太稳哈,这个手不大可能不抖,就是就是哪怕没有帕金森这个手他也一定是会抖的。
就是说camera shake一直也是呃手机跟相机领域呃主要解决的一个问题,这个我们也把它整个image formation约束,也就是符合这个呃拉普就是hyper拉拉的一个分布这么一个约束。
第二个就是本身我们想到了这个bloco的约束,布洛克呢有三个约束啊,第一它是sparse,这个是我们用到了,还有两个没有用到的,就是没原料的,两个约束呢,就是第一个就是它本身是连续的。
然后第二个呢它本身都是正值,但这个就不太好解了,所以说有时候大家加一个sparse就够了,当然也会注意到一些实在是不大好找到最优解的时候,我们就可以呃换一种方式,就是搞一个权,重的加权来。
最后实现一个差不多的一个比较好的一个结果,然后就是same motion smotion啊,本身解法啊,这整个这几个这这这几个步骤啊,最后嗯最后解的都是一个这么一个卡普拉普拉伸的一个问题。
最后就是depth of default,这个也都很常见,当然我们实际拍摄图像的时候,正常情况下我们都是所有的这种motion bro,这种各种各样的不都混合在一起,那这个时候大家就会变得非常难受诶。
在拍照的情况下,本身拍照摄影啊,这种情况下本身还会有一个噪声的影响,哎我这个噪声跟这个b乐一起出现的时候,诶这个时候又会变的故事又变得更不一样了,假设我这个图像信号非常小,这个时候又有陌生不乐。
我最后不论那个过程我都不干净,都受造成影响了,在这个时候就解起来就比较困难,所以有时候夜景视频啊,为什么现在呃这个手机做的或者是相机啊做的都不是特别好,就是暗夜视频这个问题就是魔神不热噪声啊。
各种各样的问题就是都不是比较难解决的啊,这个sparity对sparity是用直接用这个bloco的一个l y nm来约束的,就是让他的一个l one norm最小,对同学们有什么其他问题的话。
也可以问一下。
啊今天是控制的时间比较好,没有超时,大家有什么问题吗,所以刚才呃课堂上大家问了非常有意思的问题啊,d r t加rt是啥,对墨水里边感觉效果哎现在做了嗯是都不大好,这个也没有很完美。
这个本身是一个病态的逆问题吧,啊可谓光追啊,可谓光追,这个没有开源,这个已经有一些商业化的一个应用,那我们会准备呃后面一些呃更成熟一些的话,会开源的磨合的物理尺寸,这个不好说,嗨这有的人手抖的厉害。
有的人手抖的就是小一点,这个最后模糊盒有可能会几百上千个像素,嗯相机做那么好,其实也是改善了每个人的一个生产生活方式,就大家真正的迈向了就是全民拍照的一个时代啊,大家想象一下。
我们当年就是小时候你的10年前啊,拿这个诺基亚拍照的时候,那时候还有不止诺基亚金立语音王,那个像素估计可能得有10万,那个时候拍照能拍出来的东西就行了,当然随着时代的进一步啊。
整个对相机要求是实际上是越来越高的,大家实际上想要的是一个跟自然界一样的一个体验,就我在家我的一个取悦我自己的眼睛,取悦自己的大脑,让大家更开心,相机做的更好。
对普通人还是还是很大程度上提高大家的幸福度吧,呃实际镜头的p sf啊是怎么测出来的,这位同学问这个,这个有非常多的测试测试方法,比如说你搞一个点阵。
当然你看这个是呃就是镜头的p s不是motional嗯,比如说搞一系列的点阵,不同市场的一个点阵或者不同深度哎,搞一些这点阵的一个光源,然后就直接拍到啊,这个图像的一个点光的函数。
这个时候是可以直接拍出来的,但有的时候还有一种另一种玩法,就是我整做一个大板哈,每个板都是一个二维码一样的一个随机随机班,这个随机的这一个二维码就会产生不一样的不认,然后我们在呃我们已知他的光柱子嘛。
我们就可以把这个不是求出来,这是另一种方法,我感觉这个后面的一种,方法可能会好一些,因为我们这种有一个点阵的时候,通常会受限于这个相机的一个动态汉化的问题,就是他有时候不是特别准啊,不是特别准。
用啥server做minimization,minimization,这个是呃有很多sa哈,大家可以用这个half queting啊,也可以用这个a d m m,也可以用这个prom operator。
这个我们后面的课程会都会涉及到,嗯纯z max算的p s f,实际上你最后你发现你设计出来加工的多好,和你实际的p s f也不一样,实际上z max算的是,但是这max本身这个工具还有没有点问题啊。
他算算那个p sf,你的光线少了,可能确实不是特别准,而且他算的这个p s f它是通过三个基准波长来算的,它并不是像自然界一个连续的一个这么一个波来算的。
实际上它是呃跟我们真正的就是自然界里面拍的p s是有偏差的,但是我们不一样的光源,它的p s f也不一样,因为不同光谱它响应的一个点开,它的加起来它是不一样的,所以说你是硬说z max吧。
跟自然界里面都不一样,不一样的光源,太阳底下太阳光源啊,灯光啊,照着这个ph都不一样,所以说这个问题是挺复杂的,当然你要最后解不了,就说有有些同学想可能问那个z max算ps s f。
可能是呃想用这个the max仿的p s f去解底部,那这个时候我们发现这个解的都不是很好哈,就跟我们外界真正的拍照那个p财富还是有一定的偏差的,同学们还有什么其他问题吗,对这是spectrum。
是其中一个问题,但实际上最后你做出来那个p s后稍微新偏一点啊,或者是招牌位置偏一点,加工精度差一点,他最后都不一样,最后竟然很多时候仿真跟实际情况,大家做的时候就发现做实验的时候老是结果不是特别好。
他对各种各样的问题,spectrum是它本身仿真上就不准了,然后还有就是加工的最新的一些问题,就是很多非球面镜讲到这个非球面镜,就不得不讲到这个他们加工这个问题哈。
这两个非球面镜最后这个中心轴啊稍微有点偏差,那个相差影响千差万别,这好家伙在最后怼很多片的时候,又会有更更麻烦的一些问题,就是手机里面哈,我们这每个面基本上都是非球面。
就是说这个手机镜头它的一个加工对齐还是比较精密的,我们是每加工每每这个装配一个就一个镜片,我们是边装边测,边装边测哈,他不是一次性装好再去那个是要不然就不大好弄了,但是像我们一些相机镜头。
通常还是以球面镜为主,球面就不需要对新装歪一点,可能影响也不大,但大家还是尽量的让那个主光轴转一些,这个还是转一下好,同学们还有啥其他问题吗,好现在没有其他问题的话,今天的课程就到这里。
再次感谢大家来到games,204下节课会给大家讲一下deep这个问题啊,这同学问我自己磨过镜片吧,这磨过的这个可能也不是很准,那时候是那种,但我自己只磨过这种球面镜啊,就是非球面镜。
基本上都是那种单点金刚石车去车的或者五六机车的free form的,哎这个同学问的很有意思啊,这个free form的啊,这个镜头优化这个这个解释更多的哈,这本来你像非球面镜,你优化的时候就已经是很多。
这这不是不光是追求命令,哪怕是球面镜最后优化的时候,基本上就是一个玄学了,就是你这个顶点的位置啊,这个时候他都会有非常多的解,因为我们整个就是光学系统的优化,就考虑到我们三维空间的一个分布啊。
它本身就是一个非常高度的非线性的一个优化问题,就你要是优化了这么一个随form的透镜,它更是一个这么一个非酋这个nonlinear的一个问题,所以说最后他那个无穷解啊,你可以理解为这个无穷解的n倍。
他会有更多的一个解,当然这个时候也会这么优化,也会有更多的一个要求吧,所以,通常大家优化这个free farm的时候,就会加各种各样的约束,就是根据我最后想要的设计的目标来去加他的约束。
也也有时候也会根据加工的一些能力来设它的约束,同学们还有啥问题吗,对你说的free fm,这个我还想再扯一点哈,就现在工业界就很多厂家在尝试对这个free fm进行量产。
但是到最后可能现在大家良率都不是很高,也就是目前为什么,就是free form并没有在大家日常生活中大规模应用的一个原因,特别是一些不对称的一些free flength,这个加工起来是是比较麻烦。
同学们还有什么问题吗,好既然同学没有问题了,再次感谢大家来到gx 204,好,谢谢大家。
14.去模糊与成像逆问题剖析 | GAMES204-计算成像 - P1 - GAMES-Webinar - BV1Xd4y1C7v3
它是一个比较经典的一个优化的算法,这是我们给这个优化的例子呢,就是我们上节课讲到了这个,你们不是说我们有讲的布拉德一个极大成功嘛,还有一个bassical limit带来的成功,嗯还有像呃这个手抖啊。
或者是物体的运动带来的一个fla,那当然还有它本身其他其他的那大气散射呀,或者是接着闪,也有可能一起主要的这个,但是这些所有的问题啊,纠结下来就可以呃把这个information给它写出来。
哎最后我们再让他们现场处决到我们这个信号啊,通过我们这边的手段,你去求解个密问题,是可以把我们想要的一个肯定的信号比较好做的啊。
今天我们就从这个最基本的一个优化的一个手段叫have the relemon来入手,来给大家进入啊真正的一个密问题的一个阶段,首先呢要给大家呃分享一下这个比那个宠物省的一个历史嗯。
然后再给大家讲一下整个我们这个mage formation,怎么样把它用一个半月出的一个protect来描述起来,这个这个我们这个成像的一个问题,然后描述用这个翻译师啊,贝叶斯来这个描述完之后。
我们就构建了这么一个inverse problem,哎但是构建是我们跑五不能,我们会发现比如说到一些噪声啊,或者一些呃其他的一些不好的一些因素影响你想要解这个应问题,经常会有一些很低pose的一个问题。
就是我们写的问题通常都是动态,那解这个病态的问题呢,诶而且同时啊我们还会遇到我们最后要点一个cos function,这个时候我们就需要一些and nutria。
或者是呃一些我们learning fire来做一个衣服,而且今天给大家科普一下这个呃本身形象的一个bug,还有规定的spy来讲,比如说要要符合蘑菇,可以加个拉普拉斯的一个优势诶,还有这种么样的一种约束。
这个是可以先帮我们限制几个解决金,哎,最后通过一个up for that me,哎我们把这个linux conversion的一个例子就呈现给大家来,再加上本身一个后面的噪声。
唉通过这么一个例子就可以给大家解,到底我们这个里面formation怎么写啊,加一个那个微信符合怎么解诶,这个它是一个比较通用的套路哈,希望大家把这些套路都掌握好以后,你要再介入什么物理模型啊。
都可以很轻易的把这个套路套进去,然后最后求取到我们想要的结果,来设计这么一个单机,啊这个是从我师兄golden vp那借了很多live,大家可以关注一下这个funch。
首先呢要给大家讲一下这个mad conclusion,说到这个类似长5t像我们通常我们的图像传感线上达到图像,其实通常镜像左右,那首先哎我们这个经历了各种各样的一些不乐的因素,我们这个图像就变得模糊。
同时呢你传感器我们知道我们也分析了一个传感器上的一个教程,我这个有这么要,同时呢我们之后拿到了一个图啊,就是又有模糊,又有造成干扰的这么张图片,但是大家想要的是什么,一个可能大家想要的一个结果。
而往往是我又要清晰,又不常含有噪声,这个问题怎么解决呢。
其实,大家就可以通过一个媒体conclusion的方式,而同时啊我们首先啊我们通常观测我们在同样成长身上的观测,比如说你把它记为b这个b啊,还有噪声,还有不认我们这个干净的一个图像呢。
就2d里的插图以及,然后这个c呢就通常就是我们所说的布洛克,就是我选择不乐的过程和这个c最后呢呃通过这么一个noise啊,今天只给大家提供一个ng诺,夏节课会给大家设计一下波斯诺。
这个时候就我们整个靠方程要稍微给你普通方程来稍微讲一下啊,但这个整个套路点套路都是大差不差,最后呢我们呃首先规定一下我们的max formulation model,我是一个flag。
图像通常就是一个convolution,就是一个不好的一个不乐盒吧,这个c跟我们干净的图像进行一个convusion,最后再加上一个告诉,然后呢呃其实我们这个也可以把它的频率去解一下,这个这是剪辑啊。
这个体育的那个时域的卷就等于个体育的乘,对不对,我这个把它做分离变换,变成简单的相乘,然后再给它逆回来是吧,所以这个一二这个问题是相等,我要求解这么硬性问题呢,就我们已知b然后已知c我要求减x。
大家有时候放到平面不考虑噪声了,这个确实是直接诶或者两个频率一相乘,再做一个reverse变换就可以拿到我想要的这个x我的xp的一个好的,当然这个就不考虑造成了,但是你不考虑噪声。
往往会有一些呃非常不好的结果,就是我做个造成一点,我有灵敏,这时候咋办,唉这个问题就变得嗯就很难过很难过哈,就最后你没有这个有噪声的情况下,你最后啊求解这种机密。
就是你vertising的时候就会提供非常差,所以说呢,20世纪父母年代就大概嗯这可能是80年前了哈,有一个叫维纳的一个老哥哎,另外一个维纳利波,他是它实际上还是求解一个最优的一个电竞方程的一个解。
但是呢这个时候我们要考虑啊这个噪声的,把这个音噪声,然后我求解了一个本身实际上也是处理一个正常情况嗯,最后我们就可以拿到带屏蔽的一个点,它是跟一个造成相关的一个分解的一个办法。
然后在评语里面我们知道b b妹子就等于c或conclusion,跟这个就是一个干净的,就像x和conduct,然后呢我们有时候也是可以把这个c啊嗯写成一个微型形式。
很好表示写成一个大飞机用的mation的表现,来举个例子,比如说我们做这个五分基础问题,就我们考虑到光柱是左边的一个非常干净的这么一张图诶,我们在直角三角机场就是拿到图呢,假如说没有造成。
这也是非常干净,但是只是有一点不认,这个时候我们是做一个简单的一个呃revertising,这个时候我觉得这个平均值也相同啊,我们就可以没有弹幕干扰,我分析拿到非常干净清晰的。
但是呢一点点造成的干扰就会使我们结果变得非常坏,但我们这个噪声大的时候会变得更坏诶这个时候就怎办呢,这时候就是聪明的人类,就是我们提到了一个1940年那个时代维纳斯的一个维纳,就我们把这个噪声也考虑到。
直接让我求解问题的时候,就是呃我求解,我这个对我要预估了这个tag,然后跟我自身的一个让他data facility,其实要尽可能的一些相对啊,这个也是我们后面啊求解,这个也是非常一致的。
五维纳滤波就很好的解决这个问题,就哪怕有一点点噪声,哎我这个听过这个维纳滤波也是可以比较好的,分不出来这个形态当然也不是特别好,它还会有一些模糊,因为它毕竟还是一个病态的命令呃,这个sr又低呢。
就我实际上我最后我们可以从这个直接可以从这个公式观察到哎,生来越高对吧,我这个价非常高,加上无限高这一项一项就是零,对不对,这枪就是零,我们这个上下都是一消。
实际上就是一个很干净的一个就很干净的这么一个图了啊,这个s a r走出了这个西格玛像相机的噪声,我们是有专门的专利方法,就是像拍这个这个灰度卡在一个基金照明下,有一个过度卡的增加的百分率。
哎我们就可以像上节课之前我们讲这个来进行,然后像一般这种图像的,他这个噪声啊,这个这个噪声是我们自己家的这个呃虽然我们自己心里有数,对sr让大家直播间有时候要真的犯法。
就是很多时候就直接不考虑它的一些像按电流啊,就是直接减掉了,我就考虑后面x no,然后就拍了很多张avg一起之后,拿一张的一个图也要去归这个公主来听啊,像这个也都不是很懂,你要用沽的话嗯。
其实也不是特别好这个,但我们看到这个sr角的时候,在底下这个就是变特别大,所以说我们这个分母变大之后,这个实际上就意味着模拟一些,平面的种子,这个时候我那个blue就会没有办法,所以说特别好。
那这个是跟sn啊给我们信号的一个新道具新相关,所以说呢我们这个mac cot是什么本身啊,它是一个静态的一个应用,就是我们会有非常多非常多的一些血来满足我们这一个因素条件。
所以说这个我们还想加一些另外的因素来使我们解就更加好看,更加复合,自然还有甜美的一些规律对吧,这个时候我们就需要加一个room叫in pri,就是实现图像的一个约束。
我同学们也会经历很多自然界统计的规律啊,或者是自己人经验的一些规律来建立自己的华尔,那我们要求解这么一个例问题时,我们要想想要把一个它一个概,把它描述成一个概率统计模型,就把这个英文写。
然后一个概率数据模型我去优化了一个视频,诶最后我们要怎么样,你慢慢说起来,我们要求解一个问题的,就是我们有没图的,这种就是在我朋友身上拿到的一个b就等于一个a x加斯塔,a就是我们所做的一个mit什么。
这是我真实的一个呃信号,通过我们的相机系统哎,这个时候就a a可以是不乐啊,也可以这些变换,这个时候那就经过一系列的测试信号进行,通过一系列的变化,或者是congo那样再加上噪声。
实际上就是我们最后的几个可能性,mod通常大家都写成一个ax加上一个道上的一个效果,其中的s就是我想要的粗炮,它是符合一个就是这个吧,是你的一个这个没,有造成这款是零的一个。
那么就有一个加上方向有一定的理解,然后伊特呢就是一个造型,白道是他是帮他和西格玛方的西格玛的一个白道,fla呢,就是我这个信号经过这个a的一个a的一个象征系统的一个调试诶,然后再结合这个噪声。
就是我们这个最后拿到了测量传感器,拿到了一个它的一个分析,我们的一个observation,就是我们观测到的一些东西,实际上是定语是吧,唉当然我们是在一个condition,是在x跟西格玛。
这个时候我们就可以把这个你最后拿到这个币啊,就是我们观测的地,实际上,是符合这么一个高度分布的,然后每个像素我们都结合起来,就是把这些东西都调成就,最后达达到我们那个整张图上。
它的一个观测就是它的一个连成,哎我们就发现我们的这个根据这个3月入了我们这个最后的一个pcr,我们实际上观测到了b我们要铺x对吧,这个西格玛就知道了,这噪声是知道的,因为这个我们先把这个噪声铺下诶。
这个把他这个拆解出来,你就可以找到之前弄一个qb,然后是根据我们的观测,根据我们的观测b然后paptional哎,对我们这个pd condition s是什么p s后面呢我们这里通常就要跑二诶。
这个时候我们是想要通过一个最大自然估计啊,就是我们想要让这个呃概率最大,对不对,实际上就是让它一个概率的复数最,小是吧,就咱取个log,学会了好解啊。
取log也会影响这个嗯这个函数的选项就让我们要让这个概率最大,我要哭出来,最顶级车里的指数概率最大诶,我加个括号就是求他一个最小的就是阿克曼,就阿根廷,然后呢我们从已知的观测地。
然后再推出这个x是不是哎呀melix这么一个方程,那英语有选logo,就我们这很多地方都可以写成一个在这个相加的一个过程,实际上我们最后拿到了一个公式,就是可以记为这么一点。
就arc m2 倍根号方分之一,加上个b减a x nl phon要加上一个后面的一个,revision,这是我们通过最大自然估计就是推出来这么一个优化的100度。
实际上就是我们就需要优化作用函数来处理到我们最想要的结果,本身呢就是我们这个带点控的一项,通常叫revise,然后我们把这个cost function分成两步,前面那一部分。
the debut dele,大家可以理解为哈,这个我这个b也是就a x加上一个噪声对吧,这个噪声是临床分布的,也是他的now应该是最小,实际上大家这个不考虑噪声啊,这个玩意就应该相等。
但是我们这个时候他不知道,我不知道它是啥,我们要保证通过这个相机模型a哎,我调试过这个我们想要的进行s应该是我们观测是相对这个啊,data和vity也没啥可疑问的。
但是我们要限制的这个解空间通常还是要后面一些约束我啊,有一些哪些人就是我的,最后一个信号s应该符合哪些自然的一些图像的些分布,或者是用已知经验的一个形象的一个分布,这个是呃要有一个约束。
然后呢我这个要先给大家科普一下都有哪些约束,第这个什么是pv呢。
就是来给大家讲一讲,这个就没ur,我这边有s的例子,这第一个假如说我们想要增强和这个图像的模糊程度,这怎么办呢,就是我这个fw,你看我这个地方要moi这个bat对吧。
哎我这个时候就可以把整个图像里面的它的边缘拉出来,溜拉发声,通过这么一个东西把x电源拿出来,哎我把这个边缘都优化小了对吧,这个时候电源都变小了,这个图像就算用变模糊了对吧,那比如像我们拍星空。
我星空星星点点诶,但是大部分情况都是空的,都没死,这个时候我就这个说明拍清楚这张图本身的这个自然不像s,它应该是自己就比较低级,也没什么电器相互比,但我们自然的一个图像,它活着什么规律呢。
是一个the progravity,实际上就是它的整个鬼脸的,就是我头像的一个鬼脸的bust,这个在我们前面啊,就while i want the gradient in caa。
这个时候给大家提过这个事,对自然图像通常它的一个边缘buff和它这个边缘norm,它应该是一个动画小的值或者对面名的名词,这是一个比较经典的这个mate 2。
那说到这个pv啊,其实有些很简单,它只是呃就是相当于我们把这一张图片哦,所有的规定都求出来对吧,我把这个组件求出来之后,再把这个加起来,这就是他的toto不行,因为我一个点的变化是一点的。
vation toto vision,就是把这些点的变化都加起来,也就是把那些鬼点都加起来,这个啊非常努力,那我们这个求这个推演的时候也给大家讲过,假如我他妈一个泛指把它记为d s。
然后我对这个图像求的时候,实际上就是一个呃后一定一的这么一个规程,就可以很轻松的把这个就不点的存在就很,轻松的这个锤子,这个地方你就分别把我们这个x和y方向的这个规定的说出来。
就是这个todo liation,顾名思义也是非常简单,这个每个点的变化叫very reset,来就是toto的,然后但是我们要mini就行了,就是这个toto就是整个的一个变化变化量哎。
这个时候就可以构建我们一个cos f,因为这个让他尽可能的小鬼,脸上本身buff和这个就符合我们对自然图像的经济,对就tv这个同学说过,某科学的同学说这个tv作文好像很早可能比这个还早。
因为这个人的这个智慧还是挺厉害的啊,特别是以前古老的科学家,就是上个世纪的科学家,当时在计算工具没那么发达,和大家很多时候都是摸索这个就图像啊,或者是像我们信号的一些自然规律。
本身这个covariation最早,这个电机的维修点应该是用静音去优化这一点,但他为什么这个东西视角里面是数学这种出来的,可能非常早,可能估计得有一两百年了,这么一个地方大家也可以翻一翻。
有些还有一些很多人老论文就可以拿到非常多的灵感,来应用到今天的一些呃科学问题。
大家尽情的去回顾一下古早的一些问题。
当我们刚才讲到了一个xy方向的一个这个gradient,当然我们有时候呢因为xy方向本身求的时候,他没有各项异性不是特别好,所以说呢我们就求助电的时候,我们就干净,一不做二不休是吧。
x y方向我求个平方,对你每一次方向推进它,我就是直接求出它那个方向诶,这个时候出去,那就拿到了一个呃各项ropic的一个photovation对吧,把这些加起来构建一个cf。
那简单一点就是或者x方加y方,这个最后可能在求解这个方面,但这个问题都不大,这个问题都不大,哎这个时候我们就真正的是注入到这个pvation,就是我们举个例子啊,因为它本身是比较怕对它规定的。
一般是boss,就是我们他回电大部分都是没有指望,也就是因为它plus就是我们最后把它加起来,把所有的规律加起来,应该是一个比较小值,有比较小的问题,这个时候就符合我们图像和自然cd。
因为我们大部分的一个自然图像都是边缘这个信息嘛,就这么边缘是记录了一些比较,所以说这个就让他进行的选,然后这个tv就可以变成这么一天到这就非常同性也好,非常异性也好。
我们都可以通过呃这个pvation来就接触的每个点呢,这个这个ta有点离,就是刚才强调了每个点的变化,就是一个vation covation,就是它加起来哎,这个时候我们就可以用一个l y mo。
就有的人大家也会用这个q nf now tv的now,这个最后优化的效果不是特别好,就是为啥呢,就是因为他那个尖的那个地方嗯,就是有时候不可谓,而且本身这个l one我直接优化的时候,它是两个直线方程。
这个更符合我们这个直线工具的规律,这个优化的时候嗯,效果会稍微更加好一点,比如说大家通常形容它的一个外nda,而不是absolute value,而不是用它的一个n。
你最后边缘剪出来的边缘会更加清晰一些,实际上这个为什么比偏低的就是l two靠近那个基础的地方,它有点太小了,有什么解优化的那些地方收敛的就是没有特别非常经典的时候,他那个边缘是会有一些模式。
这个大家可以注意一下,这个整个pvation是整个就是没有公布信息之前啊,就这个特殊位简直是占据了半壁江山,就大家通常都是构建这么一个优化函数,它有非常多的一些呃有意思的作品。
对这个这个女生叫老贝也很厉害,他之前搞过一个pp拉bation,但他也推上过这个我们这个用lslight的一个光场相机的图片,他也就put it actor,也是啊,老板当时提出来的。
访问the norm of,开始这些很经典的文章,大家都推荐一下,可以这个都是关于这个凸透的a神,当然除了像我们自然提倡啊,这个托头人士也经常用于像深度图像的一个优化,怎么样去保别渠道。
这个都非常有一个很大的一个问题,当然我们有这么一个期待求解的一个优化问题,我们已经描述出来,就a x减b再加一个rather rider,我们最后的解读解这个问题呢,对不对。
就我们这个目标目标函数已经列出来了,我要尽可能的让这个目标更小,对不对,像第一部分就是我们的一个data flag,就我这个观测模型,就我最后推相机模型,还有我要推出的特制的s。
还要符合他一个嗯就值的一个保值的一个,然后第二个部分就是我这个要下载的那个来着,就说让他不练的,我这有一个位置,我这个number马越强,对不对,就是把整个鬼点的,那个值啊在这里面占权重就越大。
是不是这个时候也就是我们高频增加的更多啊,这个这个这个也会引起一些就是不好的,阿德盖茨,那小了呢,那这个优惠比较模糊,写出来这个大家这个套餐啊,在我们呃一些解优化的问题。
这个套餐也是一个呃呃这么一个玄学的一个问题,这个调大小小最后的结果影响的都不好,一些优化的解器,这个是一种方法,但是我们也不希望大家掌握一些更底层的一些知识,就是我们这些不到点球。
而且像我们这哪怕到了今天有很多这身体得解那些求解器,就解的也不是特别好,就收敛的会比较慢,因为大家就掌握这个优化的前进性能,也可以去改一改,就是怎么就比如说我用一个a b mm去替换其中某些环节,诶。
处理完之后这步就进的自由好了,下一步再来这个时,候就可以对我们整个的一个计划,就是说这个就是不光是优化问题,这个新的游戏里面的优化问题,也可以借鉴优秀的资产,在主角就听到了一个half。
在这个级别在北我们已知啊,我们的那个object function对我们的目标还对,就是一个1%,是最后我们后面求的时候发表示这个要求的哎,这个时候前面的这和ity加后面的一个lego vier。
我们把这个套装选一个目标函数,就重新写为就是fx加tz的这么一个假设,我们现在用的是一个啊就是鬼点和一个pvation,就是随便个bug,就是这个我们就自备了。
就像jz实际上啊就表示为g x减z等于零是吧,我这里用一个新的引入了一个新的一个变量,一定实际上它是作为呃x的一个节点的,实际上这个地方是逐渐引到了,所以他的操作和这个美丽的空间上去。
我就可以把这个整个的可靠方程给他一个fx加t v啊,但是我要优化呢,都是优化这两个参数,对不对,然后它要符合gx减z成员这么一个要求,那我们把这个ctrl d x y等于零点进来点进来对吧。
把它作为一个看剧,提到我们整个的一个就叫拉格朗的函数,这个拉格朗的函数,这个图的这个应该在这里面,这个图应该是能保证的,这个规定l i no,再加一个iphone,这个肯定是负的。
当然有时候呃感觉有有些有些时候会有会涂好就会哭,你就点点点的,不知道点哪去了,所以说这个这个这个问题咱回头再单独列出,把这个点进去之后,我们就可以构建成一个安装方式,但有些同学可能已经学过了一个。
就在这里想问大家一个问题,你通过这个拉布尔函数就看出来这个a d i就我们这个它的switch letter,在两者之间有什么样的区别呢,大家有没有学过的,这个可以给大家。
分享一下这个从这个我们这个阿克曼函数就可以看出,我们这个up加一个图形跟a b之间的一个区别,就是本身好像a d m它那个构建的拉杆横叫augmenting的拉格式,它是一个中长型的拉杆机。
实际上除了我们这里,比如说我们既要解这个方,用一个电源去解这个函数的时候,那除了我们列出来的一项,他还要增加一个一个工程项来去,作为一个是让我们整个就解的更加更快一些吧。
这个我在一个专门大家可以讲一下这个up或者x0 和a之间的区别,当然这个最后呢从性能表现来说,还有一个一应性来说,这个还是这点能不能弄一筹,当然这个就h6 s大家也是好好好掌握一下,我都可,能用。
我们把这个拉装完函数解出来之后,实际上我们就是要交替的去优化这个值分配对吧,因为这个z跟x相关了,但是我们把这个单独写出来,就是为了呃我们可以分步骤的就分别优化x n z交替的优化s。
这个时候最后就可以不断的收敛,不断的收敛,收敛到就想a的心,我们在优化x的时候,我是可以把这个z当成一个优化v的时候呢,就把这一步的x当成常数就交替的优化,那我们在我们这个这个这个就是c9 。
就没有说没有找到一个阈值的时候,这个时候就没有收敛,没有这,点我就交替的优化它好了,我们现现在第一步,那优化这个x实际上优化的过程,我们这个有有个东西叫proximal officer,也就是近端分子。
我们现在只考虑有s哈,这个z现在就是一个常数,我们要优化这个拉格朗日,也就是minimus这个ip对吧,这个类常数,c类常数对吧,不管它这样,我们从这里面拿到的就像是fx加上1/2周,然后在后面就拉了。
这是我们第一步要优化,还有一个问题,然后第二步把这个x fix掉,我现在第二步这个x乘以一个常数,我现在优化z是吧,或者fx,所以说已经变成常数了,我们一优化的是后面这一项。
实际上我们最后这一个侧目就df点对它的一个now,这个时候已经是作为两部的一个音节,就是我两部啊,这个做实际上是构建x跟z的一个观点,这个时候就是看的标注的,我们在每一步优化的时候。
都要考虑到这个rgrier这个一些问题,所以说呢呃解这个拉过日的时候呢,我们就可以像刚才讲的分别去优化这个x p b,你有个变量对正面优化这个x z,直到他收敛拿到一个我们最后想要的一个结果。
所想要的一个x,当然我们有时候也会把这个就快直接写出来了,像fx就是呃实际上是c减b对不对,减去一个data com z呢,实际上就是不合后面的这个就是一个后面取一个推荐的位置,一个关系啊。
有空位中间一个关系,从这里面我们可以看到,这时候我们变量x对我们最后想要求的一个shop里面,然后呢c呢实现原理的就是就conclusion也好,就一个没有防卫性也好。
反正不管就是一个好图变一个快速的一个过程,对大家之前那个旁边声音就会给大家讲,然后呢这个z啊实际上就我们就加了一个like vb,对他大概是这个这个要考虑xy方向。
这个也就是这是它的size是整个s的两倍,也就像是x两倍,这个考虑xy方程,这个大家注意一下就好,b等下就求个主导,这个也没啥问题,答这个问题就从这儿就来了,我们要分别求这个两步哈。
第一步是优化得到减cf的优化z我这两步我把这个我,们的目标函数解出来之后怎么优化它们,第一个我们就发现这个科的话,它是两个lsnow对吧,这个时候诶大家发现这个时候不是很喜欢,很简单是吧。
这个实际上就是一个你你不要把这个展现一个非常大的一个maj,那就抽象一点,这玩意就是一个idol的函数,我求个导诶,是不是就可以很快速的把这个x x求出来了,直接导到它等于零,有它的地址,对不对。
这是一个严格的一个图标,他这个机制就一定是学计算机,但哪怕这个最后可能呃这个我当这个c跟d可能会比较难难用,那最后大家,点的时候通常是一个就靠这个怼脸来快速求解啊,这个第一步。
那第二步呢要求它的一个toc主要去mini ma这么一个函数吧,这个就是b n t z平方加上一个z对吧,这个v是边角,这个时候我们是怎么对,还是老板号,其实这个也是一个凸函数。
l y呢two呢它也是一个凸函数,其实它是围绕着这么一个来给大家划拉一下吧,这个可能这个这个地方有点费解哈,先给大家划拉一下,谢谢,实际上我们这个关键z的这些反应技能,denied,它就是一个。
再加上一个嗯,就是这样一个结,讲一个一个一个这个加上一个这个对吧,你重写那么好看简单,这个时候我们去怎么修理它的一个机制呢,实际上很简单啊,我们就直接简单一点,对这个对这个z指导就行。
这个后面这一部分人都知道好求啊,b x减z这个求导直接这个拿出来就行,但这个l y norm这个怎么抽到,这同学们有没有这种感觉,这个l y norm和大修道这个求导也非常简单啊。
这个l y那我们求导实际上我不会取唉,我这个时候我在这个中心点之前,这也就是正值的时候,这个跟它原本的还是保持一致,而负值的时候就变个方向对吧,然后小于一个threx的时候呢,我就把它设为零是吧。
这个求导其实是非常简单的,就是正-2个斜率在这前面,就是你这个大了就是正确率,把这个一个小一个负的力在这个几小时的一个收听呢,我就把它设为零去了,这玩意这方法叫soft poly。
这个这个后面就是大家都能想到这两部戏都变得非常容易,求第一步求导创作这个局面呢,把这块写出来,第二步哎求导结合这个方式出来头顶的一个位置哎,这两步都很容易写啊,然后再交替的就把这个迭代。
直到这个函数收敛为止,把这个写下来,可能会直接下来了,其实这个没那么没那么没那么简单,没那么容易啊,不是没那么没那么复杂,大家求个导的时候把它解开啊,解开可能看着跟大家也没必要去拍,就直接吃早就上。
特别是cf求导的就是r b和c t v c temple,然后这个把这1/2全拔掉对吧,这个就是一开头全后面的呃,z在几小时他没有啊,他这个导数存在,你就给了个出来做一些,我这个小鱼就不错了。
直接就零了,没有啥早就去找对,他的需要他那个极值在那个变化的点是不同的,所以说就干脆有小于一个在那个范围内很小一个范围内,就一技能一个范围内,你干脆就让它在这个地方没走就可以了。
在我们最前面第一步求导就发现让c trl,然后这一块等于零,就拿到这个,这个时候我们就需要解了这么一个x,实际上写这个x嗯,按理发还是挺配对的,就是要一个confident提炼来。
最好对应的抗体应该比那本身这个解空间还是比较大,你点的时候可能你要直接解哈,就这个非常超大一个miss,我在之前看看讲过,如果有魔,王要用这种迭代的方法来求解这么一个这是a减b的这个问题。
实际上这个大家可以看到从这个term来看,实际上我把这个c tc还有这个rob tb拿出来,实际上是一个x的系统,后面是再点一个常数值,本身就是一个x减b的问题。
这个大家给大家讲过怎么解答这个config jam这个解法比较好,比较推荐大家使用,然后呢这个解出来x之后,然后第二步这个我们就把这个f x这部哈,就是新的一个x换那个旧的对吧,当然这个求解过程中呢。
其实大家偷偷的直接在平面的去写它也是可以的,你直接因为其余的成本频率低频率成本11点,这个变换一下,大家可以稍微调一下,就可以非常把这容易的把这个这这一部分就是实际上是a就a x对吧。
这个部分实际上我们就观测,实际上就是d这个时候就变得非常容易把这个最后调料值个解出来,然后我们这个x这一步之后,我们要交替的啊去更新这个x和z的一个值,然后歌曲z呢就是要通过频率的一个方法。
其实也很简单,大家就都是这个意思,那这个地方啊大家看看是不是很像这个文章里波啊,这波实际上基本上就是大差不差,因为后面跟的可以去,有时间在这个不能动动哈,这个大家不能直接等,这里面有很多这些参数。
比如像c的fp,啊这个我课后会给大家分享一个详细的一个治疗过程,这个大家可以看一下照的点,那么一个可能优化的一个函数设置,这个就挺简单的,很简单,就是电话一成立除是吧,这个很容易。
这个时候就是我们这个函数实际上是第一个就是l m nm在这个地方,然后这样就是为了一个at to,这个时候就是刚才我们说到的一个,stop threat to。
就是我们这个软玉值的一个把它c s p就软硬着扇子的,实际上比较简单比较简单,今天是我,最后的这个中心的这个是dx是吧,这个值应该是我们这个cs不是10号。
当它大于大于这个这个小的一个battle的意思时候,哎就是我们现在是我们刚才讲的那个函数的前面那一段,就是前面的斜率对吧,前面写的就是我们记为呃这个六点卡帕屏幕,实际上就是我们这个前面序组成一层就好。
把这个lab其中一个常数拿出来,这个就是二分之,就是可以把这个前面z玩2万呢加上一个二兰姆达分之六,然后再乘上这么一个细节,比如说这个呃这个大家只是把它当成一个系统就好。
前面的斜率跟后面的一些呃斜率因为小于一个绿植的时候,大家就把它当成圆,这个就好了,因为这个中心我们两个直线拐点的地方,他那个地方不可导不可导,这时候在这里哎。
所以说这个时候我们就可以通过这一个top transcoding的一个方法,来去把这个位置它复制掉,我们这个up配的这个z是因为上一部的x里面是这一步,已经作为一个性格上的直接把这个给带进来。
然后去每一个像素的原因是up的影响,这个号也非常的强,所以说,我们这种ex y的一个就是这个fc后面它叫一个program operator,the poor bor,是什么翻译,可能记不很清了。
但是可能是叫近端分子,就prom quor,这个大家注意一下这个车位就好了,就是说我们最后这个你看大家倍的x的时候,我们很简单求了这么一个嗯,就是解这么一个建议方程就好了对吧。
这个大家就明确明确一下用的ctrl 5点,但也不一定好,一个图非常大的时候,你要小图128x256,但大图的话这个速度确实会快很多,然后阿贝的完了又是这给大家强调一下啊。
嗯这个mini max你把这个lamba提出来之后,长度嘛不用管它,这个实际上就是可以在v加上,也就是alem这么一个,然后我update这个day的时候,也有同学呢。
我一个tober就可以把它就一个就一个boss来说,fate就可以把它截出来,当然我们有时候要是想要去优化这个用一个dnoy,就是我们现在比如举个例子,我们现在做到什么对吧。
我们也可以把这个the regular i换一下,就不一定是cd,比如说我们把这个赛季换成一个就是一个比如说一个innoy,一个cv,这也是可以的,我们,也可以把这个带队换成一个人。
not for me,也可以换成一个变3d哎,但是我们这个not vious,我要提前的标准就是呃lamba do u,现在一个not vi,实际上我们实际上我这个rap rider是可以随便换的。
你在update的过程中,你怎么样对这个the outfitting就是操作其实问题不大,最后反正你操作完之后还是这张图是吧,就是说呃有时候也推荐大家尝试一下各种各样的一个方案。
最后加个除了这个把这个pk我换成一个小的一个cn,也是可以做这个优化迭代的,对这个就非常有意思,大家都可以试一下,而且以前的那些,论文很少见,大家这么做,前两天大家工作了。
其实我感觉可能把这个tv啊换成一个cn,作为一个ravi可能更有意思,大家可以搞搞论文啊啊这个这个意思,当然我们最后抵抗version的时候,我就看到这个我们加了一个tv。
对我们就本身这个插件里面就非常干净的,我们比较各种各样的方法,比如说第一个是我们直接的一个medicine,它造成是这样,我们观众要的,然后呢加一个伟大的国,伟大的波。
可以看到它的一个恢复的一个信道比啊,可以得到pf啊,可以得到这1。5分之,然后呢就是一个aa加一个tv可以做到20分钟,然后他不在你的直接上,直接用一个哈佛的基础加一个tv的约束诶,这个可以搞到21。
3,比这个adim稍微好一点,但是前面,这个adam hs其实大差不差大差不差,影响也没有什么很明显,但是我们这个时候把这个pvation换成一个小的一个cn小神经网络,来做个说哎。
这个时候又会有一点提升,可以到r6。7个分别,那本身我们要用a d m的话,可能会写的更好,就比这个因为叠到30层就解决,就是本身这个前面优化的一个问题,就是我们比较不一样的一个温度,比较不一样的优。
给大家总结了一下这个up在那个slemv代码,那我们用一个denny的一个regular,就是我们呃目的啊就出了一个情况,我们想去到的时候,哎我们这个先呃首先搞这两个usually一下。
就这个xy这两个变量吧,你先用单可以用名字,应该设法留下,然后再不满足收敛条件下,我们去优化的去分别携带x t z是吧,每一步都是求一个x x x的一个cos,然后求一个这个pom。
然后最后啊然后这个点最后一个靠something收敛,就是这种收敛,然后呢本身这个用一个tv搜一个叫la,实际上嗯这个也很简单哈,就是实际上就是把这个段子,把这个f z这个扇子换成一个零件。
成一个扇子给我,就是这个打法不差,非常简单,然后第二步这个tv我直接用一个top 3封面截出来,这个就写第二部啊,这个也不对,上面这个就是这个电脑。
就其实啊这整个这一节课下来就是大家可以看到实际上这两部对吧,我们兵部是优化s和z当成一个常数,第二步优化z把x当成常数,这样携带一次,最后结果就承载了这个非常简单非常简单。
实际上在我们这交替的去求这么一个,这个这个有bo知道这个receipt收敛,那我们看一下它整个的这么一个过程是什么样的,就我们给到一个flab求x求求对出x球队,然后最后收敛之后。
我们就可以达到一个多的一个,好就是近端的一个牌子,进端的一个这个提醒,大家就再回复一,就positial就是在这一步我求个解,比如说我这个地方是我的r c4 d和up dd,然后我要求他点这个过程。
就talk about it这个东西里面,这个其实看起来就这一步,我忽略掉其他的变量,我可以在这一步学到他的一个,而且实际上就是调节模,就是近端近端分子,就我这个变量,我在这个只考虑这个变量,其他。
x和z差多少中距离的,这个跟x也没关系,我最后看rec罗差多少中距离的,这是我最后的一call方式,然后我每优化一步就会拿到一个receo对吧,然后这个vivo是够小的时候,在这个时候就可根据迭代了。
就每一步这一步这个没看过,这个基本不变就成为收敛,是一个收敛,诶也回到我们的课堂,对实际上这整个的过程,总结一下啊,总结一下这整个的过程,就我们一些power meter,车远是x平。
那肯定是下面的这个x兵,这本身是借,应该理论上应该无限趋近于g对,就是,当然我们想要考虑到一个就是用一个小时网络去做一个,比如一个dener to the regular lever,就cometer。
这个时候我们也可以用一些啊,求一个神经网络的办法替代我们这个优化的过程,比如像一个nt,然后也可以用一些tv,这两个大家都可以试一试,就这个问题,你这边的就这两步迭代。
这个就have project dt,下面下节课会给大家讲一下这个a d m a d m m,它跟up主的releon不一样的地方是,它需要一个增强型的拉格朗,我这个时候我用这个增强型拉光王团队。
本身这个迭代其实也都是那种手机,都是交易成子嘛,这个也是优化一部s优化一个位,只是a d m会稍微更加科举一些,他收集的题还有收敛都会更快一些,这个a。零是我常给大家强烈推荐大家掌握一种方法,嗯。
今天时间控制的比较好,也给大家从上节课这个正向的一个image formation,因为之前我们考虑的都是普通的父进程上了,这个就不太考虑啊,一些我们自己加的一些对整个的一个相机的一个模组是那个a啊。
其实可以直接进,比如说举个例子,像codor那个a啊,那个p s f我都可以出变化,哎这个点的pop其实都一样,我们最后都是写成一个a x减b,再加上后面一个叫做rati个选项。
然后这整个静态摄影的问题就整来整去,大家整明白之后发现天下武功这破套路都一样,这个陈同学这个人啊,这个很好,这个也希望大家能真正的把这一门课写下去,因为到目前为止,我们有非常多的一些难题啊。
还是没有解决,哪怕我们这个领域已经做了22 30年了吧,但我目前感觉来说还是一个初级阶段,还非常多的一个坑可以做,所以说也希望大家在这个领域里可以更进一步,得有什么问题,大家可以问一下,啊对了。
这个大家要期中考试的话,可以先跟我说一声,现在把这个时间记住,可以的,这个这个地方是一定不会给大家再往a,好像这个地方还有一个a b mm,你看这个优化还有什么改进思路啊,其实。
还有一些哈其实本身就是大家把那个immediate formation,那个a2 就是相机的一个模型成像的一个模型,a这个地方现在也有一些老师哈,我看有一些主把那个a啊用一个小时内去替代。
因为有一些相差不大,好描述的时候,我直接用一个神经网络去生成的相差,所以说你不只是我们最后一个reviver time,可以一个小电网小程序网络去替代它,我前面一个像成像的模型也可以。
当然我们还是更希望大家用一个真正的物理模型,因为真正的物理模型就更准确一点,就哪怕现在就神经网络本身还是泛化性不是特别好,所以特别好,所以说能尽可能的描述还是尽可描述,所以说像我们最近的一个工作。
就是做一个普达附近的设计,就可以把直接就把这个平面formation通过一个啊,首先这个推进的方式来直接把这个相机的模型a表示起来,这个时候就描述的更加准确,因为以前很多像我们这种做新的摄影的问题。
就这个a啊,这个变化过程都不是特别久,就很多时候都用进去,但我跟那个渲染就渲染结合呢,我就直接,把这些所有的这个相差,我说你今天把我甭管我这个这个a数学不好表现,但是我推荐渲染的方式来表现。
这个也会比较有意思,有数学作业可以联系我啊,这许大家知道知道这些论文啊都可以,这同学们还有啥问题吗,重庆就感觉思路我想一想,可能还有一个还有一个就是我们课后交流吧,这个那个什么文章叫啥,谁的问题。
对是的,这个现在已经从现在结果这个之前21年的片段呢,实际上都是这么做的,当然那么这个时候我们只做了一个extension def的,金拉的cpu的两个可恢复,其实还有更多的核心性。
大家想做的话都是可以连续,同学们还有啥问题吗,那个eboy就问的是哪篇文章了,好模拟的成像a的过程嗯,那个叫底层或者推动for compact。
对end to end complex design就几分解一些,然后用神经网络模拟这个相差的那个那叫o delix,签一张叫,但突然间他胖了起来,感觉都差不多,这个年龄还这倒也有些对,昨天好。
那个好像我就记不清了,那个老师那个文章写的也非常好,模拟本身的一个像他的一个,好再次感谢大家聆听,如果没有问题的话,我们今天就到这里,还不感谢大家回到电车204,也希望大家肯定能继续坚持下去。
好好的把这个解压,因为我们国内还是国外有非常多的应用啊,就是嗯还是很缺人才的,深空探测啊,这个都是需要一些现在摄影的一些背景,但是很多地方都缺这方面的人才。
我希望就是把大家都培养出一个能独挡一面的一个人才。
这个嗯也感谢大家好。
14.引擎工具链高级概念与应用 | GAMES104-现代游戏引擎:从入门到实践 - P1 - GAMES-Webinar - BV1QN4y1u78P
哈喽嗨大家好,跟大家汇报一下,我前两天刚刚从海南飞回来,所以今天下午刚刚到杭州,然后晚上直接冲进了我们的直播间,然后那个首先的话按照我们的惯例,首先跟同学们回答一些来自于我们社区的问题。
那首先那个同学很多同学问我们说,上一节课布置的作业,马上这节课要布置新的作业了,那我们上一节课作业还要不要继续去教,那实际上的话呢就是说呃我们考虑到很多同学,因为很多同学做的速度非常的快。
当然也有很多同学的话呢,还要花很多的时间,慢慢熟悉我们小引擎的代码和东西,所以呢我们决定还是把这课程的时间延长一点,另外一点的话就是我们也发现在B站上,因为B站特别好嘛,就是视频会一直放在那。
会不断的新同学进入到我们的社区,然后呢大家有的人还在还在补上前面的课程,所以等到新的课程能能够做的时候,可能还需要一点时间,所以的话呢我们决定暂时的话,还是把这个新的课程的这个啊。
这个上一节课的作业的这个时间继续往后延,然后具体什么时候我们能够so that dine的话呢,我们在争取在后面一节课程跟大家,或者在那个微信上跟大家在同步,反正简单来讲的话。
我们尽可能把这件事情变得flexible一点,因为确实照顾到,就是这个课程现在的周期已经非常长,长达接近三四个月,所以每个同学进入的时间啊,水平都有波动,那我们尽可能让大家都能兼容的了。
那么另外一个的话呢也回答一下同学们的问题,其实这个问题蛮有意思的,我们选了几个比较有意思的问题,就有同学问我们说,哎你们为什么不用像那个什么FBX啊,这些公开的这些格式啊,对吧,那么其实的话呢。
首先就是这些格式是直接来自DCC软件了,包括这些这些格式呢,现在有很多人在用,那么但是的话呢,我们当时其实最核心的一个考虑这两件事情,第一个就是我们尽可能让那个PICO引擎,越简单越好。
如果我要支持FBX格式的话,大家如果研究一下,就是FBX格式是非常成熟丰富和完善的,那我们就需要接入一个完整的,迪斯萨斯第三方库,然后呢去让大家去,这个就是处理这个FBX文件的格式。
包括这些数据读进来之后,我们还在做一部比较复杂的转换,当时我们在想,就是说如何让同学们能够快速的理解像反射呀,引擎的基础,数据流的架构啊等等这些东西,包括我们考虑的,就是在真正的商业级引擎里面的话呢。
我们一般不会直接用这种啊TCC的格式,因为IP格式虽然非常好,作业文件就是在不同的工作室啊,或者是那个工序之间传输,文件是个很好的,中间我们叫intermedia format。
但是呢它并不是一个效率或者引擎,friendly的这么一个格式,因为对于真正的游戏来讲的话,我们的这个数据格式要求它的效率,比如它的packaging,它可以加密,它可以流式传输。
它可以那个就是说对可以留市场等等,这些要求是非常的高,那么所以的话呢,我们就想说让同学们一上来就能够习惯,或者适应这种,就是说诶小就是customize the fireformat。
而且能够你的schema系统,能够和这些东西能够连接起来的,这样的一个设计,所以我们相当于用一个最简单的格式,把这套机制教给大家,因为从schema反射到你的custom format。
它是一个完整的一个组合关系,那么另外一个同学没人问我一个问题,就说诶你们为什么没有用那个,在Mac版本中没有用meta,而是直接用了这个就是那个那个model的VK,这个东西放在上面。
就是其实这个原因很简单,首先我们已经被同学们狂喷了,说你们为什么要van对吧,因为相比open gl的话,van实际上复杂很多,我也跟大家解释过,就是说呃当时我们的考虑是说。
让同学们直接接触现代的这个GPU的一些,API的一些结构,因为它真的是非常啊接近于driver的这个写法,效率是最高的,也是最具有工业化的这样一个基础的一个东西,那么welcome本身已经非常复杂了。
那这个时候我如果再去上一个DX12版本,再去上一个metal的版本,那肯定是最好的,就是说它肯定是性能最好,也是最符合各个平台的设定,但是首先的话我们开发团队的话,工作量会非常的大。
因为同时要支持三个版本,大家想象一下,我们是一个就是开源小引擎,其实同学们都是用业余时间在写,另外一个的话呢,就是同学们掌握和学习起来的话,可能门槛会更高,要理解。
比如说他的第一层的这个就是RH这一层对吧,抽象的更好,然后接下来的话要针对不同的平台,我们用不同的版本,所以的话基于这个考虑的话呢,我们一上来说OK统一的用motion一个版本,其他的平台搞不定的话。
我就强行的用一个中间件把它给转过去对吧,就像那个我们现在在那个,其实在Mac上还是metal的指令,但只是我们写的时候只写了这个van,但是呢它自动把我翻译成matter的,原生态指令而已。
所以这也是我们的一个考虑,那么就是说我们上节课的那课程作业的话,给大家讲的就是我们尽可能的给大家延期到,就是这个月的中下旬,如果有必要的话,我们再去研究,因为这也是同学们特别关心的一个问题。
好的我们的q and a part花了我们的6分钟,那我们先给大家讲到这为止,因为今天我稍微有点delay,所以的话呢我这边稍微赶一点时间,说话语速有点高,同学们原谅一下好。
今天进入到我们的课程的正题了,就继续讲工具对吧,其实工具真的是博大精深,那今天的话呢,这节课其实是我们比较难以准备的一节课,为什么呢,上一节课讲的全是工具链的一些基本的,fundamental的原理。
那这节课呢实际上我们要讲一些高级的,讲一些应用的东西,但是我们在讲的时候,我一直在思考的一个问题,就是说如何把这一节课不要变成一个,就是像我们在比如说在各大视频网上。
随便能找到大量的这个叫游戏引擎的使用的,这种这种这个教你怎么使用游戏引擎对吧,给你介绍每个工具的详细的功能,怎么去用它,怎么去组合,怎么组合你的变化,因为那这个呢更像是一个游戏引擎教学视频。
但今天呢我们讲的还是一个,就是如何去编写或者架构自己的一个游戏引擎,所以今天其实你看到我我们的课程准备中啊,我个人觉得是我们最精分的一节课程,但是呢我们在尽我们的所所能。
就是说尽可能的讲一些就是fundamental的,就是底层的东西,然后呢上面的一些application我们会点一下,因为你没有,确实是如果我们不知道application的话。
大家不理解底层为什么这么写,但是呢如果我们只专注于上面的application的话呢,哎我们又会忽视掉下面,其实它有一层底层的架构解决方案,所以这是我们这节课尝试想找到的,这样的一个平衡点。
好那话不多说,给大家介绍一下我们这节课的主要内容,那么这节课的话呢,我们大概分成这么几个part,第一个呢,我们还是非常快速的,让同学们对这个游戏的真正的production,有一个感觉对吧。
那么第二个的话呢,就是说我们呢接下来会围绕着一个重点呢,也是我们一直搭同学们最熟悉的叫地图编辑器,基本上所有摸过游戏引擎的同学,都知道这个东西对吧,那我们今天要简单讲一下诶。
如果我们要架构一个地图地图编辑器,我们怎么去架构,那第三个的话呢,我们其实在上一节课给大家讲的就是,plugin对吧,插件机制是工具体系最核心的一个机制,那今天的话呢我会稍微展开一点点。
跟同学们讨论一下,就是说一个plugin architecture该怎么做,就是在游戏引擎里面,Plugin accture,到底他这个有哪些坑,怎么去,就是可能会在哪上踩雷对吧。
那么后面的话呢会跟他讲两个重点呢,非常有意思的系统,第一个就是说一个线性的一个叙事性系统,在工具体怎么表达,但我这里面会用sequencer举个例子,但是同学们一定要意识到,就是在游戏中啊。
线性系统绝不止一个SEQUER,其实很多系统它都是线性的,就是说你希望点一个play开始,然后呢他依次会发生所有你想发生的事情,那么第四这啊倒数第二排的话,也是同学们这个一直很期待的。
就是很多同学问我们说,诶,能不能给我们讲一下,小引擎里面的这个反射系统是怎么做的对吧,那么其实的话呢在这节课里面呢,我们会稍微花几页笔墨跟同学们详细的讲一下,我们都反射到底是怎么东西。
因为反射我们认为四工具链里面,做game play的一个非常重要的一个基础,那最后的话呢会给大家点一下,一个比较有意思的东西,高级的东西就是协作式编辑,因为我们认为就是说协作式的编辑工具的话呢。
会将是下一代游戏引擎发展的一个重点方向,对吧,因为我们现在要处理的游戏世界越来越丰富,越来越复杂了,所以呢这就是我们今天的主要内容,首先的话呢大家一起来看一下。
就是说游戏的production到底是什么一个状态,那这是一段小小的视频,这个就是那个育碧的这个各各他自己的,in house的这个引擎,你可以看到,就是说。
其实在这样的一个真实的游戏studio里面的话,大家会在艺术家会用各种各样的工具,有人在建这个场景的layout,有人在设计的game play,然后当我们点了一个一键的play之后,哎。
在这里面游戏用户会产生各种各样复杂的行为,但这里面有大量的比如说用词,就我们叫做那个,就是那个那个那个叫PGC对吧,程序化方法自动生成的东西,也有大量的for designer的这样的一个。
FIRMWORK和框架性的东西,那么在这里面的话呢,artist就是说甚至可以变换,自动化的生成一个整个城市,那么这里面当然还有很多的,比如说我们叫做concept artist。
他设置这个角色和场景的外观对吧,然后呢我们要生成大量的那个那个model alex,它生成3D的模型,这些东西这些所有东西全部连接在一起,形成了我们一个真正的一个商业级游戏的production。
那最后交个交付到大家手上的东西,是非常的非常有意思的,你可以看到一个非常有趣的游戏,但这个游戏这里面的话,就说所有的东西它都是有语义的,所有的东西都尽可能让玩家能够可交互,可playable的。
Ok anyway,那我们继续讲一下,就是说其实呢整个工具链,它还有一个很大的一个挑战,就是说真正在实战的游戏中的话,我们知道就是游戏有很多类型,在这里教给大家一个有意思的词儿,叫JA。
我们经常讲游戏类型对吧,英文怎么说叫JA这个词呢,其实来自于法语,就表示各种各样不同类型的游戏,比如说我们讲RBGFPS对吧,这个这个MOBA都都叫JA,那其实对于不同java的游戏的话呢。
实际上他所要做的这种编辑操作,它的这种game play的设置,甚至关卡的layout都会完全关,关卡的组织规范都会完全不一样,那么这个其实也是我们工具体系,一个非常复杂的一个东西,那么工具体系的话。
但这样的一个结构和体系的话呢,实际上我们要和很多的工具在一起了,这张图的话大家有点熟悉对吧,这是我们在这个就是games,在第一节课也给大家展示了这样的一张图,包括这也是我推荐的那本教材。
叫game engine architecture,里面很经典的一张图,但这里面的话我要跟大家讲一个fax,就是说实际上这张图是错的,什么意思呢,就是说这张图根本就没有把游戏的工具层画全。
这里面缺了很多很多的工具,包括有些工具的关系,可能现代游戏引擎已经发生了一些变化,但是没有关系,我只想让大家看这个图,就明白一个道理,就是说,其实在真正做这个工具链,体系设计的时候的话呢。
我们实际上是要解决,就像我一上来讲,就是解决来自于完全不同的思维方式,就是艺术家设计师,程序员在一起能够协同协作的问题,而且在整个过程中的话呢,我们都要保证那个很高大上的原则是什么,WYSIWYG对吧。
这个这个名字比YYDS听上去酷多了,就是所见即所得,而且这个呢实际上是现代游戏生产中,一个非常重要的一个指标,为什么,因为我们在跟大量的艺术家,设计师在一起工作的时,他们会发现。
如果我们没有办法再工具这一层,保证大家的所见所得的话,它会极大地影响到游戏产品的不仅是效率,就是效率肯定是周期会变长,对不对,还要影响那个它的质量,为什么呢,因为比如举个例子吧。
比如说level artist,如果a level designer就是有那个关卡设计师,如果他不能真的快速的看到他调整完的关卡,长什么样子,而且自己真的能身临其境的在中间走,其实他很多时候的判断。
比如说这个地方我希望天上一个落石,那个地方我希望有一个小怪蹦出来,那个体验实际上是全错的,他完全不能模拟用户真实的体验,如果你不能带入到用户真实的体验中的话,那你给出来的设计一定是不好的。
那这就对工具产生了一个非常大的一个挑战,为什么呢,因为其实大家如果我待会会讲的,就是如果在做工具的时候,你有大量的就是额外的信息,额外的操作,才能够允许艺术家或者设计师,真的对它进行编辑和调整对吧。
甚至我还要解决同步版本控制的问题,但是你又要求这一切的东西,就是看起来跟真实的游戏一模一样,这个其实啊,这两个东西有的时候是忠孝不可两全的,但是呢就是我们在上一节课也讲到了,就是说我们最后大家总结出来。
就是说把游戏,直接把工具直接包在游戏引擎外面,是一个现在大家公认的比较好的企划,但这个也会给游戏引擎带来一些挑战,我后面会很详细的讲到这一点好,那么其实呢我们先从一个工具开始讲起来对吧。
因为我们这个游戏引擎课,并不需要讲所有的游戏工具链上的工具,因为那个工具量,那个数量可能是几十个为单位的,那我们就讲一个word editor,就是word是地图编辑器呢。
实际上很多人在讲word extra是一个哎,我就是拖拉拽的一个工具,对不对,各种东西拖拉拽,但是其实从我们专业的游戏,引擎架构的思想来讲的话,我们认为他是个hub,什么意思呢。
就是说它实际上是一个平台,我们把各种各样的我们在游戏的世界里面,需要构建的逻辑玩法,场景内容在中间进行,能够插进去的这样的一个平台,所以我们上节课讲到plugin的机制,所以这一点的话呢。
是当我们自己去架构自己的word的时候,首先把这句话记在脑子里面,你千万不要一上来就写编辑器,写写这种就是这个这个类似3D max的拖拽,选的这种逻辑,这种东西重不重要,非常的重要。
但是呢你会让你很快速的这种方法,会让你快速的得到一个诶,看上去很酷的这样的一个编辑器,而且你甚至产生一个错觉,说诶我是不是可以跟unreal pk一下了对吧,我以前就经常看到我们那个很多论坛上。
就会说啊,我这个什么什么东西超过了虚化,那其实从就是专业的游戏体研发来讲的话,我觉得我们还是要非常尊重那些优秀的,商业级的引擎,因为确实他们去是他们的核心,不在于一个一个的feature。
而在于整个体系,我是按什么一种逻辑把它架构起来的,所以这是我认为,就当我们去做世界编辑器的时候,最先在脑中建立了这样的一个概念好,那我们打开我们还是以虚幻为例吧,你看一个虚幻的源码,打开来。
你会发现它的上面买的时东西特别多,比如说你可以看到VIEWPORT对吧,你看到上面很多的按钮图吧,你可以看到layout啊,这个什么layers levels啊,什么outlier details。
对不对,还有counter brother1大堆东西,那当然你看着很复杂,而且这只是面板展示的方式之一啊,如果你打开一个商业级引擎的这个what editor的话,它的面板可以切换到很多很多的view。
对不对,比如说我们看那个我们的一个,真实的游戏团队的话,你会发现比如说同样是一个引擎打开来,如果是做animation的,如果是做那个场景编辑的对吧,如果是做玩法编辑的,它的面板就完全不一样的。
这这就是解释了就是为什么就像我讲这个world editor,它是个hub,就是说实际上它集成了很多功能,但是呢对于不同的用户,它又呈现出了不同的view,那么在这样的一个庞大的这样的一个体系中。
最重要的几个体系是什么呢,我这边就给我个人的理解给大家总结一下,抛砖引玉一下,第一个呢我认为最重要的是什么呢,诶editor里面的那个VIEWPORT对吧,这个VIEWPORT是什么呢,就是最重要的。
我们的用户和你想构建的游戏事件交互的窗口,那么这个东西他是怎么做的呢,其实在上一节课我们已经点赞了,我这边再明确讲一下,就是它其实下面跑的就是一个游戏引擎,就是一个游戏,但是呢这个游戏的版本呢。
我上面打了个flag叫editor mode,因为在这个editor mode下呢,你就能做很多真实的游戏不能做的事情啊,比如说我的我的相机可以自由的飞来飞去对吧,我可以无视所有的碰撞。
我可以把很多东西变成透明的,然后呢我可以显示很多debug draw,While wifi mode,对不对,那么这里面会提供很多的,我们叫做gadget,就是说诶那个小坐标系给你显示一下呀。
选点选选选那个点,取那个点曲啊,选中啊,还有一些东西,grouping啊,line啊,这些这些东西这些基础的操作的话呢,最基础的一些东西,是需要在引擎里用native code给你说的。
因为这样效率也非常高,但是呢上面一些更复杂的逻辑,当然我们可以用编辑器自己来处理,那这里面有一个很有意思的细节,就是说这就意味着我们的引擎的代码,会有一些代码是叫editor only的代码。
那么这个东西的话呢,它的版本就是不一样的,那么这里面我就特别给大家注意一件事,当我们自己架构自己的引擎的时候,这也是初级的,这个这个新入行的同学特别容易犯的一个错误,是什么呢。
就是说如果我们不小心把这些编辑器的代码,编译到我们上线发布的游戏里面去的话,那么这极有可能会成为别人写外挂的一个,很重要的这个入口对吧,就是诶我我让整个世界都透明了。
我我让这个什么什么东西选取直接就有了对吧,或者我可以直接飞来飞去了,当然了也有,但是其实外挂并不是这么写的,但是如果我们不小心把这个H的代码的话,放出去的话,只要人家找到那些函数名和指针的话。
它其实用起来特别的方便,所以的话呢,就是这个是我们在所有的引擎架构的时候,我们都会问,因为特别是在一个大型的游戏团队啊,啊游戏引擎团的人数是非常多的,工程师的话会到上百人左右。
那就特别容易出现一些没有经验的,我们的开发的同学会诶,应我们的策划和设计师要求,做了一个工具和功能,大家都觉得很好用,然后呢策划和设计那个美术都很满意,但是的话呢就是他忘了把这段代码。
把它包在那个就是editor onion那个红下面,结果这段代码就被编译出去了,然后有的时候会产生这样的一个问题,所以这件事情的话呢,就是说一定要区分区分了,所以VIEWPORT这件事情的话。
大家记住记牢了,就是说它实际上就是跑的是一个完整的游戏,这件事情非常的重要,因为它是最基本的一个保证知识,那个我们讲的所见即所得,因为特别是对于artist很敏感的,比如像才智对吧,我做了一个无效。
我的光从这边打过来,我希望他反射几下,把一个角色给照亮,包括我做一个过场动画,我希望那个角色正好走进阴影,这些是很细腻的一个光和反射,它必须要通过这样的一个架构才能实现得了。
所以Viper是你做WORDOR最重要的一个,一个和他是最好不要做plugin的,它本身也没有必要做plugin,但这里面要讲一个有意思的细节是什么呢。
就是说呃实际上在一个真正的这个world editor,商业级的word editor里面的话呢,VIEWPORT有的时候不止一个的,就比如说你在做过场动画的时候,哎你编辑的是一个VIEWPORT的。
但是你还希望有个VIEWPORT去看它,你甚至会做好几个VIP的,所以呢当我们去做一个编辑系统架构的时候呢,我们经常要让VIP的支持多个view,其实这里面的话,其实对你的引擎架构也提出了一个要求。
为什么呢,因为你不能把数据同时拷贝好几分,对不对,那你编辑了一个数据的时候,你还要像那个好几分的引擎,你考同步数据吗,那不相当于在本地写了一个小型的网络,同步了嘛,对不对,所以的话呢。
当我们再去写这样editor viewport的时候的话呢,我们实际上是要对引擎那边要做个改造,就是让它能兼容多个view,当然有的时候在我们某些游戏中的话,我们也也需要实现这种画中画。
所以也作为我们的一个需求,那么第二个呢很重要的一个窗口是什么呢,就是说在我们的整个这个游戏世界里面啊,其实我们有很多很多的东西,比如说我们天空都有语音,有角色在编辑器里面的话呢。
就是我们其实要编辑的元素特别的多对吧,我们有天上的语音,地上的这个这个NPC树上的那个那个一花,一木一草,那么这里面有一个很重要的原则,就是其实我们在第一节课,第二节课就特别是第二节课讲的特别清楚。
就是说所有的东西都是物体,都是那个object,那么这里面object呢在编辑器里面的话呢,我们也会讲说所有的object都是editable的,就是说都是可被编辑的,但是当然了,不同的引擎说法不一样。
比如说虚幻引擎里面我们会叫他actor对吧,那个unity里面我们会叫他object,比如像我们我自己做的引擎的话,我会叫他object,对不对,但这不重要,重要的就是说其实啊我们会发现,不论你是什么。
在这个世界里的对象,你都是有一些可以编辑的东西,比如说我要至少能选中你吧对吧,我至少能改变你的位置吧,我至少能旋转你吧,对不对,然后呢我点中你的时候,我想编辑你的一些属性吧。
所以这个呢也是当我们去做word editor的时候,我们最核心的要思考的第一件事情,就是说在架构上,就是说我要把这个世界你的一切的东西,比如说大地天空语音,你是天上的飞鸟。
每一个人都把它抽象成一个common,这样的一个editable object,对吧,这这跟enery object还有一点点不太一样,就是它相当于那个object再往上再走一步。
那么其实呢这里面就产生第二个问题了,这也是我在讲的,就是大家如果在下个word editicia,你会遇到的问题,就是说我们实际上一个真实的实战的一个,游戏产品来讲的话,一个场景里面对象数有多少呢。
基本上至少是几千个甚至是上万个甚至更多,大家有没有想象过,就是如果我给你一个文件目录里面,给你上万个文件,你怎么去管理它,其实你很多时候不会管你,你看到的文件是123456789十对吧,好,没问题。
你都记住了,但第二天你回来再打开这个编辑器的时候,问D973号文件,它到底是什么东西,你看他根本不知道,当然你说哎呦,我可以通过文件名,但是当你的对象数足够足够多的时候,实际上这个东西你已经完全失控了。
注意啊,这里面你看到的还不是对象文件,它是不会重复的,对不对,那么但是的话呢,我们在这个世界里面,看到大量的是对象的instance,它的一个一个instance,那么好,就是那这个数量就会非常大。
所以你会发现在一个商业级的游戏引擎里面,当我们设计它的word ash的时候,我要对这么多的对象object,我要设计出很多种不同的view,比如说最经典的是树状的view,就是我把这些物体诶。
我给它进行归类对吧,我一个个目录去存储它,那么唉我有的时候会把它分成不同的layer,就是说啊这个是地上的植被,这个是城市左边的这个建筑群,那边的话是所有的地上的这个这个这个石头。
这样的话我用大的这个layer去去把它进行,归类的话,我也可以把它进行group,但其实这样的话还不够,有的时候我们还需要什么,还有search去寻找它,所以说其实你会发现一个商业级的引擎的话呢。
它对于这样的一个lisper objects的话呢,它会提供了很多种view,而对于artist来讲的话,我们会根据artist的习惯,比如说有的人我就是喜欢做这个啊,我是做environment。
我只是专门做天空大气系统的ALICE的那好,我会对其他的view我都不重要,我会让你们都锁住,不让你去边它,或者说我把它引掉,让我专注的去调整上面的这个天空,云和雨这种感觉的效果的东西。
然后我再把你接回来,我再看你的效果,所以说当我们去设计这样的一个word editor的时候,我们的object系统一定要把就是记得上节课讲过的,他我们的模型什么MVVM模型,对不对。
数据model一定要动起来,它的view其实可以提供很多种不同的view,完全可以根据艺术家的情况,甚至在未来可以允许不同的,这个就是designer或者artist,他用不同的view去管理它的对象。
那么其实呢,这个时候,当我们有了这样的一个view的列表的时候,大家想到最正常的情况是什么,就是我们最直观的编辑是什么,诶不是什么特殊的编辑器,就是在这个地图编辑里面,我选中一个东西。
我就想直接编辑它的属性,比如说我选择MPC,我想设置它的血量,对不对,那这个时候呢,我们在上一节课讲的schema系统就很重要了,就是说我点中它,我通过schema可以反射出来。
他身上到底挂了有多少的属性数据,那么我们的编辑器,可以自动的根据你的属性的类型,生成它所需要的这个编辑界面,所以说像这样的一个界面的话,几乎是所有的引擎的这个word editor总有一个小panel。
比如像ARIAL里面这个panel叫什么,叫detail对吧,像有的隐形叫properties,对不对,这都可以,但是的话呢这就让你去可以编辑这个东西。
这个呢也是当我们去构建word editor的时候。
这个window是一定要需要在的好,那么这最后呢,这也是就是说我们在做引擎的时候,非常重要的一个东西,这个是我希望大家在写引擎的时候,一定要注意的一个东西,就是counter brother,诶。
我这里面我要小小的这个这个自夸一下,我们的PILA对吧,我pick a真的是一个小到不能再小的一个引擎,就几万行代码,但是的话呢当时架构的时候这么小的引擎。
我们的团队还是架构了counter brother,当时我看到这个架构的时候,我还真的非常的惊喜,为什么呢,因为其实真实的一个游戏引擎是做什么的,可是给大家做游戏开发的,对不对好。
那么游戏开发的实际情况是什么呢,就是你想啊,我们一个游戏产品有几十个甚至上百个artist,然后呢我们会生产什么呢,我们会生产几十几几十件甚至几啊几几10万件,是几万到几10万件的不同的资产。
这里的资产有什么,有动画对吧,有三维的模型,还有什么呢,声音效果,还有我们想要的一些漂亮的UI贴图,动图这些东西,这些东西啊,它实际上是非常丰富和复杂的,那我们最直观的想这东西怎么管理。
其实在我刚刚进入游戏引擎这个行业的时候,我们怎么做呢,我们其实那时候没有counter browser,我们就唉有一个technic artist,他非常的厉害,他也很有经验。
它会根据你的产品把所有的资产设定好,比如说我那时做halo好,halo3对吧,所有的资产比如说objects,对不对,你的这个这个foolish就植被对吧,这个什么objects。
你去看你们还有什么vehicle载具,什么weapon枪对吧,分得很清楚,然后呢这里面再点进去,你再分哪些是哪个目录,是贴图的,哪个目录是模型的,哪个目录是原始数据的哇,我的天呐,就是你钻下去。
发现是一个非常深的一个树状结构,然后呢好我们的artist,当然我们的团队很很遵守规则,大家都把这个数据都放进去了,形成了一个很漂亮的一个ree view,但这个问题就来了,当我做完了halo3之后。
我要做halo4怎么办,对吧,黑龙寺不是所有资产都全部重新来过一遍,对不对,我很多资产还要从黑龙三去继承的,那好这你们的资产怎么去重用呢,怎么去共同管理呢,对不对,比如说我我一个艺术家在做黑楼四的时候。
我想用黑龙三你们的某一把枪,哎呀,那我还得到那个目录里面去找,那好了,那这个资产到底应该放到黑龙三的目录,还黑罗斯的目录,你讲不清楚了,对不对,而且这个目录结构呢一旦设置好。
很多时候他是3年到4年前有一个人设置好的,他很多时候是不能预判整个游戏发展到后来的,这种复杂的变化对吧,我们后面会产生很多很多不同的需求,所以差不多在这个就是说小10年前吧。
就是大家提出了这个content browser这个想法,实际上在我看来,在这里面的话,我们当然还会支持这种基于文件夹,文件夹的这样一个结构的东西,但是它更多的只是个view。
而我们怎么去看待这所有的资产呢,我们会认为它就像放到一个巨大的那个,ocean的里面,一个池子里面,然后呢这些资产扔进去,你只需要知道它是你要什么东西,你要它叫什么名字,然后你就能检索到它。
它你就能够去挂了它,然后呢你可以根据你不同的项目,形成这个资产的一个view对吧,这个view你也可以用树状去管理,但是没关系,这资产放在那儿,你不用管,甚至这个资产都不需要放到你的本地。
它可以放到一个数据库里面,其实那个在最早我刚开始我们在加引擎的时候,最早学引擎的时候,现在还在美国的时候,我们就很有很有兴趣的研究一个概念,就是说诶我们要不要在本地都不要存这些资产。
因为这数据都特别特别大对吧,我们把它放在一个studio的,一个中央的这个数据仓库里面,然后呢每个人你需要用到什么资产的时候,你只是把它用到你的内存里面,因为你本质上是要跑个游戏嘛。
这样的话就避免就避省去了这些几个T的资产,在各上百台机器中来回考的这个时间,而且的话还有很多的预计算可以提前做掉,但这个我今天就不展开了,但是这个content browser的话。
实际上就是这件事情的一个,最重要的一个解决方案,也就是说我们真的把这个是asset,从一个静态的文件目录变成了一个资源的海洋,所以说ocean这个词的话,其实在现在很多现代游戏引擎的企业里面啊。
游戏公司的企业里面都已经用到了,所以说的话呢,今天如果我们假设一个面向未来的游戏情的话。
那counter browser是大家必须要考虑的东西,那么其实讲完这些东西的话,大家基本上你再去分析啊,就是这个word editor上的各种小元件的话,你基本上也就清楚,What,你仔细看它。
他无非也就解决三个问题,第一个layout的问题对吧,我各种东西的就是摆放啊,一些东西的碰撞啊检测,还有呢就是以地形为基础的,比如说上面的植被,上面的这个这个decorator。
就是各种各样的小的杂物对吧,还有什么呢,还有我们要的environment,比如天空啊,天光啊,光源啊这些所有的东西,那么其实的话呢,这些东西呢就是一个最基本的WORDASH。
我们用的各种unit或者叫各各个系统,那么在这里面的话,大家很关心啊,那我这个what一下去写,他说最关键的东西是什么呢,啊第一步要写的东西是什么呢,那么其实如果架构没有问题的话。
那第一个要写的诶还真的是鼠标的选取,因为鼠标的选曲啊其实是一切的基础,实际上我们在用很多编辑器,你觉得顺手不顺手,实际上跟鼠标选曲写的好坏有很大的关系,很多时候鼠标的选取甚至是模糊一点。
让你就是让艺术家用起来更自然,那么好,这里面有两种比较简单的做法了,一种比如说我用recasting,就是说既然我这个世界里所有的物体,我都有包围盒对吧,那我就recasting呗,我就cos一下。
我就hit到他了,那这个的话呢实际上他用的其实是物理引擎,或者说我对这个世界的物理表示,他有的时候呢你说他要做的粗做一下是很快的,但是呢如果我要做得很精准,因为你们知道一个物体的形状是七扭八拐的,对吧。
我一个角色站在那儿,你在远处看着小小的就就那一小块儿,但是呢他可能有几万个三角形面片,然后我我用它的胶囊去做做选取的话,可能你想选的是他身后的那棵树,但是你发现你错误的选择前面的人。
所以这个时候呢有的人就有的引擎的做法,就是说哎我直接加一个额外的选取帧,就是说我把每个object id打在这个frame buffer上,然后呢你就去取到那个像素,取到那个问题就可以了。
这个方法其实就是哎这就是刚才我讲的,就是你如果引擎跑的是editor mode的话,你可能就要加一个这个extra的pass,去渲染这样的一个带有object id的这样一个texture。
那么这个肯定会费一点,但没关系嘛,一般来讲我们做做编辑时候,用的电脑会比玩家的电脑会更好,就是说大家如果你做过主机开发,就知道,比如说像那个PLAYSTATION和XBOX的话。
它都有一个叫开发者dev mode,就是开发者版本它额外的跟以前内存,但是的话呢我们讲我们的开发者,PC的话也是一样的,我们会额外的加很多内存,都配最好的显卡,所以我们的程序员经常会犯的。
一个一个踩了一个坑,就是说诶在我的本机跑起来完全没有问题啊,为什么在用户那边电脑卡呀,很多手是因为我为了能做开发,做编辑用的这种电脑的话,配置都是比较高的,artist有时候也会这样,但没关系。
这都是细节,所以其实呢首先鼠标能选中一个物体,这件事就得认真写一写,但这里面有个细节,就是说,我们假设这个场景里面有很多透明性的物体,打个比方,比如说很多particle对吧。
你想选中国particle怎么办,你想选中一块玻璃怎么办,如果按照我们之前讲的说透明物的话,它是不写入DEBUFFER的,对不对,他会被直接过滤掉,所以这个时候的话呢。
你们要需要写一些特殊的代码和逻辑去表达它,举个例子,比如像particle很多引起你的做法怎么办呢,哎我在party发生器那个地方,我作为一个虚拟体对吧,其实你选中的不是那个particle。
你选的可能是下面那个根的那个虚拟,你把它选中就给拖来拖去,拖来拖去了,那么对于其他的一些更复杂的选取的话呢,一般来讲我们都会有一些特殊的code来解决它,所以真的大家再做一个,就是游戏引擎的选取的话。
你会发现你要考虑的情况下特别的特别的多好,那其实呢当我们可以选取一个物体的时候,大家会发现,就是在游戏引擎里面有大量的物体的,我们叫做transform操作,什么意思呢,就是把它平移旋转,还有什么呢。
放松对吧,这个在我们在一开始讲那个object的时候,我在讲物理讲述的都讲了大量的这个这个东西,但是其实在做word ash editor的时候,这些地方反而是特别容易出问题的,为什么呢。
因为这个地方的话就是有大量的,比如说3D max maya,包括像其他的游戏引擎,给我们的artist的,形成了非常多的一些优良的操作习惯,这些习惯都是经过很多项目常年总结下来。
你会发现就是一个简单的旋转,那当你按哪个热键会出现旋转的空间,旋转的空间,当你的鼠标往上移动的时候,移动到那个那个get的百分之多少的时候,诶,它的X轴的旋转还是Y轴的旋转,Z轴的旋转会被高亮对吧。
都会这个有很多讲究,如果你做的不好,别人用起来就非常不认识,我给你讲,大家讲个小例子,就比如说在我们在做旋转的时候,你会发现我只要鼠标一动就旋转好了,对不对,诶但是我们的设计师需要一个模式。
是说我希望整度数旋转,比如每隔五度旋转一下,这样方便我什么呢,诶很快的对齐,比如说90度,45度,这个180度是吧,135度这几个常用的度数或者是30度,60度,所以这些东西的话呢。
就是如果真的想写得好的话,很多时候你会写好几个月,而且很细心的打磨,所以这个地方为什么跟大家去讲呢,这也是说其实在我们在真的做一个word editor这样的,或者说一个工具链的时候。
它其实大的框架很容易讲得清楚,但是的话当我们真正去写它的时候,你会发现你要想写得好,还是有很高的这个门槛的,这也是就是说商业级引擎,让大家觉得很敬畏的地方好,那么接下来我们有了这样的两个工具。
我们就可以摆摆layout了,对不对,那接下来我们就说哎,我们地形和地形相关的一些吧,地形的话在前面GRX的那个那个那趴的话,大家都知道地形我知道很简单,不就是一个高度图嘛,对不对。
高度图无非就是个high field,再加上一个texture吗,对的确实就是这么简单,然后呢你再加上这高度图到底怎么生成的呢,那我在前面讲了那个PCC对吧,用程序化自动生成,但实际上呢在现在游戏中。
很多时候我们可能还要加很多的其他小工具,那另外一个这上面不止不止是一个山川河流,对不对,我们有大量的这种植被啊,大量的地形的变化呀,这些东西是怎么生成的,那在我们去构建一个word editor的时候。
我们最核心要提供的模块是什么,这里面呢我只给大家点几个,比较常重要的一个模块,那大家首先猜到了就是哎对high brush,就是说我能够对高度进行这种刷。
那这个大家想象一下1heat press是不是非常简单,对不对,定义好了吗,一个追杀嘛,或者一个平台删,我就给你拉起来嘛,但实际上当大家对于一个有限密度的这个high field。
这个网格进行做笔刷操作的时候,你会发现对这个信号进行合理化的,smooth是最重要的,也就是说你会发现艺术家,你你你觉得你提供了所有的药的形状的功能,但艺术家说我总是拉不出我想要那个山的形状。
因为其实你们的差距并不是你的笔刷种类,而是什么呢,是你拉出来之后,其实艺术家希望他的过度尽可能的自然,那这个自然是怎么定义的,所以这个smooth就是有很多的细节和讲究。
包括大家想象一下我们的high field,那个船狗是斜着的,一个个过去的对吧,实际上它它你可以理理解成这个布,它本身是沿着某一个轴向被切割过的,当你去拉高度的时候,拉的不好,你会发现它有个很明显的。
沿着你那个选择45度切向的,那个那个过渡角,你就能感觉到那个height那边的,是有点ZZ的那种感觉,所以其实的话呢,如何去有效的,就是让这个刷出来的山看上去更smooth。
更自然的话实际上是个high的笔,刷一个很重要的东西,另外一个的话呢,也是我们在实践中发现的一个点,就是说其实艺术家很多时候希望的是什么呢,他也需要一种可扩展的能力,虽然我们作为技术人员。
会给大家提供很多的笔刷,但是当我们真的写一个游戏引擎的时候,我会强烈建议大家提供艺术家,可以自己导入一个高度图,自己定义一个笔刷的能力,其实这个东西会让他们乐此不疲,当然了。
就是大家如果研究一下胡迪尼的话,你会发现就是说这方面他做的更加的强大,这也是就是说当我们去做工具的时候,首先就是不要专注的是哎我的算法多么的厉害,而是说我的这个东西可它的扩展性有多强,知识速工具。
首先脑子中要想了一个问题,那么另外一种笔刷呢就是非常非常常见,就是叫instance brush,就是说刷各种各样的实体,比如说刷那个小的那个那个detail对吧。
刷decorator就是地面上的那个小小草,当然也包括刷这个tree,那么这个东西其实是一个非常直觉的东西,就是当我要大面积的刷草种树的时候,我就会用这个方法去做,但这里面会有个很有意思的点是什么呢。
就是说啊首先他这个方法非常的简单,非常的好对吧,比如像刷数,我一下能刷很多很多输出来,那么每一棵树都是独立的存储,这样的话其实我真的能实现,就是说当我去看它的时候,它在这个位置。
我游戏跑起来它一定在这个位置,这个数现在是一个偏黄色的树,游戏跑起来它一定也是偏黄色的树,因为这些所有的属性全部定就是静态的,放在那儿,那这个时候如果我对这一棵树不满意对吧,我或者说说想挖一条小道出来。
那我可以上手一个一个去改也没有问题,所以这是instant base的一个非常好的一个方一个点,但是它的缺点是什么呢,就是啊如果大家以一个实战型的游戏来看的话,比如说你方圆几十平方公里。
你会发现光你把这些树的位置去存一存,它的内存占用就已经非常大了,然后的话呢它有很多的预处理,其实非常的麻烦,但是呢这个东西的话呢,后面可能要用一些PGC的方法去解决它,那这里面就不展开。
但这个呢不妨碍就是说instant笔刷是游戏的引擎,一个很关键的一个笔刷好,那么另外一个呢我就不展开了,就是说实际上这个听上去很像有心情了,因为具体的算法我在图形学科已经讲过了。
就说哎你需要对光大量的光源的摆放,其实现代游戏引擎啊,随着我们的GPU能力越来越强,我有时候觉得我们越来越像那个电影行业,就是你知道,就是当我们在电影里面拍摄一个场景的时候。
实际上我们的艺术家会布置很多辅助性光源,会把那个角色刻画的特别好,或者会把那个就是说呃,某一个场景的气氛渲染的特别好,其实现在游戏研发的时候,很多时候气氛都是靠这种光啊,滤镜啊,包括这个天空的云啊。
天光啊打出来的,那这些environment的话呢,实际上都是啊有各种各样的插件来协作去完成,那么我们今天再去做这个word editor的时候,一定要给这些插件留下空间。
其实呢这里面就是what edita,我认为就是大家在在思考的时候特别容易忽略,但是有很重要的一点,就是说实际上我刚才讲的这一个个的插件,你说他坐下来难不难,其实不难,因为你知道了前面所有的这个算法的。
对不对,真正难的是什么呢,哎这些东西在于彼此是有一些规则的,举个例子,比如说我们在这个世界里要修一条路,诶,这个路就有很多规则了,比如说路上不能长树,对不对,是不能树长了路中江。
而且呢我的那些杂草也不应该长在路的两边,对吧,然后呢这个路我画出来,我认为是一个方向,对不对,但是如果我的train有高低起伏的话,我这个路不能够什么逢山开山,逢水架桥对吧。
他应该是沿着这个terrain的起伏有一个起伏,但是呢他又要修改tern,为什么,因为大家知道路得平嘛对吧,你头上有的时候是斜的,你你们没有很少看到那个路修的是倾斜十度,15度对吧,那所以路实际上呢。
它既要符合那个terrain的高低,他又要在turn上进行一个切割的这个操作,然后呢还有什么呢,就是说诶就是说我们的这个就是说啊,我们的一些石头或者是一些其他的东西的话呢,就是它应该碎石子。
它应该沿着路的两边有一个路基的这样的东西,所以说其实啊一个最简单的一个roll的系统,大家理解一下,我们在上节课讲rose系统很简单对吧,你就拉个LIN就完事了,但实际上你真的在一个word里面。
做一个rose系统的话是很麻烦的,大家说诶那我可不可以不处理对吧,我很简单,我大不了,首先把路弄好之后,我开始artist上手,该砍树的砍树,该把decade清理掉,清理掉,对不对。
然后turn我上手去修,同学们想象一下这个工作量是不是非常大,OK没关系,我我我我忍受得了,这工作量很大,但第二个问题就来了,这个问题其实也是更严重的一个问题,就是说今天我作为一个lol artist。
我认为这个路这样开是有道理的对吧,但是我的designer,我的设计师说你录这样修的时候,我的那个比如说这个这个这个战斗,这个combat就没法打了,就敌人直接就冲过来了对吧,我我得在这边做个拐角。
这样的话呢我可以在这边设埋伏对吧,这样敌人那个大炮不能直接射到我,这样的话我的游戏才有的玩儿好了,设计师那个那个那个LEVELIST被要求重新改,这个这个这个录的这个方向的时候,大家知道吗。
这个时候就整个就完蛋了,因为你前面做的所有的工作全部得重做一遍,所以其实我们必须要用一种procedure的方法,就是程序的方法自动解决这个问题,而这个时候怎么办。
哎唯一呢就我们就是一套rule system,就是我们通过一套复杂的这种GRAF,把这些入都表达出来,然后呢我们把原始的数据分层分的很清楚,比如说这是你的画好的tree的分布对吧。
这是你的这个road的分布,这是你上面的这些object的分布,因为我们不希望这个TRA,涨到这个这个房子里面,对不对,我们希望房子周边多少米之内不能长树好,包括你的河流水在哪里,我也标标注出来。
然后呢,这些所有的地形元素我全部都有,之后我交给计算机,用我的规则体系生成一套我们想要的,这样的一个合理的数的分布,这个时候这个效果才是对的,这件事情讲讲很简单,其实你真的让它简单生成一下很简单。
但这里面我个人认为,一直以来我一直在思考或者想解决的一个问题,叫deterministic,什么意思,就是说当我改了一个局域的时候,如果我这个数的分布,因为树的分布,大家希望是随机的嘛对吧。
但是呢我希望其他已经生成好了,我已经满意的地方,那些树不要再全部重新生成一遍,因为有的时候我对你上次生的结果是很满意的,我只想改个局部,所以说如何能保证这种generate data。
它具有一种叫做locality,就是说局部性其实是一个实战化的,这个就是word editor很重要的一个一个一个属性,那在这里给大家,因为这门课的话呢,我们只是给大家打个基础,让大家意识到。
就是说其实环境编辑最重要的就是这套rule system,那给大家看这个别人做完了一个结果,我觉得这个结果还是蛮impressive的,其实但这个呢,实际上已经不算是什么先进的技术了。
基本上商业性引擎都要提供这样的功能,大家可以看到他一上来再刷这些植被的时候,他会很快的检测到,就是有路有石头的地方,它就会那个让开,包括像这么大件的树,它也是这样,而且呢。
这个时候他如果对这个路进行改造的时候,所有的植被都会相应的发生变化,其实这个技术差不多在十几年前的哈,大家就开始在研究,到今天的话呢,其实特别是基于这个DEPLANAI的,这些技术的成熟啊。
实际上这件事情已经是非常非常的,这个will study problem,就是大家都已经解决的相当好的一个问题了,但是这里面真正难的问题是什么呢,就是说如何去定义一套形式化的语言。
让我们的设计师能够定义这套规则,包括这套规则很简单很易懂,很好维护,这其实是一个很很有意思的,而且这里面再讲个游戏的细节啊,就是说真正在啊我记得罗没记错,应该十几年前吧,那个CRYTEK引擎的时候。
他们就有很多人在做这个东西,他们要精细到什么程度呢,就是说我们在热带地区的植被,它应该是什么一个规则对吧,我到了高纬度寒带地区的植被是什么,东半球是什么,西半球是什么,对吧。
它你会发现它的规则都有一些细微的变化,包括比如说我们用这种方法自动生成,比如像城市对吧,那其实不同的这个亚洲风格的城市,日本风格对吧,比如说这个这个欧美风格,欧洲风格和美国的这个大都市风格。
都完全不一样,所以的话呢这里面其实真的钻研下去,就会非常的有意思,那么其实呢刚才讲了这些这么多东西啊,实际上他都不可能一上来,全部写到我们的word action里面,对不对。
那这个时候的话呢我们就明白,我们需要用plugin这个机这个机制,那事实上在大量的商业游戏的,商业软件的这个实践中,我们都会用这个plugin这个机制,比如像著名的qt对不对,然后呢像这个浏览器。
像我们的ARREAL都是用这个插件的结构,那么实际上的话我们再回头看,我当我们去构建一个word extra的时候,你会发现啊,你看到的是一个矩阵,这个矩阵里面的话呢有两个维度,一个维度是什么呢。
各个系统,比如说mesh的编辑系统对吧,particle的系统对不对,我们还有这个动画的系统诶,你会发现它正好和我们以前讲object component里面。
一个个的component类型发生了这样的一个勾连,对不对,诶其实里面还有一个纵向的维度是什么呢,比如说我要编辑一个NPC对吧,我要编辑环境,你们的这种像bird这种,我们叫做那个叫做这个这个群。
叫种群,叫群,就是那个就一群物种呢叫那个词叫什么叫herb,还叫什么一个词的那个系统对吧,比如说哎我们还要做其他的天空这样的系统,那你会发现也就是说这个纵向的这个呃,横纵纵向的这个各种类型的物体。
和横向的各个系统之间形成一个交叉矩阵,那我问大家一个问题,那如果我们要给一个word editor设计plugin的时候,我们到底是应该按照这个纵向的,object类型的去切分,还是按照横向的。
就是说各个系统进行切换,比如说party system来进行切换,那其实这个问题的答案呢是都要,这也是今天我这节课想跟大家具体讲一下,就what editor里面plugin在设计的时候。
大家需要考虑的问题,因为实际上举个例子,比如说party system,大家想想看,当我做好了一个word的架构的时候,party system是不是最好用plug init形式单独做。
不要把它变成word or的一个内嵌功能,因为你可能有各种各样的party,比如说我做了一个普通的一个系统,对不对,我今天发现显卡特别的强,我想实现一个GPU driven的particle。
叫GPU particle,那么GPU particle呢,它可能会和一般的particle有一点点区别,那最简单的做法是什么,我要通过一个plugin干,将来对吧,我的形式会发生变化。
那么那个但是的话呢,比如说今天我要做一个这个,就是说诶一个NPC的行为,那NPC行为的话,它实际上可能当我想这个插件我想写的是说诶,你可以直接选择这个NPC的职业年龄。
他的所属的这个这个这个他的行为模型好,这个时候我想影响的是什么呢,诶我要影响的是我要随机给它一个外观,我要随机他一个性格,我要我甚至要影响他的animation,他的AS的所有的行为对吧。
包括他可以交互的东西,所以说其实啊在一个真正的word editor里面的话,我们实际上要支持这种矩阵性性的,这个数据的支撑访问,让任何一个plugin能够纵向的,横向的都要去对这个世界进行进行影响。
这里面就回到一个非常有意思的问题了,就是说大家如果学过这个软件工程的话,应该知道就plugin其实有很多种模型对吧,那这里面有大名鼎鼎的,比如说覆盖模型,对不对,就是说我新版本的plugin。
就能够把老的这个plugin的功能全部盖掉,直接用我的功能,那这个东西在游戏引擎有没有用,当然有用了,对不对,比如说我今天要做一个地形编辑O引擎,原神提供了一个版本。
但是呢今天我要做一个这个地形编辑的话呢,我希望我想做一个像小小星球这样的一个东西,就是我希望整个地区地面全是curve的,然后呢哎我呢是能形成一个SOPHIA,这样的话我的所有的摆放都在上面可以去做。
那这个时候就意味着什么呢,哎意味着你的这个新的地形的plugin,最好能够覆盖掉以前那个老的party,你可是你要解决的问题我是完全不一样的对吧,那么他在parking还有一个模式是什么呢。
我们叫做这个啊,Distribute,就是说所有的plugin都是独自工作,每个人解决自己的问题,互相不影响,最后结果合到一起,那这个这个模型就更不用讲了。
大家想象一下在我们的word editor里面,是不是大部分的plug in都是这样的,比如说我做particle的对吧,就跟那个地形没有太大关系,对不对,那我是做那个就是说其他的打光。
我比如说做那个light的这个部署的plugin,可能跟这个particle又没有什么太大关系对吧,所以其实的话呢我们的plugin,大部分时候,大家感受到的其实都是这种分布式的。
就大家分分头自己把活干完就合到一起来去,来那个分公式的,然后最后形成几个协作的这样一个机制啊,这种模型我们是不是在word里面都要用到,对吧好,那这个时候还有一种著名著名的方法叫pipeline。
就是我的数据一个串一个一个串一个,那我们在做这个这个editor会不会用到呢,唉实话实说,我们会用到,为什么呢,当我们进行这种数据处理和导出的时候,打个比方,比如说我们要做一个物理这个物理的效果。
那物理的效果它的前面的东西是什么呢,我要对这个世界进行partition,就是比如对一个对象进行几何的切割,对吧,我希望用一个几何的插件,形成我想要的碎片的类型,那这个呢我的物理的那个pk。
更多的只是设置它的物理属性,那这个时候实际上我的那个几何的那个plugin,插进来之后,它的输出输出就是我的输出,而它呢会插在我前面,先对数据进行处理,那么最后一个这就是洋葱圈了,洋葱圈的意思就是说。
哎我要和别的pokey进行输入和输出,同时操作,那这件事情听上去好像有点抽象了对吧,那这么复杂的结构我们会用吗,刚才我讲的那个比如像rule system对吧,他其实就是有点像杨同学。
为什么他几乎会和所有的plugin都会talk,他要读那个地形的笔刷的那个plugin对吧,他要读那个地形,他要读什么呢,所有的decorator那个plugin就是刷direct。
director的plugin对吧,他需要那个读那个所有的那个tree啊,foliage的这个plugin我都要读诶,我根据我读来的数据之后呢,我自己对它进行处理,处理完之后我还把结果反过来写回去。
改写你们的状态,所以这里面我想跟大家讲的东西是什么呢,就是说今天当我们真的站在一个引擎的视角,去架构一个就是world editor或者各种各样的editor的时候,大家在你的设计结构上。
一定要保持一种很强的开放性,因为当一个真实的游戏production的需求来,他对工具的要求的话,实际上各种plugin的模型它都会用到,所以千万不要上来,先给个假设,说,我要求所有的BGIN都怎么怎。
么按这个模式去走啊,至少以我个人的工程实践来讲的话,我觉得这事好像搞不定对,所以说有的时候我想就是做软件工程,有的时候真的就是在啊,我认为在两个很精分的需求中间达到一个平衡。
就是说我们去追求这个软件体系的那种,严谨性和一致性,但是的话呢我们要理解工程上我为了解决问题,其实我明白我的scenario非常的复杂,所以我必须要妥协,我必须要允许很多种不同的pattern。
在我的系统中能够和谐地共存,所以这里面就讲到一个很有意思的问题,就是最近我们哦,你知道我们程序员万年不变的话题是哪个语言,是世界上最好的语言对吧,那么有的时候我们会看到有些评论说,哎这个从学术上讲。
这个语言设计的不够elegant,就是不够优雅,然后我作为一个工程师的话,作为一个码农,我就很不屑于这句话,我说优雅有什么用呢,一点用处都没有对吧,他不能解决我的问题,所有能帮我解决问题的语言。
他都是好语言,所以说其实当我们去研究这个plugin的设计,pattern的时候,我们我我会建议大家,秉持着这种实用主义的原则,任何一个架构只要能解决我们的问题,那就是个好的架构。
其实plugin里面的话呢,其他的问题其实真的是非常的复杂,举个例子,就是说,当我们一个庞大的一个游戏引擎体系,发育起来之后,你会发现引擎的内核你会不停的升级对吧,你的版本结构,你的数据我会升级。
但是呢你很多plugin它并不能够严格的保证,按照你的这个版本结构进行升级,对不对,那这个时候最理想的情况当然是,我每次引擎一升级,所有的plugin全部升级一遍对吧,但这件事情其实做不到。
特别是对于那种大型的商业引擎,那么都有成千上万的人为他写插件,那这个时候这些插件的不同版本的兼容性,将会是一个非常大的问题,所以这也是希望大家在一开始设计这些接口,的时候,就要考虑的清楚。
比如说我们对接口进行版本编号,你这个pk只用了我这样的一些SDK的话,这个SDK是有个版本号的,那个版本号只要不变的话,你的plugin我认为是有效的,但是如果我发现我要变了的话,我就无效。
但是呢这里面有一个很很难的挑战是什么呢,就是说作为引擎的研发者的时候,你虽然开放出这些接口,你根本不知道那些plugin的老哥,是怎么去用这些接口的,很可能他用了一个你完全想不到的方式,这个把这个接口。
这个这个去修改了你内部的数据好,你也不知道,当你对你内部的结构进行升级的时候,那个老哥的东西可能直接就崩掉了,但你认为我的接口函数没有变啊,我柯南给你做的服务都提供了呀,那我为什么会崩掉呢。
但有的时候你就会产生这样的问题,所以简单来讲的话呢,就是说其实一个好的,就是一个引擎的设计的话呢,在这个地方是特别能够体现出它的功力的,这一点上,我实话实说,我认为还是蛮难的,非常难。
所以同学们在一开始去加个游戏引擎的时候呢,也不要对自己提那么高的要求,说句实话,至少pica没有认真的考虑这个问题,我们做的还是比较简单的,因为怕同学们太难,但是呢当你从业,比如说五到10年左右的时候。
诶,你确实可以认真地考虑这个问题,我个人认为就是说呃编程10年以下的话,考虑这个问题为时过早,真的就是我自己一直认为,就是说我不认为我不建议,就是程序员写了几年代码之后,就觉得我要做管理。
实际上技术开发了很多东西的话,你没有10年到20年的沉淀的话,很多时候你很难理解他的这种复杂度,它能体系的那个丰富度,所以的话呢架构真的是我认为架构师是程序员,程序员的终极归宿吧,OK好。
那这就是这个我们讲这个,这次详细的结合我们的word editor,跟同学们讲了一下这个plugin这个结构,那接下来呢给大家讲个有意思的东西了,就是说诶我们在游戏中的话。
怎么样去表达一种线性的这个叙事性的东西,因为其实啊在就是我们讲在游戏中啊,一个最重要的挑战是什么呢,我们叫做startling对吧,其实我经常嘲笑,就是很多3A游戏做到后来他不是游戏了。
它就是个交互电影,确实是虽然我个人是觉得哎呀这不是游戏啊,这违反了游戏的精神,但实话实说,我作为一个玩家,我还是很enjoy的,而且这让我云游戏起来一点都没有罪恶感,我觉得这个游戏我就不需要买了。
我云完了之后,这个游戏80%以上的内容我已经知道了,为什么我还辛苦自己受苦,完成了剩下的20%的交互部分呢,所以说但是呢这不妨碍就是说在游戏世界里面,我们的叙事非常的重要,你们可以看到。
就是我们的游戏做的越来越像电影,就是每一个镜头,每一个角色的动作,每一个光每一次爆炸对吧,每一次这个这个入场都是被精心设计过,而这一切的东西发生在哪里呢,它其实啊是发生在一个时间轴上。
也就是说在这个时间轴里面诶,到什么时候我开播放什么一个背景音,这个时候我应该播放什么样的一个爆炸的效果,诶这个时候我应该希望角色做一个什么,比如说打招呼或者开枪的这样的一个动作对吧。
或者说躲进掩体的一个动作,那这个时候其实啊你会发现我们有大量的元素,或者parameter,是在时间上在发生了这样的一个变化,那这里面的话呢我就举一个例子,因为这个东西讲的有点抽象。
那我就用一个比较看得见摸得着的例子,就是大家看到虚幻五里面,虚幻里面很重要的概念叫sequencer对吧,在这里面的话呢,其实呢它对于每一个物体在这个世界里,object的变化。
我定义了一个东西叫什么呢,叫track,它当然在虚幻里我们叫做actor了对吧,那在这个track里面的话呢,实际上我们对它的每一任何一条属性,都可以定义一个在时间轴上的变化,然后呢。
当我们把这些变化集中在一个时间timeline上的话,我设定了一些叫ky friend的东西,就是它每个关键的变化节点,我在这个key friend之间差值,你用线性也好,你用那个就是那个QQ差距也好。
那都是我们的选择,那这些东西结合在一起,我们就形成了一个sequence,那么这个sequence的话呢,实际上我们就可以用这些简单的东西,最后展现出一个让你觉得很丰富的,这样的一个世界。
其实你可以理解成就是说我今天要拍一部电影,那我们正常的想法就是诶你有三个演员对吧,好123action,所有人开始说话,对话动作对不对,但是在游戏世界里面,这件事情是非常难的,我们怎么做,我们会这样做。
OK演员一,OK你的动作是走到桌前拿起书开始读,然后呢,这个整个时间是多少秒,是五秒,好,这个走到桌子是几秒,那个拿起书是几秒,读是几秒,诶,这个2号演员你你你要做什么,你要坐到椅子上开始张口说一段话。
这段话说的几秒几秒好,2号演员全部按照要求做了,第33万元呢是坐在他对面,坐下来也开口讲话好,当我把这三个演员的timeline align套一起之后,诶,你发现当我一点一个播放的时候。
你看到的画面就是有一个演,有演员一在认真读书,演员二和演员三,在图书馆坐在椅子上开始聊天,你看到的东西是在同时发生,但是呢真正在游戏世界里面,这些东西是一次一次一次一个个去做的,这个设计非常的有意思。
这就是我经常跟大家讲,就是为什么游戏这么难做,就是作为用户来讲的话,你看到的一件事儿都是诶好像顺理成章,就是应该这样,但是在游戏这个引擎和游戏世界里面的话,所有的东西我们都要用零和一,用一行行脚本。
一行行代码,让他一个一个要素的生成,当这些要素合到一起的时候,还要非常的合理,你觉得这个事情符合你对自然的认知,所以我经常讲就是我们是躲在零一之后,或者说我们是躲在像素之后的人。
那么这里面就举一个很简单的例子,就比如说我们如何让一个小鸡在这里面动起来,对吧,那以按L为例的话,你首先是要把这个小鸡绑在这个,这个就是object上面去,你绑到audio,那接下来诶我这边有个动画。
它也播放不了,我们后面可以播放一下,那么接下来的话呢,就是说哎我们实际上要这个用一个东西,我来用一下鼠标来,我回到上一个吧,就是我先把这个小鸡绑到绑成一个track对吧,这个时候的话呢。
哎我这个小鸡就开始可以定义他的行为了,然后呢我把他的transform把它的位移绑上去,它就有了一个叫property track,好来,这个时候的话呢。
唉我们构建了这样的一个property check的时候,我们把这个transform绑上去之后,诶第三件事情我们就可以做了,第三件事情我们可以做的是什么呢,哎我们可以给这个小鸡。
它是在每个不同的位置设置一个k free关键帧,大家如果看完我们动画的话,就觉得这个太简单了对吧,我也知道啊,不就是个位移吗,我设置一个一个在第一个时间轴上放在一个位,一个位置。
第二时间轴放到第二个位置,那你这个沿着时间轴一走,它不就形成了一个差值了吗,对很简单,那这个时候如果我对小鸡希望形,形成一个路径的规划的话呢,那我就可以非常的简单,那我实际上就可以让他在几个K分之间。
来回走来走去,实际上你可以看到就是说在各个关系中,我们改的到底是什么呢,就是它的一个component的一个parameter,就是transform,它的位置可以来一句。
但这里面这个case非常的简单,这个小鸡看上去特别特别的傻,但是呢同学们我们看到的游戏里面,那些刚才我一上来放的那个视频中,比如说那个黑黑客,那个黑客帝国reload里面的那些酷炫的表演。
实际上就是一个一个角色,一个个效果在这个timeline上表达出来的,包括像刚才那个战地那个视频里面,你看到哇真的是很棒对吧,很精彩,所有的事情都在发生,但实际上呢这就是很多个设计师。
他在一帧就是一个K分,一个分成员,一个object一一个object把它序列放好,最后我们看到的这样的一个结果,所以其实这个东西啊,对于整个游戏的工具体系来讲是非常重要的。
就是工具体系实际上有一大类的需求,就是在时间轴上去让parameter动起来,或者让对象动起来,这里面不止讲的是剧情,包括我们讲的生效,包括我们讲的游戏里面的一些UI对吧。
其实UI的话很多时候你点一个东西,它后来发生了一系列的事情,比如说那个比如说举个例子啊,比如说你你暴击了一个人对吧,产生了一系列的什么击杀头衔,包括你who kill了谁对吧,暴击率是多少,包括对对。
我能看的见面,这一切全是在一个时间轴上去发生的,就UI体系里面也有大量的这种,基于timeline的这样的一个顺序,所以我们举了sequencer作为一个例子,就是让同学们知道。
就是说其实你看到那些复杂的这种线性的,沿着时间轴的交互,它都是这样的一个体系,就是说用了一个体系叫timeline,然后timeline里面的话,我们修改各个对象的这个属性,那么UI控件的话也是一样的。
你供它属性,那你控制那个光源,控制天空那个的光照,你控制这个你现在场景,你甚至这个一下子可以切换场景对吧,其实很多过场动画还是偷偷的,把场景都会换掉的,那么也是用了这样的一套架构来去发声。
在这里面引出我们非常有趣的一个话题,是什么呢,就是反射和games play,为什么大家看啊,其实刚才我讲的那个sequencer这个体系的话,它最核心的就是在时间轴上去调了。
以前component里的几个parameter,对不对,那这件事是怎么做到的,就是我怎么我的工具是怎么知道去修改,那个RUNTIME里面那个对象的那个数据呢,我这个中间链接是怎么建立起来的。
当然知道我们有schema,对schema只是帮你描述了,但是你得找到那个数据啊,你得set and get,对不对,你首先知道他当前的数据,你还要去改它的数据,哎。
这里面就引入了我们很重要的就是reflection,可以说reflection也是sequencer的一个foundation之一好,那么实际上的话呢就是在我们在做game play的时候。
其实你会发现在游戏中的game play,是非常丰富和复杂的,而且我今天作为一个引擎的话,其实我根本不会知道啊,未来基于这个引擎开发的各种各样的游戏的话,它会有什么样的一种EMPLAY。
比如说在这里面举个例子,我希望有个激光对吧,我顶上去之后它能发生什么事情,它能够射出一根箭,这根箭能够拉动,有什么东西,这些东西不可能写到引擎里面,对不对,那说同学们会说没关系啊。
我们可以用数据配置把这个逻辑配出来,实际上你会发现有的是玩法,它是用数据配不出来的对吧,就是说任何语言它的表达都是有上限的,数据本身也是一种语言嘛,那怎么办,我们要允许就是说那个我们的游戏开发团队。
基于这个引擎不断地扩展它的玩法,不断不断增加新的接口,新的功能对吧,哎这个工具我要必须要要要来支持他,那这个时候实际上大家最熟悉的东西就来了,就是说哎我们各种各样的。
就是基于visual的这种script语言,其实呢大家很熟悉的叫blue print了,blue print只是这个visual script语言的一种,实际上大家看我们现在的很多的引擎。
包括一些游戏之外的应用里面,都会用到这样的一个方法,什么意思呢,这个东西其实从某种意义上有点我们叫做啊,有点像现在很流行的一个概念,叫做低代码或者零代码开发,也就是说你不需要用代码。
你就可以构建你的东西,那么在游戏这里面的话呢,我们实话实说,我们处理的情况是最最复杂的,在游戏引擎里面,那么在游戏引擎里面,我们设计这样一个visual scripting语言。
我们最核心要解决的问题是什么,那么实际上是这个是呃,可视化编程语言的可扩展性,道理很简单,如果这个编程语言是预设预设好的,各种节点对吧,然后我只是去开放各种接口,让你连接这件事情难不难,你其实有点挑战。
但是呢可以做不难,但是他有个很大的缺陷是什么,就是说,就像我今天我要去加一个新的feature的时候,那我今天假设左边定义了一个角色,他就跳的这个一个角色对吧,那我在右边的话。
就需要在我的可视化节点代码中就说诶好,我知道每个人类有一跳这样的动作,那我明天说不好意思,我支持了这个角色,他还可以这个停止跳这个动作,那我是不是在工具这一层也要再加一行代码,使得工具里面那个那个节点。
他要增加一个一个接口,而且它能正确地调用那个函数,这个调用函数我一般我们叫做invoke对吧,那这样的话,实际上你会发现,就是说我们在这个一旦增加了游戏逻辑之后,我那边就会要不停的去修改我的工作单位。
当然我可以通过那个C加加的派生和继承,我只是不会用每次改它的基本结构,我只是派生一个新类,我可以支持这个事儿,但是工具那边的话就会变得非常的复杂,这就是一个不可扩展,不可维护的东西。
所以这个时候呢大家最喜欢的东西就来了,就是说诶反射,反射呢其实是游戏高级语言里面,一个非常常用的一个概念,这也是最近这些年啊,我觉得语言一个很大的情况,因为在早期的语言比较像汇编对吧,比如像C加。
我们是没有反射的,对不对,大家什么东西都是我们上来手写我的,我的感觉就有点像那个,我记得我以前在读书的时候,我们在幻想一种画面,就是半夜寝室里面那个亮的灯,有人在拿着小刀在光盘上刻出一个操作系统,对吧。
因为操作大家知道那个早期的那个存储,它都是那一个个那个词典嘛,我们只在YY那种最土法炼钢的感觉,但是呢其实那些比如像汇编啊,比如说像C语言啊,这些语言确实是他没有反射。
它实际上它就是一段非常native的代码,扔给机器就跑了,但是呢实际上当我们到java,到c#这种高级语言的时候,实际上我们全面的都支持了反射,反射,实际上也就意味着说,当我写黄银行代码之后。
实际上系统会告诉我说,你到底有哪些新的功能被暴暴露出来,这样的话当我们这个其他的调用者,它并不需要跟你的代码链接编译到一起,它实际上就可以,这个知道能够调取这些新的功能接口的入口。
这个是一个非常重要的一个,一个现代语言的一个拓展,而且这在工程上来讲的话,其实我记得我在呃是很早很早以前,我们在最早架前几代引擎的时候,因为我们没有用高级语言嘛,就是引擎里面我们都是用那个CC和C加加。
然后我们用了很多很奇怪的这个模板的hack,其实它的核心目的是什么呢,就是因为找到类似这种反射的感觉,就是诶我定了一个结构,定义了一些方法,我外面的接口我能够不需要跟你重新编译,我就能把你的方法找到。
我就能调用,你等我们有了反射之后,我们就知道,哎呀我们这些工作到后来全是无用功,那么反射怎么做呢,唉其实呢反射啊,这个待会我再讲反射怎么做啊,其实反射我们认为呢,它实际上就是在代码和工具之间。
在引擎里面构建了一个很好的桥梁,就是我的引擎实现了一些功能,它写好了之后,我通过网反射,我生成一个表,告诉我说你这个引擎开放了哪些类的接口,有哪些功能,有哪些数据,你可以访问。
并且生成了一堆的这个诶invoke,你去调用它的函数,一堆的这种set and get,你可以修改和改变它的变量,这个时候等我写工具的时候就会非常的简单,比如说我写一个我的脚本语言,我定义了一个。
我发现你们你定义了一个功能叫做人啊,这个人有很多属性对吧,比如说他的身高体重,他的血量唉,我都可以set and get,然后呢我发现你可以让他走跑跳诶,这些功能我都有,那当我在我的可视化脚本语言里面。
我创建一个节点叫做人的时候,它的所有的这些属性参数,节点全部都可以这个显示出来,而且还有一点什么呢,我们知道我知道它的类型是什么意思,就是说哎比如说像那个走跑跳是一个动作,那我就可以去invoke它。
它可能是个三角形的标记,就这个节点你动作流可以走过来,那么他如果是属性的话呢,它是个property诶,我可以显示它,我甚至可以编辑它,我可以找一个modifier,可以可以修改它。
比如说我把你的血量减伤这个武器的伤害,最后得再重新得到你的一个新的血量,我用一个脚本,用一个简单的贴那个那个visual scripting的这个图,就可以把这个算法给写出来。
大家会说诶我作为一个程序员,这个东西让我去写个代码会更简单,而且更好,第八个对不对,为什么你要用这种visual scripting的方法去解解决呢,这件事情的话其实让我也研究和思考了很久。
就是我以前一直都不理解,说其实脚本也很方便,我可以对这个引擎功能进行扩展,而且我作为程序用debug写的效率最高对吧,也很方便,而且我还可以def啊,为什么大家后来会用VSCOTT这个语言。
那我自己后来的理解是这样,就是说我们作为程序员的话呢,我们天然的会认为这东西很方便,但是对于大量的设计师和艺术家来讲的话,他们光光建立那一套语言的编译环境,包括确保按照你的语法去写,不会出错。
这个事情对他的门槛是非常非常高的,他们很多时候需要的是什么,就是这个块拖进来,你看到不同颜色的接口和蓝色的接口,连蓝色的线,红色的接口连红色的线对吧,红色对红色,蓝色对蓝色,三角对三角方块的方块。
圆形对圆形,其实对于他们来讲,是一种最自然的一种表达方式,所以的话呢我现在也自己被洗脑了,我认为就是说visual scripting,实际上是引擎未来发展的一个方向,因为它真的能够把引擎。
开放给足够多的这个用户,所以r reflection反射就是,如果你们认为这是一个正确的方向的话,它就是构建在引擎和工具之间的,一个重要的一个桥梁,好这个时候我们就讲一个有意思的细节了。
我们这个课程一般来讲是不会讲细节的,但今天为什么一定要讲细节呢,因为课程里面的同学们一直在插那句,我们说请请课程组织讲一下,我们那个PICO的反射到底是怎么做的,那今天的话我们就夹带点私货给大家讲一下。
就是在C加里面,我们到底是怎么实现这个这个这个反射的,这个事情呢,其实呢讲起来没啥秘密,非常的简单,就是我们实际上大家知道啊,就是我们所有的现代高级语言,他都要通过一个类似GP2规范的这样一个。
编译系统,把它编译出去,那么整个编译过程呢也不是我们自己能瞎写的,实际上他也有一套非常规范的pipeline,比如说你前面要进行语法分析,要passing对吧,你要生成这个s st抽象语法树。
然后呢你还要对它进行形成一个中间代码,中间代码再生成我们的target code,就是我们机器能跑的,那所以整个这套pipeline,已经在过去的几十年里面,有我们无数的先贤。
已经整理总结的非常的完善了,谢天谢地啊,正好还有大量的开源的这样的一个编译器,比如说C浪对吧,它其实非常的好,它可以把你的这个语言翻译成这个这个AST,就抽象语法书,大家仔细观察一下。
当我们给你一个C加里面的一个类,和它的变量的定义的时候,你发现没有,他经过了这个这个高C浪的这样的,一个分析之后,它会形成一个非常好被解读的,这样的一个一个一个就是语言的这个表。
它其实是树状结构的一个表,而这个表的话,那里面我们就可以很容易地把任何一个类,它的接口的函数,接口的这个就是他的那个member web全部提取出来,其实他这个东西是不区分语言呢,你其他的语言扔进去。
它也能处理,那好我们有了这样的一个东西之后,大家想想,我去生成我们想要的这个schema,应该是很简单的对吧,皮克洛呢我们就比较土,我们就选的是那个C浪,C浪,为什么选C浪呢,其实有很多原因了。
第一个它看源本身,而且很模块化,你可以自由的加载,而且呢它本身也是一个非常稳定成熟,也是被最广泛验证过的这么一个平台,所以呢我们PGA的选择就是选择一个A,大家觉得最简单最可靠的一个插件吧。
但我个人认为C浪是个很好的选择,大家甚至如果有兴趣的话,也可以通过这个皮克拉,你们怎么去用这个C浪的话,也能知道PC浪最简单的一个用法好,那么其实呢,那我们当我们把这个C加的代码,拿来处理的时候。
我们实际上就可以生成我们的schema对吧,这个schema,但是大家注意啊,就是在PICO里面的话呢,我们并没有显示的把这个schema文件存出来,我们只是在内存中定义了一个四维码。
大家可以找到那个数据结构好,那其实呢这个在讲一个细节,就是说实际上呢反射呢比大家想象的,要有一些更精准的控制,为什么呢,因为我们一个引擎代码对吧,就算提高了有几万行代码,那你们可能有几百个。
甚至上应该有几百个数据结构,我并不是所有的数据结构我都需要反射的,对不对,我们实际上很多时候是需要和资源打交道的,数据才要反射,那怎么办呢,哎我们通过定义一些描述词。
大家注意到在pillar里面有两个描述词,第一种叫做那个class,定义一个类,那个红写了一个红啊,然后这里面说我后面写了个FS,什么意思。
就是说我这个class里面所有的member variable,都要被反射出来,唉这个看上去没毛病对吧,但是呢实际上我们在定义有些累的时候呢,我们并不希望所有的memorable都要被反射出来。
为什么呢,因为有些变量并不需要跟内存啊,并不需要跟磁盘之间就文件之间交换,它实际上是我计算中间结果有这个有这个需求,对不对,诶,你在后面加个描述词叫什么呢,哎就是white list only对吧。
这样我就知道了哦,那这个类里面的话呢虽然有十个不同的,慢慢吧,举个例子啊,但是呢只有我看到的叫meta enable,那个那个描关键词的时候,我就知道哦,这些东西我要把它反射成我想要的那个,那个数据。
那这东西怎么实现的呢,这里面讲一个细节,这里面就不好意思讲个细节了,其实这个东西实际上是通过宏来,实际上大家如果对C加加语言有了解的话,你会发现其实我们的编译器,我如果是真的编译它ex e的时候。
这些所有的描述全部都是无效的,但是呢如果我们去编译它的这个,reflection的时候,我要获取reflection的时候,实际上我的if define,把它define成那样的一个标标识。
但这里面注意就是说在那个C浪,它提供了一个方法,就是你可以定义一个,attribute的一个特殊关键词,ash里面有一种类型叫做annotation,就是标记,然后呢你可以把各种标记打进去。
那你在你最后生成的SD代码里面,他会给你生成叫那个tribute的括号annotation,然后把你的文字放进去,我们只要检测到这个东西的时候,我们就知道哦,你下面到底想让我干什么,所以大家仔细看。
看上去非常神秘啊,一个C代码放在这,我就能生成所有的反射啊,这些东西,但实际上它就是一个非常简单的,就是我成员叫字符游戏吧对吧,大家会发现就是编程,程序员到最后对字符的非常的敏感。
就是因为就是呃我我分享一个小故事,就是程序员到后来基本上都有强迫症,因为程序员对什么这个缩进啊,什么时候打逗号啊,比如说大括号,到底同行不同行都非常的这个geek,都甚至为此会这么有劲对吧。
两方吵的面红耳脸红,脖子粗,实际上就是因为我们的这个职业属性,会让我们对这些东西特别的敏感,就是因为你看到所有精妙的游戏啊,这些东西它本质上它都是一个字符游戏而已,所以说这里面的话就跟大家讲一些细节。
就是让第一次让大家明白,就是皮克拉的反射到底是怎么做的,其实皮克勒的反射的话还蛮具有代表性的,比如说大家想如果想学习一下unreal的反射,怎么做的话呢,荣耀虽然比我们做的复杂。
但是它基础的方法和结构跟这个非常接近好,那么其实这里面的话呢,诶讲完了这个反射之后,大家就知道了哦,那我我给一段C加代码,只要加上你的这些特殊的标记,我就能够自动找到你们所有偶像的结构,这是没错的。
而且我还能生成它的schema描述,这也没有问题,但是呢这还不够,因为我的工序我要大量的去访问,修改这里的数据,调用你们的方法,对不对,所以呢我们要是每个reflection。
我要生成它很多的ACCESSOR,就讲你可以理解成就是三类函数吧,叫get set invoke,对不对,就是我是获取一些数值,改变一些数据,或者我找到一个方法之后,我把这个方法给调用一遍对吧。
invoke他一下,那么这个呢就牵扯到一个非常有意思的概念,叫代码渲染,大家想象一下,我们一个引擎需要反射的类可能有几十个,那我把反射做出来之后,那这些函数谁去写呢,如果这个函数变成了。
也是需要我程序员去写的话,首先这些代码其实非常的荣誉,第二个不是说好了自动化吗,说好了接口自动生成吗,你为什么又突然又让我去写代码了,所以呢这里面就有个很有意思的工具,叫做代码渲染了。
那么这个东西呢其实也不是什么高深的概念,因为实际上在web端的话,大家很早就发现这个问题了,就是我要生成各种各样的页面,但是呢它的逻辑其实是大同小异的,但是呢只是它的数据不一样,那我希望这个前端的代码。
它是能自动生成的对吧,比如像这里面我要显示两个不同,UI51改变的是什么,是三里面三个颜色的那个名字,其他东西我一概不变,那这个时候呢,实际上代码渲染是一个非常好的一个工具。
其实我现在都几乎找不到他什么缺点,反正它的好处是什么呢,第一个就是说能够大量的减少荣誉代码开发,甚至呢它会减少你犯错,因为渲染出来的代码一次性,第八个通过之后以后很少会出错。
就像我们做的那个schema系统的话,其实那个代码放在那差不多也快10年了,但是几乎不出错的,为什么,因为这些代码全是自动生成的,如果出错,他早就出错了,如果不出错,你就写10万行,生成100万行。
它也不会出错,那么还有一点是什么呢,它是非常完美的把数据和逻辑进行了分离,就以前我们在写代码的时候,其实有些东西我们认为是数据的东西,那我必须要写进去,对不对,但现在我们可以实现就是数据和逻辑。
更加彻底的decoupling,所以代码渲染就是,当我们在架构一个大型系统的时候,我一直认为就是能够通过自动化生成的代码,尽量的自动化生成,不要自己手写,因为手写的过程是不可控的。
很容易就是你昨天那个版本写的没有问题,后天那版本写出来就是有问题了,那么在PICO里面的话呢,我们用了一个非常有意思的小工具,就是那个mustache,mustache的那个英文的原意叫什么呢。
叫这个胡子,确实因为这个他要求你在描述你的代码的时候,加很多的这个大括号对吧,感觉像这个人套了很多大胡子一样,然后呢他通过你的数据的语法的翻译诶,自动的把你渲染出你想要的代码,这个东西其实非常的简单。
而且也是很稳定的一个系统,所以在我们的皮克勒引擎中的话呢,我们也这是我们真正实战的,在内存中生成的这个CHEMA数据,然后呢哎我们写好了这样的一个模板描述,我们就可以自动的生成它各种各样的代码。
更具体的细节的话,同学们就可以看,所以同学们今天啊基本上听完这两趴的话,如果大家的技术基础过关的话,基本上就能够猜看懂皮克拉的这个代码生成器,是怎么做的了,他首先就是调这个叫那个C浪对吧。
声称我们内存中的schema,然后在生成schema之后呢,我们根据我们预先写好的这些程序的模板,再调master生成我们大量的excel code,这样就能实现我的引擎里面,可以定义任何一个结构。
在编辑器里面就能互相看到,对吧好,那么基本上讲到这儿的话,我们的引擎工具链讲完了,就是这些东西,那么当然了,真实的引擎工具是非常复杂的,那我再讲下去的话呢,我觉得我讲的就基本上就是要这个。
什么引擎教学课程了对吧,引擎教学课程这个东西说实话我并不擅长,我不是个特别好的引擎的使用者,但是我非常有兴趣,就是架构讨论引擎的架构好,这里面的话呢我在这节课里面呢,我再额外的补充一个小小的一部分。
就是说,其实我个人认为就是在现代游戏引擎,有一个很重要的发展方向,叫做协同编辑,为什么呢,因为大家看现在的3A游戏啊,包括我们经常讲开放世界,这个数据量和数据的维度。
远远超过我们一个人能够handle的一个,这个这个就是这个能力,那这个时候呢,我们客观上就需要很多人共同编辑,那只要大家一共同编辑啊,这个事情就很头疼,比如说当你要编辑这么大规模的一个一个场景,对吧。
你你这个里面有大量的素材,这些素材可能有几十个,甚至上百个artist共同产生,那我们彼此之间怎么样的可以不打架呢,当然我们说我们全部用P4PCC对吧,proceed方法生成对的。
这个听上去好像很了不起,但是真正游戏的核心啊,它还是一个叫做novelty,就是就是说它具有一定的这个叫新鲜度,或者说叫做这个就是叫啊生动度了,nobody就怎么创新度,那么这就意味着说。
如果一个P7算法足够成熟之后,实际上他的pattern还是会很容易被玩家发现,所以我们还是需要大量的artist,他的灵光一闪的创意,但我这句话说的很有天一点为时过早,说不定那个按照阿拉马斯的想法。
2030年我们实现了强人强人工智能,nobody这件事情我们也可以交给那个AI去解决,这是有可能的,那我们的这个工具体系会再重新设计一遍,包括我们很多的artist可能会因此失忆啊,这是个很悲惨的故事。
那我们今天我们先假设强人工智能还很遥远,那我们实际上就还需要,就是很多人在一起共同协作,那怎么协作呢,那其实协作的话呢,其实最容易出的问题就是冲突,也就是说我去改了一个东西,和你改的东西发生了冲突。
所以呢在传统的做法中呢,我们会把这个场景分成很多很多的不同的文件,然后呢让你编辑完之后,你们去merge对吧,这个做法其实是很笨,但是呢其实也很有效,那在这里面的话呢。
就是说我们会把物体进行不同的划分嘛,那里面有三种完全啊,三种独立的这个划分思路,举个例子啊,第一个就是我把世界进行分层,比如说编辑地形的编辑地形,编辑植被的编辑植被,编辑建筑物的编辑建筑物。
或者甚至是我的,我在物体里面会区分说,你编辑的是建筑物还是周围的小装饰物对吧,那这样的话呢,每一个不同layer的东西放在不同的分层里面,每一个artist只编辑自己的分子,这样好不好好的。
但是呢这里面会出现一个比较大的问题,是什么呢,就是说哎其实这个分层你很难分得特别好,而且呢很多时候不同层,不同层的东西是有相互依赖的,举个例子啊,比如说我们做地形的artist,他做完地形。
一旦对地形进行修改之后,那你上面的那些植被,那些东西的排布,是不是相应的都要发生变化对吧,举个最简单的例子,就是说啊我的一个artist改变了这个房子的位置,那你在周边种的所有的树对吧。
包括你对地面进行调整,是不是都要相应的发生变化,但如果这件事情是在三个互相看不见的artist,一起来做的话,这个地方就会产生无数的问题,所以分层是一个最古老的方法,很早很早以前引擎就已经支持了。
但是的话呢确实也是一个,我们认为在真你真的开始协作的时候,问题其实非常的多,但是我们这个里面有个很土的做法,就是三个artist的轮流做对吧,第一个做完,然后把它的分层锁定,另外一个是基于基于它继续做。
这样是可以的,但是你真的想就是同时去做的时候,他很多时候效果就很差,那么好,那么一种更土的做法将来了更有意思,做法就是我对世界进行划分,我分成块一块二块三块四块五对吧好,那这个就很简单。
我们就是反正这个地块的事情归你了,那个地块已经归我了对吧,这个事情呢也是非常简单好用,但是它会出现一个有意思的问题是什么呢,就是说我们有很多房子,比如说我就是跨界了,怎么办对吧,比如说我作为一个山脉。
我作为一个植被作业,做一个分布一一个湖湖泊,我很可能会跨两个界,所以那我是不是要支持不规则的世界画面,其实这件事情啊在那个真实世界里面很存在,举个例子吧,比如说我们我我以前看过很多。
那个就是有意思的旅行的这个小小小文章,大家讲在很多欧洲国家的那个国际上,有一栋房子,左边属于一个国家,右边属于国家对吧,那你这个怎么去解决这个房子归属的问题呢,对吧,包括有一些山也是这样的。
一些河流也是这样,所以说其实这个对世界的划分,很多时候啊是一个非常有效的,它能解决很多问题,但是呢在有些地方他又很难解决这个一些cross,这个boundary这些case怎么解决。
但是呢我们在看一个场景,特别是一玩家去看一个场景,它是连续的,所以说如果这个世界真的是割裂的时候,如果你感觉到边界那边很明显的区别的话,很多时候艺术家啊,玩家是接受不了了,当然了,这里我们有很多方法。
比如说最后再来一波artist,对边界这个地方在进行专门的修理,这也是可以的,所以这个方法的话也是一个非常简单的使用的,一个方法,那么另外一个呢下面给大家只是提一下吧。
这个因为也是现在刚刚在推出的一些技术,比如像unreal five最近推的这个one file projector,就是OFPA,他这个就很极端了,他说你们既然觉得这个世界容易冲突,对不对。
好游戏世界里面每个对象,我就给你创建一个文件对吧,你们每个人只改自己的文件,你们彼此再也不会冲突了,这个听上去非常的了不起,我个人觉得也是非常了不起的,一个一个一个尝试。
但是呢这个就是我自己也是简单看了一下,OFPA吧,就是包括我们团队也在交流,就是说他的问题它会产生无数的小文件,当然其实他也不会那么傻,他会做做了很多机制对于小文件进行管理,但这个事实上的话。
那就会产生两个比较现实的问题,就是说当我进行版本管理的时候,比如说我地形这个我这个场景做完之后,我要去提交一个新的版本的时候,我发现我要提交很多很多的文件。
这个大家如果用过真正的source control的软件,你就知道source Ctrl软件的话,比如像p four,比如像SBN对吧,如果你一下子做大量文件的版本管理的话,这个对他们来讲就很痛苦。
他们到最后你会发现整个工作室都卡住了,卡不动,更新不了这个数据,包括就是我们在cooking的时候,因为我这些碎文件我不能在内存中,就是也是这么多碎文件,这个到时候会让我的游戏的性能特别低。
所以呢它实际上在cooking的时候呢,要把这些所有文件还是打包到我的,一个level的文件里面去,那这样的话呢,就会使得在我在对数据进行打包的时候,有了一个额外的过程。
而且这个时候你面对的可能是上万的,这种小文件,大家如果对操作系统有所了解的话,你会发现操作系统最恨什么东西呢,最恨的就是小文件,所以的话呢,这会产生很多的额外的这样的一个负载。
所以这个技术呢但我个人认为就是虚幻,提出来肯定是有它的道理的,就是说他一定我们想到东西,他也也想到了,所以实际上的话,我认为这也是个非常值得大家关注的一个,前沿的方向,因为这里面我讲的每一个问题。
它总是有一些技术方法可以绕过去的,而这个方法确实是能彻底的解决,就是协同编辑里产生冲突问题,当然了,这里面我讲的是协同编辑里面,最简单的就是哎,我们几个人各自编辑在一起合的,实际上协同编辑啊。
我们的终极状态是什么呢,我们同时在编辑,也就是说张三李四王五在编辑的时候,彼此之间都能看到,而这个时候呢实际上就要有一套网络的架构,就是说一般来讲我们是在局域网里面,就是说在工作室里面。
内网的性能非常高,诶我编的东西别人都能看到,这里面真正的难度呢其实不是状态的同步,难度是什么呢,保持它的语义的高度一致性,大家还记得,我们在这个就是上一节课里面讲到一个概念,就是那个啊,诶稍等。
就是上节课我们讲的就是说一个叫command的概念,对不对,我们我就讲过,就是说我们在做这个工具系统做编辑的时候,我们实际上争取把用户的每一个操作,比如说一个拖动,一个选取一个平移对吧,一个改颜色。
一个改材质,一个改一个参数,包括sequence里面每一个key frame对吧,K分的增加删除全部变成原子化的操作,变成一个command,然后呢我们在不同的大家所有人的电脑上。
我同步你的command,这样的话的好处就是说能够让这个协同编辑,就真的能够去写了这件事情,我讲起来其实非常简单,其实我们将来这一趴,准备的PPT页数是蛮多的,后来被我全部删掉了。
因为确实讲起来就太深太复杂了,真的是很难讲,那么但是呢它的核心就是说,你要对整个编辑操作进行原子化处理,实际上是你协同编辑的一个基础,如果你没有这样的一个基础的话呢。
那你所谓的协同编辑它一定是个hack,就是你可能看到大概上看上去很像那么回事,但是当艺术家真的用的时候,他会发现很多地方违反了人的直觉,这个是这个东西非常的有意思,就是人对很多协同,就比如说他的直觉。
就像是几个小朋友在一起在画布上画画一样的,那么他会认为比如说你画了个蓝色,我画一个紫色,如果你蓝色先画下去,我紫色再画下去,我的紫色穿过你蓝色的区域,就应该把你覆盖掉,因为我在你的后面,对不对。
然后这个时候,另外一个小朋友再点了一个绿色的点,诶,他那个点可能点了一半在蓝色区域,一半在紫色区好,这时候那个画紫色的那个那个那个小伙伴,他又说我想暗度一下,我觉得我刚才做的不好,哎呀这个问题就来了。
那这个点的那个那个那个绿色的点,和那个那条红色的那个杠子杠子之间的话,他们之间到底有什么关系,其实呢这也是我们认为,就是说做协同编辑非常难的一个问题,是怎么解决undo redo对吧。
包括呢怎么让不同的operation没人进行,那这里面的话呢其实有很多啊,非常前沿的一些设计吧,就是说那我们先讲一个最简单的做法,比如说我加各种锁,比如说一个对象,我给他加个锁对吧,这是很自然的。
就是二例子说这一篇东西都是我的了,是所有的意思都被我锁上了,好你们不能编辑了,那很好,大家肯定没有冲突对吧,但是这里面所会产生竞争了,那么还有一种呢,就是说哎这个资源是我的,你不能动啊。
这个有的时候是有用的,那举个例子,比如说啊我去做一个模型,这个模型的话,我现在打算改它的材质,但我不希望其他人再去改它的材质,因为我们彼此之间会冲突,那我就会显示的告诉你这个资源,我锁上了这个信号。
可以以几10ms的速度瞬间同步给别人,但是呢即使有这样的两个锁的话,实际上你在处理它的安do redo的时候,还是有非常多的问题,因为有的时候你创建了一个一个instance,你对它进行编辑。
然后别人觉得你成分很好,这棵树很好,对你的树又进行了其他调整,然后呢你过了一会儿就觉得这个数不对,你想用再重新种棵树,你把那个树诶那个按度一下对吧,那可能那个老师做的所有操作,可能当场就会崩掉。
所以这其实是我们在做这个编辑的时候,是特别复杂的一个问题,那这里面当然也有一些pattern了,比如说去OT对吧,operating那个这个transform的方法对吧,其实非常的理论很难。
比如说像我们真正在引擎,你们经常用的叫CRTT这个方法,就是说哎我们希望通过一套规则体系,让这个conflict变成free,然后呢可以,但是呢他让各个状态,在各个就是那个终端那边都能同步。
但这里面展开了就非常的细节了,但这个其实我也跟大家讲过,就说其实协同编辑是一个,在理论上非常热的一个领域,因为现在随着网络的普及啊,就协同操作是一个越来越重要的需求,那么比如我在上节课讲到的。
就是像文本编辑对吧,大家用的各种各样的网上的文本编辑器,已经是越来越成熟了,大家还记得早期的时候我印象特别深,早期最早我用google doc的时候,google doc功能是蛮限制的。
当时第一次我们发现,我们彼此能看见对方的边界的时候,实际上就还是很震撼的,那么今天的话呢协同编辑,比如像他PS啊,用的做的非常好了,已经很成熟了,大家可以看到,但这个过程是非常非常的漫长。
那么其实的话呢,就是现在的协同编辑里面的话呢,我们有很多种flow在一起,也会就是说竞争,比如说现在我们会比较推荐的是什么呢,就是说诶你把所有的操作不要直接apply,它的最终结果。
先找一个server,把所有的操作全在一起,结算完之后再统一的发挥给大家,这就有点像什么呢,有点像我们以前做的那个网络架构里面,cs模型,就是说所有的客户端只是发起你的动作。
然后你不要操作有server统一结算完之后,把最终的结果返回给每个client,你们自己去看对吧,那你们有至少这个问题的好处是什么呢,你没有争议,你付出的代价是一点点的延迟,但这个东西的话呢。
在一个局域网的情况下是可以接受的,这其实也是现在这个很多协同编辑的,就是这个那个那个游戏引擎的话,会采用的这样的一个结构,但这里面可能会带来的一个,有意思的问题是什么呢。
就是说那个如果客户端那台机器炸了,没关系,大家就炸了对吧,但是如果被选做服务器的,那个那个那个艺术家的机器,假设炸掉之后,那一群人直接就崩掉了,所以这个系统的健壮性和鲁棒性的话呢。
其实也还是有一些东西需要去设计一下的,所以这件事情的话呢,我认为还在一个非常早期的阶段,但是我我会觉得这是一个我自己个人,也是我认为下一代游戏引擎研发很关键的,很前沿的一个一个方向。
所以在这边的课程的话呢,我也跟大家去点一下,让大家有点感觉,那基本上呢讲到这一节课的话呢,我们这个这一趴的东西基本上就讲完了,那现在的话呢,其实哎又到了我们又一个section对吧。
就是四节课基本上结束的时候,也给大家布作业了,那么上一节首先我讲了上一节课的作业的,我们的时间还可以往后推,就同学们不要着急,其实我们并不认为,同学们需要把所有的作业做完,而且呢大家如果需要更多的时间。
我们的我们的课程组的小伙伴,还有我们的很多共商观的小伙伴,其实他们真的很认真负责,大家都会很耐心地帮大家答疑解惑,给大家解决问题,那么接下来就讲我们这节课的作业是什么,其实讲完了整个工具体系啊。
讲完了这些反射系统,我们有一个想法,就是说如果是同学们最想了解,最想掌握的呢是PULA这个小引擎对吧,那PILA小引擎呢,我觉得最核心的就是它的资产,包括同学问我说,为什么我们要自己的这个format。
JASON这个format对吧,包括我们A做了这个自自动的,schema和反射系统,然后呢在我们的editor里面可以自动的去,那个就是说产生所有的编辑界面对吧。
我们甚至做了一个小小的content browser,我们出现了旁边的property panel,所以呢我们这一期的作业呢,是一个开放性的命题,就是如果同学们知道了,这个反射系统这些东西的时候。
我们希望我们这作业标题是这样,大家自己听好,就是大家可以尝试在我们的这个就是资产里面,asset里面定义一种自己的属性,比如说大家发现我们现在第一个机构对吧,我们知道它有read the body。
他有他的mesh,它有它的animation,对不对,比如现在你想对这个世界做一点小小的逻辑,无论做什么都可以啊,比如说你希望这个角色会会是这个自动的打枪,或者有个血量对吧,比如说我想有个血量。
我要增加它的血量的这样的一个一个属性,这样我从高处跳下来会摔死,打打个预防好,包括我从多高摔下来,我受到伤害是多少,这两个变量我想定义好好,那请尝试在皮克拉这个引擎里面,把这些属性增加到我们的这个。
character的这个里面去,然后呢你可以在编辑源码,你可以编辑它,而且呢你一键点play的时候,这些属性真的能跟你的引擎代码起作用,当然因为现在我们的二次开发的接口,还没完全开放出来。
所以你还需要直接改那个皮克拉的代码,没关系的,但是呢你至少从这个资产,从那个JASON的一个就是S的文件,到引擎内部的这个这个这个数据,到整个编辑器这条链路全部打通打通,那么如果这件事情大家做完的话。
我们会认为大家就是真正掌握了,我们的这个就是说这套schema反射,asset编辑器的这套体系,这道题目其实是蛮开放的,那么当然了,我这边只给大家举个例子,比如血量这个例子对吧。
其实同学们可以自由的发挥,就是你只要定义了你自己的cosmos的data,通过整个这套反射schema系统能够反射上来,同时的话在资产里面这个数据真的能读的,读的进来,存的出去。
然后呢他真实的能产生游戏的game play的效果,那我们认为同学们这个作业就做完了,那同样的提交作业的方法呢也是老的方法,就是大家把自己的作业的思路,实现了代码和效果的截图展示出来,发给我们就好了。
我们给大家帮助,给大家一些反馈,包括同学们有什么困难的话,我们的共商观也会帮大家来解决,好不好,Ok,那这一次是我们第一次,尝试做一个开放性的作业,因为这个作业我们本来我想做个三破。
但是其实啊对于我们来讲,因为我们写了pk了,所以我们这个对我们很简单对吧,但是的话呢我相信对同学们来讲的话,一上来摸一摸它还是有些挑战好,那今天这就是我们课程的全部,能够给大家呈现我们的高质量内容。
另外一个好像是这节课讲完之后,我们又可以休息一个星期了,对于我来讲的话,非常开心啊,我又可以过一个好的周末了,我们的小团队也可以过个好的周末好,那今天的课程全部在这儿,那接下来同学们有没有什么问题哦。
对老规矩就是会出现我们的reference,就是那个把我们找的资料也给同学们去分享,好的,那同学们有没有什么问题对,就是刚才我们讲的,这次这个作业是比较开放的嘛,所以顺便补充一句啊。
就是我们有一些更加详细的一些作业要求,我们会放到官网上,同学们有什么问题的话,随时可以问我们好,那同学们有没有什么问题,在线上可以问我们的呢,啊同学们,我们说小引擎的反射系统会输出详细的代码。
讲解文档吗,哎这个东西啊,我们的课程组真的是在准备,可能会通过wiki的形式给大家,当然也有可能通过视频的形式看到,wicked的形式会更好,因为它的系统会更加的全面给大家,同学们,第二个问题很有意思。
有同学问我说反射会不会影响运行效率,实际上的话呢,就反射对于引擎来讲没有什么影响,因为它本身那些反射代码你不用它,它不会产生任何的overhead,但是的话呢当你再去工具里面。
去这个频繁的调用这些反射的代码,比如说get and set invoke,包括就是说因为在工具里面,很多时候,我们是通过字符串去找到那些函数的指针嘛,你要找那个map嘛。
这个字符串根据字符串去search,当然我们可以把字符串优化成那个一个id,我们叫做string id的东西,我会反射,我会我的减速会更快一点,但是呢这个事情过程的话,本身有的时候会产生效率。
特别是对于那种就是大批量的这些数据的,那个编辑,打个比方,比如说刚才我们讲的那个,就是刷草和植被的那个刷子,可能一下子它会创建很多的物体,很多物体属性都要被射一遍,包括我们在做sequencer的时候。
我们要改变很多的parameter对吧,那这里面的话呢在编辑的时候,可能会有一些效率的影响,但是呢在run time的时候呢,这些数据还好不会影响,因为反射主要是在editing它会用到的东西。
啊这个同学问的问题就比较挑战了,就是说在现在的游戏开发中,DCC工具和引擎工具之间的分工到底是什么,首先这个问题是非常大,也非常的难,因为呃说句实话,我自己现在有的时候也有一点点的晕。
我跟大家讲一个两个有意思的一个发展方向,第一个就是说其实在现代的有那个DCC工具,比如说3D max maya,包括像ZBRUSH,包括像那个胡迪尼,其实越来越强大,真的他们很多时候都prefer。
就是说诶,你能够在我的工具里面做尽可能多的东西,我甚至能提供一个类引擎RUNTIME的preview给你,你甚至可以把你的引擎集成进来,给我做一个viewer对吧,我可以让你做很多的view这个东西。
那么这其实是DCD工具在五推的一个方向,但是的话呢,我又发现另外一个有意思的趋势是什么呢,就是说在现在一些前沿的引擎里面,我们希望把很多第四次的功能,直接集成到引擎里面来。
那么这个原因是有是有很深的道理的,我举个简单的例子啊,比如说大家如果看虚幻五的发布中,有一个系统叫rain系统,那么也就是说我可以在引擎里面直接手K动画,大家知道就是我们以前在游戏已经教过,你的动画。
是由max maya这些ADC的软件做的,对不对,但但是呢在我们实战的游戏研发中,我们会出现一个问题是什么呢,比如说我那边也场景中有一个啊,有一个这个这个这个比如说有个扶手,然后呢。
我希望这个角色他是手抓着这个扶手跟你说话,诶那这个时候就很有意思了,就是说我怎么能做一个动画,让这个角色能够非常准确的抓住这个扶手呢,这件事情就很麻烦,那怎么办,传统做法是这样的。
我们会把那个场景导成一个建模,导到3D max maya里面,因为这个模型本来就有嘛,对不对,好,我把那个角色放在,我想他放在那个位置,然后呢,让artist在max min里面精准的把那个手放上去。
然后开始给你巴拉巴拉,开始说话,然后呢整个这个动画我再倒回到引擎里面去,我只要把角色的朝向位置大小全部对准之后,你可以看到在游戏的这个比如说过场动画里面,这个角色就能精准做这个操作,大家仔细想想。
这个过程是不是特别的麻烦,是非常非常的痛苦,对不对,那么我们就会发现artist希望是说,既然你们的引擎工具做的那么强大了,你作为一个把这个角色首K1下,这个动画有什么难,我们想想好像也不难。
确实我可以做啊,好那我们就干脆把这动画这盘也就做掉了,包括就是你会发现,比如说有些引擎,它会直接把一些DC的工具直接买进来,集成到达的体系里面去,所以说其实我看到的是什么呢,我很难讲两边在分家。
我看到的是大量大量的融合,所以这个呢其实也是符合引擎作为一个生产力,工具的一个客观需求,就是说它实际上是以艺术家怎么方便怎么来,所以我个人也比较关注的一个方向,也就是说在引擎里面的话。
怎么把这些DCC的功能直接集成到引擎里面来,这样减少artist在这个不同的工具之间,来回切换的痛苦,因为刚才大家看到我画的那张图。
那张图是那个game engine architecture里面那张图吗,实际上我一直讲那个图是比较古老的嘛,就是它比较传统,事实上在每一个DC的工具。
它的exporter importer数据来回倒一次的时候,就会产生一次呃,产生错误的这样的一个机会,包括会极大的下降我们的内容生产的效率,而且让整个内容生产变得更加的不直观,而且很容易出错。
所以的话呢这个两边的融合,这个趋势现在特别的明显,所以你让我说哪个工具归d cc,哪个归我们的这个引擎的话,我认为这个边界是动态的,一直在变化好的,那今天的话就是再次谢谢大家,那我们争取在下一节课。
我们再见,下节课,非常有意。
Skin play,OK好拜拜。