大地图开发管理:《巫师3》Umbra遮挡剔除技术

作者:刘源 GDC2014 2018-11-14




本演讲介绍巫师3使用Umbra实现的遮挡剔除技术。

笔记略过了一些过于平凡的实现细节,包括流的加载,如何向Umbra提交数据;也略过了一半以上关于“游戏应当如何选择中间件”的讨论。

演讲时巫师3还未面市。

视频:https://www.gdcvault.com/play/1020686/Solving-Visibility-and-Streaming-in

PPT:https://www.gdcvault.com/play/1020231/Solving-Visibility-and-Streaming-in

Umbra 3

Umbra是一个芬兰中间件公司,做出核心技术之后,于2007年成立,专注于解决3d可见性。可以看到国外的创业公司相当的小而美,公司2014年的时候只有14个雇员,居然还分到了两个国家:在西雅图有自己的销售分部,面向全球销售。最近搜了下已经有4个销售部了。另一篇文章中提到巫师3使用Simplygon做LOD,可以发现国外有不少中间件公司,这些公司可能很小,但是相当专业。

在和各公司密切合作的过程中,Umbra会根据对方的需求(例如Bungie公司),对技术做相应演进。使用Umbra技术的产品包括:

  • Call Of Duty-Ghost
  • Destiny
  • KillZone-Shadow Fall
  • The Witcher 3-Wild Hunt
  • Unity(按:Unity确实是使用Umbra作为中间件的。不过应该不支持动态拼合)


Wichter 3的引擎团队与中间件选择

Wichter2开始使用自研RED Engine,现在是第三代。巫师2加强版是2012,巫师3是2015,比前作大35倍,开发了一个复杂的流式加载系统,改造了很多美术工作流工具。引擎团队50人左右,其中有16名左右的程序员,其他是QA和本地化人员。

选择中间件,最主要的理由是人力限制:你永远没有足够的人力来做所有细节。选择要点:

  • 文档和支持
  • 最好有源代码
  • 最好能为项目做定制需求


选择和实施时的技术要点

  • 内存管理:最好能定制分配器,以便跟踪库的内存使用情况
  • 最好支持多线程。Umbra的烘焙和查询都支持多线程


巫师3使用的中间件

  • Umbra 3
  • PhysX,以及其扩展插件APEX
  • SpeedTree
  • Wwise
  • Scaleform


Umbra方:剔除数据的流式加载

Umbra是这么工作的:输入需渲染的所有多边形集合,称为多边形汤,离线预处理后生成遮挡数据卷(tome)。对数据卷进行查询返回可见物体。他的最大优点是自动化:

  • 不需要手工标记
  • 不需要美术进行简化,直接输入渲染用的多边形集合


所以对于美术和程序来说非常友好,你只需要提供直接的数据就可以了。


此时Witcher3的需求是:

  • 大型开放世界,所以无法用人工方式处理。这很适合Umbra全自动流程
  • 流式加载,并需要处理LOD,这个是需要解决的


流式加载

为了实现流式加载,Umbra将世界切成矩形地块,分开烘焙,每个地块一个数据卷。在运行期,根据摄像机的当前坐标和视距,加载局部地块的数据卷,然后通过计算合并为一个综合的遮挡数据卷集合,提交给渲染系统查询。出区域的地块可以被卸载。

对于Umbra来说,这个算法的实现难点在于:

  • 每个块必须独立。即使计算遮挡数据特别是在边界时,非常想利用其他块的数据,也是不行的
  • 边界的匹配。邻居块的设置参数可能不一样,有时候需要使用很巧妙的技巧
  • 计算必须非常快,必须在几毫秒内完成。基本上都是每帧或者隔帧查询。


不过,在演讲后有人提问的情况下,都没有解释任何具体算法。

左图:预处理的分块。右图:根据摄像机视野判断的需加载数据块

LOD

要实现LOD,必须防止同一个物体的不同LOD将自己遮挡了。Umbra使用一个很简单的方案,严格区分遮挡者与被遮挡者两个概念,只有LOD0(即最高精度的版本)有遮挡能力,其他LOD都只能被遮挡。

Umbra查询后直接返回LOD。每级LOD有一个激活距离,通过距离做裁剪,这样做极大提高了查询性能。此外,可以手工指定距离计算使用的参考点,得到更高清的LOD版本,以便处理放大镜头。

Umbra考虑过更复杂的策略,例如,按屏幕面积选择LOD等级;又如,使用所有LOD的交集,而不是直接使用最精细的LOD0来计算遮挡(按:这是理论上最准确的结果,可能也会小幅加速)。但是总的来说,目前的简化方法是足够管用的。

流式加载的过程和效果

为了调试,提供了一个自由摄像机系统,可以暂时离开主角,观察当前的流式加载状态。此外将流式加载的过程、内存占用、模型统计、Umbra的统计数据可视化。

32:00开始有一段移动过程视频。其中绿色表示已加载的块,黄色表示流式加载中的块(加载是异步的)。



同一个城市的三种情况。第一个是典型的情况:主角在城镇门口,第三人称相机。只有城市前面的物体被显示,其他被剔除。


最差的情况:从天空鸟瞰城市,整个城市基本都可见。


最好的情况,主角在小巷中,玩家只能看到非常少的建筑物。此时:

  • 加载了43个遮挡数据块
  • 遮挡数据块共61M,外加动态生成的数据块间数据15M
  • 62000个模型块(Mesh Chunk)
  • 500个模型块可见
  • 1.8ms查询时间


其中模型块是模型的子部件,如下图绿色部分为不同的模型块。剔除以模型块为单位,所以可以只看见一个塔的塔尖。


此外,该遮挡系统通过包围盒支持动态物体,可以剔除包括:

  • 粒子特效
  • 蒙皮mesh
  • 模拟mesh(按:不知道是啥)
  • 贴片,包括动态和烘焙的


数据生成

使用专门的服务器组,在每夜构建时生成全部数据。同时,可以在编辑器里面手工更新。每个地块256*256m。烘焙时间最少几秒,最复杂的地块需要15~20分钟。

实测性能

Skillige岛屿

  • 8*8km
  • 平均加载45000~50000个模型块
  • 平均可见1~5%
  • Umbra数据~300M(数据+ID表)
  • 40~80M内存占用


Novigard城(刚才图片中的城市)

  • 8.5*8.5km
  • 平均加载超过100k个模型块
  • 平均可见2~5%
  • Umbra数据~250M
  • 45~80M内存占用



43:40开始展示漫游过程,推荐看一下,可以看到模型块拆分得非常细:

  • 视频中房顶的两个侧面是两个块
  • 最近处左下角房顶的正面的绿色草,就有3~4个块,在视角移动时开关。


阴影图目前还没有使用剔除系统,但是理论上用起来很简单,只需要先提交投影方向的查询就行。物理部分也没有使用该系统。

来源:GDC2014
知乎专栏:https://zhuanlan.zhihu.com/p/36281693
最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多