【GameLook专稿,未经授权不得转载!】
GameLook报道/对于不少起步较早的手游公司而言,从2D到3D的转变,意味着团队很多基础技术都需要换代升级,这往往会给游戏和研发团队本身带来巨大的挑战。作为比较早的入场者,芬兰明星手游团队Supercell同样遇到了类似的问题。
在GDC 2023演讲中,Supercell工程师Tim Heinpurola分享了该公司从Flash技术到自研渲染平台的发展过程,并且分享了Supercell这么多年技术迭代所学到的经验和心得。
以下是Gamelook听译的完整内容:
Timo Heinpurola:
我的名字是Timo Heinpurola,今天将要分享的话题是Supercell的渲染现代化。首先我会简短介绍一下公司的技术发展,随后会提到重写我们核心渲染器以及将我们所有游戏移植到新系统的过程。随后,我会谈到新着色器本身,说说它的架构概览、一些功能设定,最后,我会说一些在这个过程中学到的经验。
不过,首先做一些自我介绍,姓名之前介绍过了,我自2020年3月份加入Supercell,从那时候开始,我就专注于打造我们的共享渲染能力。实际上,我是来自IT领域,在那里做了五六年,但一直想要进入游戏行业。
所以,我加入了Bugbear Entertainment,主要从事游戏《Wreckfest》的研发,此后,我加入了Next Games担任游戏《行尸走肉:无人之地(The Walking Dead: No Man’s Land)》主程序。进入Supercell之前,我在一个小型初创工作室Reforged Studios工作。
Supercell创立于2010年,现在全球总人数为420-430人,以旗下《卡通农场》、《部落冲突》、《海岛奇兵》、《皇室战争》和《荒野乱斗》五款游戏而著名。
从Flash到Native C++
Flash时代
我想在这里说说公司的技术发展历史,实际上,我们从Flash时代就开始研发我们的游戏,我们的首款游戏《Gunshine.net》就是用Flash研发、为Facebook平台设计的。当时,Facebook是我们多平台策略的首个组成部分,我们很快意识到《Gunshine.net》不会成为我们希望的能够获得巨大成功的产品。
因此,我们决定砍掉游戏,并转向以平板为基础的移动平台,后者在当时方兴未艾。所以,Flash当时并没有被放弃,而且那个时候的选择局限性比现在大得多。我们希望继续使用Flash研发游戏,因为我们在这个管线里有更多的经验,而且还准备了大量即将推出的内容。
TITAN的诞生
我们将其称之为TITAN的诞生,我们研发这个管线是为了将Flash内容转化为我们的内部各式,并打造一个渲染这些内容的渲染系统,我们将其称之为Stage,是以Flash API为模型打造的。
Stage是TITAN的一部分,但后者远不止于渲染,而是包含了可以让团队部署大量功能的能力,这些是他们需要但却没有必要自己研发的。以往,TITAN曾是一系列组件构成的工具箱,研发团队可以选择并使用这些组件,但它越来越像一个真正的引擎。
TITAN还通过工具和技术团队维护,所以,即使每个团队都有能力并直接使用TITAN,但维护它的重任依然落在了工具和技术团队身上,我也是团队成员之一。
我们看到了3D内容需求的增长,我们的初期游戏都是带有预渲染或手绘的等轴伪3D,如果你们看早期的《卡通农场》就会发现,它虽然看起来像3D,但实际上并不是实时渲染的3D。
不过,我们的测试游戏《Everdale》以及《荒野乱斗》真正凸显了我们游戏里3D内容的潜力,以及它打造生动环境的能力。值得一提的是,尽管《Everdale》项目被砍掉了,但它在Metcore工作室找到了新家,所以我们很期待他们能够对这个概念和想法带来什么新东西。
3D新风潮
苹果抛弃OpenGL|ES
随后,3D内容掀起了一些新的风向,其中一个就是苹果丢出的重磅炸弹:他们决定抛弃OpenGL|ES。
这对我们来说是个巨大的问题,因为我们非常依赖OpenGL|ES,基本上我们所有的渲染都是直接在此之上打造的。我们在OpenGL|ES之上有些轻量层(lightweight layer),但大部分游戏都是直接调用底层API,所以我们对已有渲染架构进行了审视:
在底部,我们有OpenGL和OpenGL|ES层,在此之上,我们打造这里这些轻量层,比如着色器加载、带顶点缓冲绑定的渲染类(render class)、创造OpenGL纹理和纹理内容加载的GLimage,这些都是比较简单、轻量级的东西。
在此之上,我们有网格、材质、建模和场景等的3D渲染功能,这一层也包含Stage,这也是在直接调用OpenGL|ES并使用了底层。随后,我们还有具体的游戏渲染层,它使用之下的所有层,包括直接调用OpenGL,所以,我们对OpenGL的依赖很严重。
让我们的渲染经得起未来考验
我们希望让我们的渲染经得起未来的考验,我们将苹果的决定视为一个机会,所以我们并不只是部署一个Metal渲染通道,我们希望恰当处理这件事。我们之前的渲染通道成为了绊脚石,想要创造更复杂的3D效果变得越来越困难。我们走到了从2D渲染向3D渲染过渡的路口,独立维护这些系统变得越来越难。
所以,我们需要一个抽象层,能够允许我们的游戏渲染工程师们聚焦于游戏的实际视觉效果,而不用对底层API考虑太多。
具有风险的变化?
这可以被视为一次具有风险的变化,毕竟,我们要重写的是数十亿美元收入级别的游戏渲染系统,但我们相信,这样的改变对我们保持竞争力而言,通常是必要的。
所以,我们不断将游戏转移到新TITAN功能上,因为它在很多方面可以给我们带来帮助。它通过每次更新帮助我们提高现有游戏的表现。比如,我们要研发一个新内容分发系统,这些游戏会变得更好并为玩家们带来更多内容。
这还可以让工具和技术团队规模更小,因为我们只有这一个堆栈,不需要维护很多的技术分支。而且,这还让在不同游戏之间的学习和技术分享变得更容易,因为我们有统一的技术语言、使用的平台也一样。
因此,是时候介绍THOR了,也就是面向硬件优化的TITAN渲染器(TITAN hardware-oriented/Optimized Renderer),实际上,这个名字是我在观看了一部漫威“Thor”电影之后起的,不过它很适合我们技术的缩写,所以这个名字就保留了下来。
进入THOR时代
THOR的诞生
THOR就是上文提到的抽象层,目前它包括了Metal、OpenGL、OpenGL|ES和Vulkan。Vulkan仍是一个辅助型的工具,但我们在努力尽快将其上线使用。
加入公司的时候,我们已经有了THOR的大致框架,我们有了基础的架构、对OpenGL、OpenGL|ES和Metal有基本的支持,这时候依然没有Vulkan的支持。实际上大量的核心功能仍是缺失的,大量的东西需要重写,部分原因是为OpenGL增加的多线程支持,但这是个很好的开始。
在2020年春,我主要是单独从事THOR的研发,也没有任何有项目需要从事,就只有一个不同渲染测试的单独项目,主要是为了创作纹理、具有吸引力的渲染和基本渲染。不过,就在暑假开始之前,在芬兰这个时间通常是六月底七月初,我以非常有限的方式让《卡通农场》得以运行。
可以看到,画面还比较简陋,但其实它是游戏在THOR上运行的第一张截屏,这是很大的里程碑,因为从这里开始,我们可以不断提高THOR,让它做到能够用于游戏制作。
之所以选择《卡通农场》,是因为这个游戏的渲染功能设定很有限,基本上它只依赖于Stage,我们不需要部署 任何3D渲染功能。
为最坏的情况做准备
当然,我们需要为最糟糕的情况做准备,所以一开始就为游戏设置了自动测试,甚至在还没有开始考虑加入任何东西之前。我们加入了预定义的场景用于烟雾测试,它会自动玩游戏,还推出了录制游戏过程的视频录制功能,将其存储于硬盘以便后续分析。
我们还有日志抓取(Log Capturing),所以,如果在视频中看到了一些问题,就可以进入日志,看是否能找到这种现象发生的原因。而且,我们可以在Google Firebase执行这些测试,它可以支持大量的设备和操作系统,覆盖率比较高。
这帮助我们在发布之前找到了很多渲染问题,在分享的最后,我会举出一些案例。它可以让QA聚焦于更棘手的问题。
在2020年秋季,我主要专注于提升和稳定THOR,让它为游戏制作做好准备。解决一些小问题、做性能优化之类的事情。与游戏团队合作非常容易,对于很多问题,我可以直接和团队交流并快速得到答案,没有人质疑我做这件事的能力,而且我有很大的自主权做一些重大决策。
最后,使用THOR运行的《卡通农场》在2020年11月23日发布,这是THOR的第二个重大里程碑。因为我们已经有了一款游戏在此之上运行,随后就可以开始收集表现数据、崩溃报告以及整体玩家反馈。
幸运的是,在运营过程中,我们并没有遭遇太多的问题,所以我才得以转到下一个项目。我做的事情就是从一个游戏团队转向另一个团队,将游戏渲染移植到THOR上,并在这个过程中对THOR不断提高。
下一个要做的是《部落冲突》,这其实是需要移植的第一个拥有3D元素的游戏,所以这一次我需要移植网格、渲染序列、材质等所有东西。不过,这是一个相对直接的过程,部分原因是Stage已经被移植,而《部落冲突》内大部分的渲染都依赖Stage,只有一些3D元素。所以在《卡通农场》之后,这款游戏也很快在2021年4月12日发布。
随后是《皇室战争》,这个项目实际上是和《部落冲突》(移植)并行的,这里没有太多惊奇的地方,主要是一些渲染器变体过滤系统(shader variant filtering system)需要部署,但最大的问题是与项目的时间线匹配,也就是他们的发布计划。推出这次更新用了很多时间,最终是在2021年10月25日推出。
THOR运行的第四款游戏是《荒野乱斗》,这或许是最复杂的一个,大部分的功能已经存在,但由于我们的内容量比较大,而且不同渲染器的变体,我们遇到了很多小问题需要解决,最终这次更新在2021年12月16日推出。
最后一个移植的游戏是《海岛奇兵》,这个耗时最久,同样是因为游戏的发布计划。而且这款游戏做3D渲染有些不同的方式,需要更多的工作量,不过更新最终在2022年11月2日发布。
这个时候,所有在线运营的游戏都已经被移植,我们终于可以做“外科手术”去掉旧的渲染路径,这是THOR的第三个重要里程碑,我们可以视为这个项目现在总算是完成了。
你们或许已经注意到,这些项目的时间规划才是最大的问题,这是真实的,因为将THOR的工作量与这些独立项目的时间线匹配是很复杂的事情,因为他们依然想要研发更多的内容,包括所有的新功能,与此同时,我还在做核心渲染,所以这或许是最具挑战的部分。
但是,这只是开始。THOR的研发从未停止过,我们现在将注意力转到了在THOR之上建造。因此,现在我们可以加入新的渲染技巧,这在之前是无法实现的。这还让分享变得更加容易,如果你们有同样的代码和语言,沟通起来就更容易,也让我们打造更好的工具更容易,因为这个管线使用更好的工具。
THOR是什么?
我们来谈谈THOR本身,我们对它有三个主要的设计目标:首先,它需要支持多个图形API。我们想要增加Metal支持,但我们还必须保留OpenGL和OpenGL|ES的支持,所以至少我们有两个API,但我们还希望增加对Vulkan的支持,因为这是安卓一直在努力推动的方向。
我们还希望它强大和高效率,但同时易于使用。我们希望用这个系统高效率打造现代化的、令人印象深刻的视觉效果,但我们还希望游戏工程师和游戏渲染工程师可以在使用的时候不遇到很多的困难。
而且,我们希望它能够面向未来,所以我们不希望很快就要再次重写这个系统,而是希望它成为我们未来的渲染平台。
简而言之,目前THOR支持Metal、OpenGL、OpenGL|ES和Vulkan等API,它是以围绕Metal的核心概念为架构的,因为我们发现,Metal或许是性能和可用性之间最好的折中点。而且,Metal是我们最初的主要目标,因此,围绕它打造一个架构是有意义的。
THOR还是多线程的,这对我们是很重要的一点,因为现代的移动设备都使用多核心,而且往往使用不同类型的核心。所以,我们希望充分利用这一点带来创造多线程渲染算法,这在之前是没办法做到的。
设计挑战
我们还遇到了一些设计方面的挑战:首先,它必须支持以往路径支持的所有设备,这个挑战有一部分原因来自于我们的使命,那就是创造可以让尽可能多的人玩很多年、并且被永远记住的伟大游戏。所以,我们不希望仅仅是因为重写核心渲染,就放弃那些已经喜欢了我们的游戏很多年的玩家们。这个系统是面向未来设计的,但对现有玩家可能不会立即带来太明显的帮助。
增加的抽象(abstraction)应该是非常有效率的。我们一开始对于OpenGL|ES的使用非常高效率,因为我们所有的渲染都是在其之上直接打造的。抽象往往会增加开销(overhead),所以,我们希望将额外的开销保持在最低水准。
第三,是必须与已有路径共存。这或许是最大的挑战,我们不希望将所有鸡蛋放到同一个篮子里,我们的方式是将运营中的游戏一个接一个地移植到THOR,确保在移植下一个游戏之前,此前移植的游戏能够很好的运行。
我们来看看THOR的核心架构:
我们的底层是特定平台层,这对于Metal、OpenGL、OpenGL|ES和Vulkan都是各不相同的。对于OpenGL和OpenGL|ES,他们有很多代码是共享的,所以技术上来说,它们是同一个平台的变体。
底层之上是包含资源的抽象层,比如Buffer、纹理以及不同的渲染状态,如渲染管线、DepthStencil state、着色器函数定义(shader function definition)等等。这就是我们称之为的THOR,这就是硬件或者底层API抽象层。
在这之上,我们有之前同样的层,主要用于3D渲染,也包括Stage。我们对这些层没有进行重大的改变,我们将它移植到THOR,但并没有做出重大的结构变化。然后是特定游戏渲染层,它现在只取决于THOR和这里的场景层。
所以,可以看到它不再依赖底层API,这是我们最大的目标之一。
我们来快速了解一帧的构成:我们从命令缓冲区编码(command buffer encoding)开始,这是我们从Metal得到的一个概念。你可以创造一个命令缓冲区,然后创造一个渲染编码器,后者负责这些绘制调用(draw call)和状态集(state set)编码到命令缓冲区。
这是在OpenGL上模仿的,因为OpenGL并没有命令缓冲区的明确概念,Metal和Vulkan是有的,所以在它们上面只是原生操作。但对于OpenGL,我们有一个主机内存缓冲区(host memory buffer),这里可以编码状态集和绘制调用等等。
这个命令缓冲区接着被推到命令序列,在Metal和Vulkan,这基本上是通过驱动进行GPU执行,但对于OpenGL,我们实际上拥有一个专门的线程,来打开命令缓冲区并执行这些OpenGL命令。
因此,这让我们可以在任何线程创造这些命令缓冲区,但OpenGL的命令实际上是在单一线程上。
我们当然也可以编码多个命令缓冲区,并且并行执行,唯一的限制就是在任何特定时间里可以存在多少个缓冲区。但是,如果你编码这些缓冲区,执行、然后再等待时间释放,那么你可以在一帧期间创造很多个命令缓冲区,这个限制实际上来自于Metal。
随后,第二个命令缓冲区开始被执行,到了最后,我们计划呈现,这就是一帧的完结。
再来说说着色器。我们在GLSL中编写着色器,这随后被编译到SPIR-V模块,然后,我们用SPIRV-Cross将模块转化到具体目标语言。对于OpenGL,它就像是GLSL的不同变体,对于Metal,就是MSL。这些随后在运行时被加载,并转化为运行时概念、着色器函数,被编译和连接到着色器程序中。
在OpenGL,我们还有一个着色器程序缓存,可以用来大幅优化low time。在Vulkan,我们直接加载SPIR-V模块,但需要注意的是,SPIR-V模块对于每个平台来说都可能不一样,因为我们可能需要根据平台做一些优化。
我们有low time和built time管线,所以我们无论是在low time还是built time,都可以做这个SPIRV-Cross交叉编译(cross compilation)。Low time是我们最初就有的,我们推出SPIR-V 模块,在low time时,我们做交叉编译得到最终目标语言,然后进行编译。但现在,我们进入了built time管线,我们实际上在游戏打造的时候离线制作这些着色器的变体。
在此之外,我们还有一个变体系统,每一个着色器都可以定义一系列变体标志(variant flag),随后管线打造这些的不同变体。但是,众所周知,就像很多其他的引擎一样,打造所有的变体可能需要大量的时间,所以我们还支持特化常量(specialization constant)。
因此,如果你从THOR请求一个着色器函数,你可以特化一系列的常量,后者会进一步扩大着色器部署范围。在Metal,它用了函数常量,在Vulkan则是特化常量,而在OpenGL,我们实际上利用了SPIRV-Cross模仿特化常量的方式,但我们可以在编译时间定义这些值。
THOR的拓展
所以,很自然的是,并非THOR的所有功能都在所有平台可用,游戏可以用功能标志测试来检查可用的特定功能。但其中一些功能还被模仿,这可以实现统一部署,所以游戏引擎工程师可以预期一种特定的统一部署,或者有一个可以在此基础上建造的基本部署,然后,他们可以为想要使用的特定功能扩大范围。
一个OpenGL|ES 2支持的案例是uniform缓冲,在OpenGL|ES 2当中,我们没有原生uniform缓冲支持,只有一个主机内存缓冲区,基于着色器uniform block布局存储uniform值。随后,当我们想要渲染一些primitive,我们通过从这些内存缓冲区读取和使用GL uniform call来解决。
展望未来,我们的焦点转移到了在THOR之上建造,这里有一些我们正在做的案例。我们在为THOR增加功能,每当我们发现Metal或Vulkan有一些新功能,我们就可以考虑是否能将其加入到THOR当中,看它是否能够真正给游戏团队带来帮助。
此外,我还希望提到一些我们正在做的新系统,比如render graph部署,还有一些我们称之为ODIN的东西,这个名字并非巧合。
Render Graph
基本来说,Render graph就是一个渲染器任务管理系统,每个任务部署一个帧渲染,这里我们有两种类型的任务。一种是并不输出像素的普通任务,很好的案例就是GPU蒙皮(skinning),这个任务基本上负责模型转变、未转变的顶点数据,处理并输出这个结果到一个临时顶点缓冲区用于渲染。
另一个是渲染通道,它们是真正为所有的缓冲区在屏幕上或者屏幕外输出像素的,这些任务随后在工作队列排序执行,我们可以有很多个工作序列,取决于这个平台有多少个不同核心。
同步基于这些节点的输入和输出,所以你们可以看到,模型蒙皮和不同渲染通道之间是有相互依存性的,在渲染通道开始之前,模型蒙皮需要先完成。
此外,阴影通道和彩色通道之间也有依存性,但你可以看到在这些任务执行过程中有很多的重叠。这是因为,彩色通道只遇到阴影通道上的帧缓冲存储器输出,但仅在GPU之上。所以,我们可以重叠这些任务的大部分执行,因为这些执行是命令缓冲区的准备。
因此唯一重要的事情,就是确保阴影通道的命令缓冲区在彩色通道之前被打开,这是系统也会考虑的事情。
现在,我还不会对ODIN进行太多的解释,但我想要说的是,因为THOR这个项目并没有太多的使用中间层,但ODIN这个项目如图所示:
目的是让Metal层更现代化。所以,为了更好地完成我们现有游戏和新游戏的需求,要有各种类型的材质、让它更数据驱动和易于使用。
一路走来积累的心得
接下来说说学到的经验:
质量
这里我想说的第一件事就是质量,我们的游戏在大范围的设备上被用户游玩,我们的MAU达到2.5亿,他们有大量不同类型的设备。因此,手动测试一切是不可能的,自动化烟雾测试可以很大程度上降低QA的压力,让我们有更好的覆盖率。
另一个非常重要的话题是恰当的自我审查(proper self-review),确保你做的决定或者合并的代码是你自己理解的,并且符合你自己的质量标准,这可以帮你确定在限定时间和信息的情况下,做出了最佳的决策。而且,这还可以让你的同事更有信心,因为你并非随机做决策。
另外,你也可以更好地解决未来在你代码里出现的bug。
最后,尊重你的QA人员,他们可以帮你高枕无忧。
能耗
对于整体的手游研发来说,很重要一件事是能耗。电池和散热是手游的局限因素,你很少见到主动的风扇降温,这些设备的设计并不是为了持续性能,而是峰值性能。所以,如果你试图维持设备100%的使用,就要使用电池,它一定会过热,设备就需要散热。
渲染尤其要注意能耗,因为很多的渲染代码往往在热路径(hot path)上。这对于实现我们的目标也是很重要的,哪怕是在低端设备上,我们也需要做到高效率,我们需要让玩家们能够尽可能长时间的体验我们的游戏,所以要考虑到电池能耗问题,以及游戏的舒适度。
这里举一些考虑能耗的案例,首先,使用热存储器上的高速缓存数据布局(cache efficient data layout)。
为了今天的分享,我挖掘了一些数据,结果发现缓存丢失和缓存命中的差别是200倍,所以,如果你遇到缓存丢失,那么它的能耗是不丢失的200倍。所以,一定要以对缓存有效的方式设计你的数据布局。
另外,偏向使用多核心。如果你能够将渲染算法分散到多个线程,那么就可以让单核的压力更小,让它们以更低的电压运行,节约大量的能耗。
还有,使用低功耗内核,如今大部分的设备都有低功耗内核,它们可能有中功耗、高功耗核心,不同类型的核心,使用中低功耗核心可以节约很多电量。比如《部落冲突》,它主要运行在低功耗核心上,尤其是在稍微高端一些的设备上。
最后,我建议同行们从一开始就编写合理的代码,如果你没有分配时间,很可能没有解决代码问题的时间。因此,确保你写的代码足够合理,不使用很多的暴力破解(brute forcing),如果你没有进一步优化的时间,它可能会进入游戏制作当中。
我想贴出这张图片,它展示了移植到THOR之前和之后的不同能耗,这是使用旧OpenGL|ES管线和使用Metal的新渲染管线的能耗对比。
当设备运行不如预期怎么办
很多的安卓设备的驱动或者硬件是有问题的,这些情况并不总是像我想象的那么糟糕,但带来的影响仍然是很大的。
这里有一些案例,我们遇到的首先是缺少嵌套代码块,随后是用输出作为临时变量,最后是破损的uniform结构。
先来说说缺少代码块。当我们分析测试案例录制的视频时,我们发现,一些设备上的英雄比其他设备显示的更暗,进一步挖掘,我大概像这样指出了问题函数:
我们做的是SRGB解码,如果一个常量被设为true,我想可能问题是常量值设错了,检查一下true是否设置为true。但尝试之后,并没有解决问题。这时候,我想,或许这是驱动问题,所以直接去掉if,这样它就不会执行代码,但结果发现也不是,我发现驱动只是不喜欢函数里的代码块。
这是很糟糕的,因为我们需要将这类代码转移到主函数,将任何这类的代码放到嵌套函数内或从主函数调用的函数都是行不通的,而且这是一个比较新的OpenGL|ES 3级别的设备,
随后,是将片段输出(fragment output)作为临时变量,这其实是我们做错了,但我认为结果非常有趣。
在录制过程中,我们发现在一些设备上,角色被绘制成了灰色,我贴出了它的代码。我们将它写成了片段输出,然后我们通过读取输出值并写回去对SRGB做了线性和代码,从临时变量值读取解决了问题,我们不再是从片段颜色读取。这是OpenGL会遇到的事情,你永远不应该从片段输出读取,永远只能是写入。
但我们比较感兴趣的是,在其他设备上我们也这么做了,但编译器并没有出错。
最后,是破损的uniform结构。在一些设备上,我们只能看到黑屏,这对于任何渲染工程师来说,都是最糟糕的噩梦,看着黑屏,你不知道究竟是否渲染了任何东西。我用测试的设备看了很久,思考哪里可能出了错,然后我发现屏幕下方有些闪光,所以我认为它的确渲染了一些东西。
我是通过安卓debugging工具GAPID检查的,它显示的是统一数据(uniform data)不连贯。可以看到,它只是展示了一些uniform数据,这是我们在源着色器展示uniform块的方式,下图右侧是为OpenGL|ES2后端转换的代码,没有像这样在代码中增加uniform缓冲区支持。所以,它只是生成了一个矩阵结构,然后是一个基于这个结构的uniform。
结果发现,驱动并不喜欢uniform以这种方式定义。当我们更新uniform数值的时候,u_view里的一些column从u_projectionView获取值,所以这以很奇怪的方式搞砸了uniform位置。
解决方案是用SPIRV-Cross里的一些东西,将uniform块更新为一个vec4阵列,所以你可以只是更新这个uniform、也就是GL uniform call。唯一的问题是它不允许将浮点值与Uniform块中的内部值交叉,但是,对于拥有这个问题并需要使用OpenGL|ES2后端的游戏来说,这并不是一个问题。
把事情做好的心态
最后,我希望说一些非常重要的事情,它可能在今天的分享中有些被忽略了,但我希望在这里强调,也就是公司里的整个把事情做好的心态。我们的文化主要是为人才赋能让他们发挥自己最好的水平。
我们很少有官僚作风,所以,当任何时候你想做一些事,比如开启一个项目以提升特定系统,并不需要走一系列不同类型的企业审批环节,不需要通过不同管理层的批准,你可以成为自己的项目经理,并且开始推动项目的发展。
当然,也有这种方式行不通的情况,比如较大的结构变化、一些战略上比较重要的事情,但是,对于我们所做的大部分系统研发来说,它是非常奏效的。
人们倾向于对自己研发的代码以及从事的系统有责任感和归属感,所以,我经常说,如果你搞砸了并没有关系,这完全没问题,是人之常情,但这之后发生的事情才真正重要。因此,如果你真的负起责任,帮助人们解决你们的问题,或者自己解决,这才是真正重要的事情。
这种自主研发的心态,可以让我更有效率地工作和在不同游戏团队之间切换,与不同游戏团队交流并快速完成,在不需要经过不同管理层的情况下作出重大决策。当然,这并不全是好消息,比如,有些人在没有做必要准备的情况下做决策,并且与对着系统一无所知的人聊天,但整体来说,还是利大于弊的,而且非常的奏效。
结论
首先,我们打造技术是因为需求,对于THOR,我们非常需要增加对Metal的支持,所以这是既定的任务。但我们还希望让游戏工程师能在未来打造更好的视觉效果。因此,我们并不是因为有趣就做一件事。
我们还必须谨慎处理,因为我们在重写数十亿美元游戏的渲染,所以我们希望确保并不是将所有鸡蛋放在同一个篮子里然后放弃。
最后,THOR是我们面向未来的渲染平台,所以我们能够打造这个所有不同团队都可以使用、并且可以依赖并在其之上不断建造的通用语言。
如若转载,请注明出处:http://www.gamelook.com.cn/2023/04/516026