天美J3技术美术专家分享UE干货,在场从业者直呼牛逼
把UE5的特性迁移至UE4。
整理/严锦彦
上周,葡萄君参加了Unreal Fest Shanghai 26大会,听到了不少行业大牛的技术干货分享。其中一场分享给葡萄君留下了深刻印象,那就是《三角洲行动》的技术美术分享。
葡萄君对技术的了解并不深,因此很多时候只能靠现场反应,以及与专业人士对话,来判断分享的质量好坏。而三角洲这场分享是在上午进行的,后面中午吃饭,以及下午听会时,身边总是还有人在回味三角洲的分享,说他们的技术有多牛,能够实现UE5和UE4的特性与技术平移。
11月5号,三角洲新赛季将上线UE5技术升级的新地图天际港
于是,葡萄君也将这次分享整理了一下。以下是天美J3工作室技术美术专家xinyuan的演讲,主题是:《三角洲行动》生态环境渲染方案与工业化管线实践。
01
生态交互的特性开发
先简单介绍一下我自己:我是xinyuan,目前在腾讯天美J3工作室担任技术美术专家一职。过去几年,我和团队主要负责《三角洲行动》的生态渲染特性和生产管线,比如植被、岩石、地形、水。今天想和大家聊聊三角洲在环境渲染特性和工业化管线上的一些实践,希望能给大家带来一些启发。
今天的分享分为三个部分。第一部分相对轻松,是我们过去一年的一些工作内容,我会分享特性开发中遇到的一些问题和我们的解决思路
第二部分会介绍我们的生态工业化管线,以及全局生态 Global Biome 的设计思路。大家可以从中了解到,在大规模项目里我们是如何做资源管理和性能控制的。
第三部分是今天的重点,我会着重分享三角洲如何在UE4引擎管线下落地UE5的Nanite植被。
我们先进入第一部分。
三角洲对战场氛围和环境交互都有比较高的要求。在这些特性的开发过程中,我们积累了一些有意思的trick和实践经验。这一部分我会围绕我们最近一段时间做的一些有趣的特性,和大家做一些简单的分享。
开始之前,我们先来看一段关于动态环境的视频。
我在过去几年大部分时间在和植被打交道,所以先聊一个简单的问题热热身,插片植被的高光表现不好。这个问题可以排到美术最关心的效果榜前3了。
这个问题在很多使用插片植被的游戏里都存在:要么高光溢出、糊成一片,要么干脆没有高光。原因在于,传统工艺中大部分植被会把球形法线烘焙到顶点上,用来拟合整体的 diffuse 光照,但这样也会让高光集中在同一个区域,糊成一片。
基于我们过去大量的实践,要比较好的解决这个问题,还是推荐先从选型和制作上去做一些补充。第一看分布:真实世界里较高的植物大多比较粗糙,高处本来就不太看得到高光,高光主要集中在中低处。第二看选型:可以多用一些阔叶植物来点缀环境,这类模型不需要编辑法线,结构高光天然就是正确的。第三看工艺:制作 cluster 时尽量多一些扭转角度,这样在光影下更容易产生高光,当然整体而言这种材质trick方案不一定适合所有类型的植物,我更推荐多从选型分布上去补充;
在材质层面,也有一些 hack 方法可以参考。核心思路是对插片上的叶片像素做随机化扰动:先把随机值存成灰度,在材质中解码成一个随机角度来偏转法线,再用不同的法线分别计算diffuse和specular。这样既能保持整体的 diffuse,又能得到离散的高光;
这个部分和大家分享一些水下渲染的一些实践。很多水下效果会用后处理来模拟光线吸收。但半透明不写深度,水下一有玩法,这些排序问题会很麻烦。
水下效果的核心是光线吸收。我们的做法是利用Fog Pass对半透渲染着色的特性来避免排序问题,这样既不需要新增Pass,也不用手动处理排序。同时,雾的物理意义和水下吸收是一致的:用高度雾模拟从水面到水底的光线吸收,用距离雾模拟光线随远近的衰减,就能比较好地还原水下的效果。
在此基础上,屏幕后处理只负责偏色、折射、模糊以及Light Shaft这类效果。
水下渲染的另一个重要问题,是如何准确区分水上和水下。水下雾、吃水线、特效气泡等内容都需要做隔离。
早期我们用一张水域高度纹理来做隔离,采用R16精度、每半米一个像素的大纹理来存储高度。
但随着对局量越来越大,我们收到了玩家很多由精度、加载、硬件兼容性等原因导致的水下雾渲染错误。这些bug的出现也让我们意识到:和玩法逻辑强相关的内容,由GPU驱动的方案并不够稳定。
最后,我们改用了和逻辑水数据一致的查询方案,直接在CPU端查询相机位置处逻辑水的高度。这样3C、玩法和渲染就做到了完美匹配,同时还省掉了一张大纹理的采样和内存。
再来看环境交互,先从水交互说起。如果你经常玩三角洲,会注意到几乎所有干员的技能和行为,对水都有不一样的交互表现。
整体框架上,我们用的还是Capture、Simulation、Draw 这套常见流程,模拟部分也是最常见的浅水模拟方案。
和常见做法不太一样的是Capture环节:我们没有采用深度捕获,而是用Particle 2D的方式来捕获交互源。这个选型对我们后续扩展复杂交互起到了很关键的作用。
为什么选择粒子驱动?主要有这几个好处。
首先,它不需要额外渲染交互物体和深度;其次,相同材质的交互源粒子可以合批绘制,开销很低;第三,可以直接复用粒子系统已有的LOD和重要度机制,来做退化和剔除,这在性能上有很大的优势。
更重要的是,交互的动态行为由上层粒子系统驱动,借助力场和形状就可以设计出各种复杂的交互行为。这也是不同干员的技能能有丰富水交互表现的原因。
另一个很有战场特色的交互是地形弹坑。弹坑会改变地形、形成动态掩体,从而改变整个战场环境。
基础方案分三块:结构上,我们程序化地拟合弹坑的高度结构,并更新到地形高度图;Shading上,使用软细分加地形VT贴花来表现细节;玩法侧,则同步完成除草、更新物理碰撞,以及控制弹坑禁区。
实际对局中还会遇到多个弹坑叠加、相互覆盖的问题。我们的处理方式是把弹坑拆分为中心区域、隆起区域和溅射区域,再结合VT贴花分层和弹坑生成顺序的加权,让叠加后的效果依然自然。
最后是植被交互。基础方案是逐instance的骨骼风动。局部风场不依赖 RT,而是由CPU传值来驱动局部风场的大小和方向,比如画面中爆炸产生的全向冲击风。这样我们可以用很低的成本,让植被对战斗行为做出及时的反馈。
如果大家也在做类似的事情,希望这些经验能帮到你。关于特性的分享就到这里。
02
工业化管线搭建
对三角洲来说,单个特性本身也许并不复杂,真正的挑战来自大规模地图、高密度且多样的生态,再加上多端方案。生态环境本身是一个有机的整体,从美术表现,再到实际的资产制作、地图特性管理,都需要遵循这一特点。对TA来说,如何用工程化的思路来解决这些问题 ,是极其重要的。
首先是我们称为Biome Manager的核心模块。它的作用是串联起 PC 端和手游端的效果参数,让双端尽可能使用一致的框架、共享参数和输入,并在不同地图中完成转换和初始化。
它由两类数据驱动。第一类是美术驱动:关卡和灯光美术可以快速调整生态效果参数,比如季节偏移、风场、潮湿程度、色彩变化等,这些数据按地图存储在BiomeConfig中。
第二类是PCG驱动:生态健康度、潮湿区域、战损区域、水体状态这类基于地理信息的数据,存储在Clipmap纹理中,供双端Shading采样。这份Clipmap同样配置在BiomeConfig下,按关卡进行管理。
这种设计方式还可以让同一份资产在不同的地图、不同的模式下,自动引用当前地图中的BiomeConfig数据集,而无需新建资产。
在具体的资源生产上,针对生态中最复杂的植被资源,我们搭建了一套叫FAT的资产管线,也就是Foliage Automation Tools,覆盖植被资产从生产、管理 到监控的全流程工具链。
DCC模块,FAT主要负责外包和内部DCC生产环境的标准化,主要用来进行资源规范检查和性能前置检查。
FAT Core 模块,主要完成植被资产的自动化导入、渲染数据生成、以及跨地图的资产复用管理。
引擎内部,FAT还提供植被资产的渲染与风效 Lookdev,以及地图中资产使用情况的监控,确保最终满足性能规范。
针对多种不同生态的复用问题,我们引入了Biome Lookdev流程和工具。
这里的biome Lookdev和单资产的渲染Lookdev是两个不同的环节。对生态来说,同一个资产在不同环境下会呈现不同的状态,所以生态效果是不是正确、舒服,需要把多种资产组合在一起来做lookdev。
通过biome切片工具可以快速创建64×64的小型生态切片,它应用了标准化光照,同时方便美术同学可以快速进行生态组合和整体效果调试。
与之配合的特性是跨区域自适应Shading框架:同一份生态资产在不同地理区域可以自适应响应效果。比如同一棵植被在不同位置的健康度不同,同一块岩石在不同区域的layer内容、色彩也不同。这样的设计既增加了生态效果的多样性,也让资源得到了最大化的复用。
对于同一种生态资产的不同材质变体,比如战损、风动、燃烧等,我们用FoliageTypeManager来创建和管理,它是对虚幻Foliage Type概念的一套扩展管理框架。
当一个资源需要创建新的分叉变体的时候,必须经过这个工具。我们把实际会用到的材质变体,比如同一资源在不同地图、不同生态主题、不同特性状态下的版本,都提前做好预设。美术只需要通过FoliageTypeManager一键创建所需的变体,这让同类资产的材质变体数量有限且可控。
最后,Culling、LOD切换、阴影配置等性能相关内容也统一管理在Foliage Type上。这样在SOL和大战场这两种性能要求完全不同的模式下,我们可以尽可能复用同一份资源,只需通过Foliage Type的预设来区分。
我们尽量保证所有相同的生态资产都来自同一个Static Mesh。这样所有地图都能共享这个模型自身的优化与配置,不用反复复制新资源,有效控制了模型资源的膨胀。
性能控制要尽量前置。我们在资源生产的早期,就通过管线工具对资产的性能数据进行监控。
生产阶段,FAT分为External和Internal两部分。External 负责资产在 DCC 端的标准化和数据检查,让外包侧就完成第一轮检查,重点关注性能以及影响后续编辑的关键指标。Internal是外包资产进入内部生产环境时的第二轮检查,很多进引擎前的预烘焙都发生在这个环节,确保数据二次流转时依然合规。
地图编辑方面,QuickPerf是编辑器下对应的检查工具。如果地图中资产种类超标,可以用它快速筛查出来,也能实时看到资产所处的生产阶段和合规状态。
最后还有一道兜底,就是Biome Monitor流水线。它每天会收集地图中使用的所有生态资产指标并上传到网站,比如资产种类、数量、单资产规格等,同时由机器人把当天的指标推送到群里。这样TA不用打开引擎,也能快速掌握地图资产的变动情况。
水体方面,WaterACT是我们针对水玩法系统开发的一套全流程自动化生成和管理工具链。
编辑器侧,它可以自动生成水面模型、物理数据、水体数据和相关配置,并提供FlowMap、FoamMap的生成与编辑工具。运行侧,它负责水体交互、水面物理数据、跨TOD和区域插值的水下数据,以及Wave数据的管理,并支持在Editor和PIE中实时预览。
有了这套工具链,策划和美术可以快速完成数据生成、验证和效果调试,几乎不需要TA介入就能完成相关配置。
从去年开始,我们大量资源改用照扫的方式生产,同期也建设了 JadeXcan 自动化照扫管线。
扫描美术只需要把照片提交到云端,系统就会自动进行分布式重建、清理和烘焙。几个小时后,这些资源就可以直接作为早期的占位模型使用。
原本人工需要一周以上的重建和初步清理工作,现在压缩到数小时内就能完成,大幅加速了资产生产。
03
将Nanite Foliage移植到UE4的落地实践
接下来进入今天的重点,Nanite Foliage相关的落地实践。先说背景和挑战。
第一,三角洲本身基于 UE4 开发。为了规避整体迁移引擎带来的风险,引擎团队决定把UE5的三大件以及整套 Nanite Foliage方案移植回 UE4。
第二,作为一款竞技 FPS,我们必须保证高帧率体验,目标是在3080、2K分辨率下达到120帧。这是后续所有策略和工艺的基准。
第三,在我们开发的过程中,并没有太多同类型项目作为参考,也许我们是第一个落地全套方案的多人fps游戏。
带着这些问题,接下来和大家聊聊我们在Nanite Foliage上的实践历程和成果。
在我们早期的方案推演时,很多方向都是不明确的,因为大部分的方案都没有实际落地的参考。
Masked材质在Nanite里无法走fixed function路径,光栅化的overdraw问题会很严重。反过来,如果通过增加顶点来减少overdraw,植被风动的顶点WPO消耗又会变得非常重。
对于工艺的选型,我们的切入思路是这样的:对插片不断增加顶点、减少无效像素,让资产逐步接近Opaque工艺。这个过程中overdraw会下降,但顶点数会上升,也就是WPO相关的消耗会增加。
我们期望找到这三者的平衡点的同时,也想构建一个可以用于测试迭代的标准环境。
我们做了大量测试环境和资产,控制了以下变量:
资产上,制作了近 400 组从Mask到Opaque、面数逐级递增的植被资源;
场景上,搭建了中低密度和高密度两组植被场景,覆盖了从贴脸到开飞机看超远景的 ;
硬件上,在3080到5080的显卡上、4K关闭超分进行测试;
性能指标方面,我们重点关注Nanite Triangles、Nanite VisBuffer、Nanite BasePass以及最终帧率。
基于这些场景和资源,我们得到了不少实践结论,这些测试环境和资源也为后续开发提供了很大帮助。结论我就不逐条念了,挑几个重点说:没有风动时,所有场景都是Opaque更优;硬件配置越高,Opaque工艺的性能表现越好。
但值得注意的是,在一些情况下传统工艺依然有优势。尤其是在中低配置、中低植被密度时,低面数的Mask工艺表现也不错。这些结论和测试资源对我们后期建立资产性能规范提供了重要的参考。
纯Opaque植被虽然效果好,但硬盘和包体占用极大,数据管线的效率也非常低。Nanite Assembly可以显著降低硬盘、包体和内存的压力,并缩短数据流转的时间。
以一棵500万三角形的植被为例:磁盘空间从158MB降到2.5MB,Nanite内存从69MB降到3.84MB,数据的导出导入时间也从30分钟以上缩短到1分钟左右。
我们目前的Assembly工艺流程大致是这样:先通过照扫获取纹理,制作Cluster Atlas,然后在SpeedTree或PVE中完成分布和组装,导出为USD原始数据,再经由FAT预构建资产,最终导入Unreal。
实践中assembly流程也有一些限制。因为要做程序化分布,所以它无法像直接建模那样实现复杂的逐part顶点变形,变形数据在instance分布后会丢失,这对于美术建模植物时的方法有要求,这些unique的方式就不能使用了。
这是三角洲中一棵Assembly树的实际数据:100万三角形,由6种Cluster Part、648个Instance组成。
这是我们用 Assembly工艺制作的一组树种的展示,Assembly工艺的另外一个优势,就是可以通过同一组Cluster Part的不同分布组合,快速生产出不同的树种变体。
最后给大家看几张实机画面,展示Nanite植被在三角洲实际场景中的效果。高光和透光都非常的物理,TA再也不需要通过复杂的材质hack来找补了。
在实际落地中,我们仍需要同时制作Nanite和传统Mask两套植被方案,来适配更低端的机型平台。
为此,我们用程序化的思路落地了双档一体的制作方案,内部称为UHD-HD一体制作。
先做Opaque Cluster烘焙成Mask Card,基于制作分布生成对应的Instance点云,这样制作一份资产,就能同时产出两个档位的资源,也可以做相互转换。这确保了大规模生产时的效率。
对于纹理和材质来说也是双档公用的,没有增加额外的包体内存负担,在固定的区域用于放uhd叶片相关的贴图,即便区域全纹理分辨率不到1/4的大小,其精度也是mask工艺的数倍。
对于具体的资产数据组织,我们利用Naite自带的HighRes Fallback来组织这两档数据,在关闭Nanite时将自动退化到Mask资源。
我们通过这次的Nanite植被升级 ,也将整个植被资源管线升级到了USD管线,USD天生支持layer、instance等概念,这和我们多端一体 多档一体的设计理念是很契合的,各类核心数据都在一个usd文件内, 这对于各种资产自动化处理更友好,相比XML+Fbx这种形式的格式效率快大约3-5倍左右。
这是一个UHD-HD对比,两者来自同一份源文件,造型保持基本一致。
为了让Nanite植物能动起来,我们开发了骨骼风动的方案,内部叫Pasta风动。
和原生的骨骼绑定方案不同,Pasta并没有走Nanite Skinning管线,它是一个基于PP2骨骼风动的扩展方案。把风场和骨骼变换统一放到 Compute Shader中计算,结果写入一个Buffer供动画使用;所有顶点变换都在名为 CustomVertexDeformation的固定管线中完成,不走可编程管线路径,让海量三角形的动画也能高效运行。
我们来看一下Nanite植被在Pasta风动下的实际效果。
巨量的骨骼会直接带来显存和性能压力。在我们的一些场景里,同屏有3.7万个instance、300万以上的骨骼,前后两帧累计显存超过260MB;每帧逐instance更新BoneTransformBuffer,性能开销会非常高。
为此我们开发了Animation Bank技术:对中远处同类型植物的骨骼进行合批并复用动画,有效减少同屏骨骼数量,显存可以优化到50MB左右。
此外,在单资产的骨骼生成上,我们也做了Bone Reduce骨骼压缩算法:按主干、长枝、短枝、叶片的层级思路,处理后在效果基本无损的前提下,大幅减少了骨骼数量。
最后分享一些Nanite Foliage和Lumen结合的实践Tips。
首先是Lumen的光追代理。默认的Ray Tracing Fallback是逐三角形退化的,对光追本身来说是正确的,但高面数的Fallback Mesh在大量植被下,显存完全无法接受。
而基于三角形退化的自动算法,对植被这种离散结构并不适用:当单个叶片已经退化成一个三角形时,再继续减面就会漏光,而且不同类型植被的漏光程度差异也很大。
我们的做法是利用5.7的FoliageOverOcclusionBias功能,它可以对三角形做二次缩放,让Fallback Mesh的三角形数从1万以上降到100到1000区间,美术也可以快速调整不同植物的遮蔽程度。
第二个问题是Lumen在植被上的瑕疵。对于植被这类离散、高频结构很多的内容,Lumen的问题会严重,主要是糊和闪烁。
加载距离问题。GI贡献主要来自屏幕空间 trace。而在我们的帧率目标下,ScreenProbe的精度预算,可能要下采样到16以下,这个精度对于植被还是不够;另外,屏幕空间技术往往伴随着各种空间和时间上的累积方案来平衡性能,这也让画面稳定性变差,经常出现闪烁。
还有一个麻烦是Ray Tracing Proxy有加载距离。而且树动起来之后遮蔽位置并不会变化,因为我们并没有给RT Proxy做风动画。所以,我们需要一种稳定的遮蔽来表达中尺度的结构。
对顶点数巨大的Opaque植被来说,逐顶点存储并不现实,好在我们有Assembly,可以逐Instance来存储这份数据。因此,即使超出了光追距离,树冠内部依然有合理的遮蔽,而且风动时也不会显得突兀。
来看一下对比效果:左边是默认效果,右边是加入 Per Instance AO之后。
今天讲了三部分内容,看起来分别是特性、管线和新技术,但回头从TA视角下看,如何平衡项目开发中单点效果、工程性和生产效率,可能是我今天分享的一个隐藏主题。
对于独立的单一效果,很多情况下确实需要一些巧法子,但很多trick在大型项目里的代价可能比想象中要高,单点需求或者特性的可维护性,健壮程度往往是不足的,可它又是项目开发迭代中不可或缺的环节,整体的框架立住,才有空间承接一些独立的trick。此外TA的视野往往更宽一些,时机合适协助团队提供系统性需求的梳理和建议也很重要 。
最后关于一些新技术特性的推进落地,我们会在早期建立起benchmark并设计高效的测试循环,步步为营地将关键技术和工具落实,对大规模开发的稳定性和效率都很有帮助。希望今天的分享对大家有一点启发或帮助,谢谢大家。
游戏葡萄招聘内容编辑,
点击「阅读原文」可了解详情
点击下方名片,关注公众号
(星标可第一时间收到推送和完整封面)