【Siggraph 2007】 Maxis Sketches

今天给大家分享的是《孢子》中的程序化世界生成技术,相关链接在文末的参考章节有给出。

这里的生成技术分为多个部分,这里也按照原文的陈述顺序进行排列。

1. Player-Driven Procedural Texturing

这个技术要解决如下两个问题:

  • 如何给玩家创建的物件附加贴图?
  • 如何将玩家创建的物件转换为游戏中的模型?

前人工作:

  • SSX中是通过对物件mesh以及配件进行替换来实现
  • Sims2 Body Shop则是面部通过顶点morph实现。clothing,top & bottom texture pages,没看懂这里说的啥意思。
  • Need for Speed vehicles是通过贴花跟顶点morph实现

玩家可控的贴图工具具有如下一些Goal

  • 能够根据玩家的输入产出令人满意的效果
  • 不能太过于细节,否则很无聊
  • 也不能太过简单,否则效果太重复。希望能够超出全局贴图图层选择(这里没看懂,是说支持自定义贴图选择?)

根据《孢子》的玩法,这里主要需要两种贴图程序化方案

  • 生物、植物、Cell的贴图方案
    • 基于画刷的3D贴图painting
    • 通过effect system驱动,而非手工填刷
    • 通过多层不同的参数化脚本实现效果的多样性
  • 矿石、矿山的贴图方案
    • 贴图repeating
    • 按照region进行paint
    • 程序化UV

下面来看下实施细节。

皮肤Paint方案

  • 皮肤画刷带有多层贴图(diffuse,specular,alpha,bump map),笔刷是通过粒子系统驱动的,笔刷具有如下的一些特点:
    • 2D & 3D填刷
    • UV自动生成,cubemap partition
    • 填刷效果通过脚本控制
  • 皮肤mesh是自带UV的,因此只要画刷一刷上去,就能得到对应的贴图效果
  • 画刷的选择以及其作用位置是通过effect system来控制的
    • 不是整个mesh用同一套,不然无法实现多样性,不过这样一来,性能消耗也会增加
    • particles可以随着时间的推移在mesh的surface上移动,从而实现动态效果。这么看来,画刷的作用不是固定下来的,而是每帧动态计算的,如果全屏画刷种类有限的话,性能应该也能控制住;可以通过骨骼的变化来控制这个移动效果;这里集成了一套脚本库,用来实现不同的效果。

建筑、载具贴图UGC

  • 这类模型是通过一种叫做rigblock的可形变部件组合而来
  • 为了避免过于剧烈的形变导致UV失真,这里对UV做了特殊处理,这个过程通过程序化完成
  • 最终生成的mesh会经历一次mesh合并与贴图合并,从而降低DrawCall

程序化UV

  • 模型部件形变
  • 模型部件上为不同region添加了不同的标签
    • 这个标签后面在材质以及功能区域上也会有应用
    • 即根据不同的标签施加不同材质,添加不同的逻辑功能
  • 添加了UVing标签的region
    • 通过多种方式生成其UV,boxmap,cubemap partitioning,Cylinder, sphere, planar, disc等映射
  • 这个过程是在VS中完成的
  • 整个贴图是通过两种颜色实现参数化控制的

遭遇问题与解决方案

  1. 性能问题,UGC物件Mesh数目、材质数目、贴图数目过多在,从而导致DrawCall过多,此外也不支持LOD。
    解决方案:将多个材质的贴图合并到一张中,并创建单独的一套UV,将mesh也合并到一起,并实时生成LOD数据
  2. 生成模型的AO效果缺失
    解决方案:通过PostProcess模拟?或者运行时烘焙,整个过程是多线程,异步执行

2. Creating Spherical Worlds

孢子的世界观主要包含两块。

  1. 世界变迁
    1.1 多个时代,希望无缝过渡:Cell Life(细胞时代),2D地图;星球三个时代(生物,部落,文明);太阳系;银河系。
  2. 星球设计
    2.1 目标:
    a). 星球数目要很多,远多于能手动编辑的数量
    b). 星球上要有玩法,而且外观也要能够满足需求
    c). 星球要能在运行时快速自动生成,不接受本地存储(数据量太大)
    d). 星球还要支持玩家的手动编辑(地形)
    2.2 关键点
    a). 如何实现参数化保存:通过一套参数可以在运行时自动重建
    b). 如何快速生成球面高度数据
    c). 如何根据高度数据实现星球的自动贴图创建(材质着色等)
    d). 如何保证手动编辑的便捷与美观

星球参数化存储方案
现有方案有如下几种:

  • 经纬度
  • Gnomic
  • 稀疏体素
  • 贴图方案:常规贴图有cubemap、diamond,duodecahedron等;还有运行时生成贴图方案;贴图投影方式有正交投影与透视投影两种

方案的目标为:

  • 降低几何失真
  • 存储高效
  • 能够实现3D空间到UV空间的快速映射(方便进行数据读取以获得高度以及着色等数据)
  • 支持贴图的tiling
  • 支持法线贴图的高效生成

最终考虑采用的方案为:cubemap贴图方案(在部分文献中也称为cubic sphere方案),这种方案在顶点处虽然存在扭曲,但是比极坐标方案要好很多;此外法线贴图生成可以通过高度图实现,如通过2D平面的微分方程(DDF)得到法线,之后通过雅克比转换成球面形式;高度贴图的生成可以通过2D笔刷完成,笔刷预置了高度模板。

地形染色则是根据高度图计算得到,根据海拔生成水面,根据高度图也可以得到梯度、curvature。整个染色逻辑是基于artist的公式而实现的,基本原理是先根据source贴图生成base color,之后在运行时生成细节贴图,并根据星球类型进行调整,如不同的星球类型具有不同的大气、温度等数据

运行时编辑
最初方案是通过effect script控制,整体只需要一个mega script,其中包含多个sub script,这里遇到的问题是难以实现artist控制,相应的解决方案为在上层添加一个terrain script,最终可以实现每个脚本对应一种效果:

3. Fast Object Distribution

物件程序化生成的整体目标为在目标区域通过程序化的方式生成符合自然规律的物件,需要输出位置,朝向、颜色、alpha以及密度等数据,这个目标的完成需要符合如下的要求:

  • 高效,运行时使用
  • 低内存占用
  • 可复现

现有的参考方案有:

  • 伪随机数,如LCG以及Mersenne Twister算法
  • 蓝噪声
  • Wang tiles
  • Dart throwing

最终的方案为通过Halton Sequence生成N个采样点,这个方案的优点为:

  • 可以很好的避免correlation(关联?)
  • 可以保证采样点分布间隔相对稳定
  • 新增的采样点可以实现跟已有采样点的和谐并存
  • 实现简单
    • 不需要细分(subdivision)
    • spatial data structure
    • 无状态

其不足之处在于计算消耗略高。虽然可以使用LUT,但是对于采样数目过的时候,消耗依然会很高,同时添加了采样数目上限的限制。

对于这个缺点,可以考虑增量式Halton,即找到H(n+1)跟H(n)之间的差值。

这里使用i/N作为magic number,这个数值会用来对属性进行索引,即对属性进行选取,属性包括颜色,透明度以及朝向;也可以用来discard某个sample。

传统的属性选取方案为通过某个参数(比如particle age)进行索引,或者通过随机数进行索引,其效果给出如下:

新方案为使用sample index进行索引,效果给出如下:

同样的物件随机分布方案可以应用在多种物件上面,美术同学可以控制每种物件的分布范围,后续的物件不会跟之前摆放的物件存在位置冲突。

这种方案中,物件的密度控制需要做一些处理:Halton方案会随着增加物件种类,导致整体物件密度不断上升。

可以考虑通过density map进行控制:

根据当前采样点的位置采取密度贴图的密度值,并与当前采样点的顺序进行比对

贴图
效果

4. Rigblocks: Player-Deformable Objects

用户可控制形变的物件指的是通过组件组装的方式实现不同的模型效果,通过组件组装的方式实现不同的模型效果,拼接的组件并不是静态的,而是自身带有动画的,这里说的动画不是指的随着时间而变化的动画,而是随着拼接位置(空间)而形变的动画,通过这种模式,可以实现相同的组件拼接在不同的位置产生不同的效果,增加了可玩性。

PCG规则随着时间与空间而变化是一种增强可玩性的好方式,另外也可以跟随一个参数实现不同的效果,从而实现与现实中乐高完全不同的拼接方法,增强物种多样性;随时间变化的方式可能不合适,因为不好复现,难以把控。

其设计目标有三个:

  1. 希望玩家能够自己组装出游戏中的关键组件
  2. 玩家创建的组件可以发布,供其他玩家使用
  3. 可以提供丰富的体验与较少的美术工作

而这类物件有三种类型:生物(基础组件包括眼睛,手臂,脑袋等)、建筑(墙体、门窗等)、载具(轮子,车身、引擎等)。

从形变效果来看呢,允许玩家使用提供的组件组装出各种物件,这里提供了多种组装模式:stacking、pinning、sliding等。而组装的组件需要带有动画效果,支持根据组件自身的动画拼接出合适的组合动画效果,同时还允许玩家通过某种方式对输出的动画进行调整。

生物组装逻辑
基础模块是一种特殊模块,即body mesh。允许玩家对基础骨骼进行修改,如更改脊柱以及将肢体attach到脊柱上等。之后通过metaballs生成mesh,并将rigblock挂接到body上,下面来看下案例演示:

上图展示了基础block通过局部缩放可以实现不同效果。

上图展示了基础block通过拼接可以实现不同效果。

建筑组装逻辑
为不同类型的建筑提供不同的全套基础组件,比如城堡:

跟生物组件一样,基础组件是可以通过局部编辑实现不同效果的。

工作流
传统动画工作流中,每个动画对应一个动画文件;而rigblock则由多个组件组成,每个组件都有自己的动画数据,需要考虑提供一套track editor实现关键帧编辑导出功能,这里使用的方案是MEL脚本控制着handle rigs的添加。

整个过程是基于handle驱动的动画逻辑,美术同学可以放置handle,因此可以通过Maya实现迭代。

动画技术点

  1. 动画融合
  • 不能通过传统的动画混合方式实现
  • 可以考虑将多个动画进行叠加实现,叠加数据是相对于原点(rest pose)的偏移,通过将最终叠加的transform数据转换成deform matrix来实现与maya的效果的匹配.

  • multiblender(多层混合?),则支持传统的运行时动画效果(这里有一层混合?),在传统的运行时动画效果基础上添加形变动画。

  • 烘焙:

    • 有如下一些考虑点:1. 编辑是一次性的,不会时时刻刻都要用到编辑时数据;2. 编辑数据直接渲染输出性能不如不做编辑的运行时数据
    • 基于上述考虑,可以尝试将编辑后的数据烘焙成运行时的数据,从而实现性能的提升:移除形变动画并生成一个全新的base mesh。
    • 单个模型需要保证一定的渲染性能,如单个贴图,单个材质,单个drawcall,且要支持LOD
    • 最终考虑使用动画烘焙的方案来实现相关目标,不过这里有一些问题需要考虑:
    1. 对于自身带有动画的组件(如嘴巴)来说,希望这些组件在attach&deform之后动画可以如预期一样在最终的物件上存在
    2. 但是合并后的物件的骨骼数目可能不一定有原始组件上的骨骼数那么多,效果会存在损失
    3. 因此需要将原始组件的mesh顶点等数据重绑到最终的物件骨骼数据上

这个方案的特点是:

  • 当前的操作方式十分直观且简单,且经过验证得到了玩家的认同
  • 现有的方案能够产出十分丰富的效果,能够满足玩家创造力的表达,远超预期
  • 在激发与放大玩家创造力之间做到了很好的平衡,在两个极端之间找到了一个很好的平衡点
    • 玩家不可控制,但能够输出十分符合审美的效果
    • 玩家完全控制,但是输出效果难以入目

参考

[1]. SIGGRAPH 2007 Maxis Sketches
[2]. Player-Driven Procedural Texturing PPT
[3]. Player-Driven Procedural Texturing Thesis
[4]. Creating Spherical Worlds PPT
[5]. Creating Spherical Worlds Thesis
[6]. Fast Object Distribution PPT
[7]. Fast Object Distribution Thesis
[8]. Rigblocks: Player-Deformable Objects PPT
[9]. Rigblocks: Player-Deformable Objects Thesis

你可能感兴趣的:(【Siggraph 2007】 Maxis Sketches)