4

[CG] 顶点动画贴图 (Vertex Animation Texture, VAT) - 芒果和小猫

 1 year ago
source link: https://www.cnblogs.com/WAoyu/p/16667843.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

什么是顶点动画?

简单来说,通过改变网格顶点的位置,使网格变形从而做成的动画。顶点动画的灵活度要远远高于骨骼动画。骨骼动画是靠骨骼(一堆有层级结构的节点,数量应该是远远小于网格顶点的数量的)的变化来驱动网格的形变,从自由度上来说,顶点动画每个网格的顶点都可以发生变化,因此自由度要远高于骨骼动画,可以做出骨骼动画达不到的一些效果,例如像流体这种拓扑发生变化的物体。

如何在游戏引擎中使用顶点动画?

在动画的每一帧,网格的顶点的位置、数量、拓扑都可以发生变化,因此对于这种动画,我们只能把每一帧的数据都给保存下来(当然也有网格序列的压缩方法,例如利用类似 PCA 的方法等),因此数据量会很大。在游戏引擎中有两种常见的做法

  • 一种是在 CPU 侧,将数据存储为网格序列,然后按照一定的规则去播放这个网格序列,像 Unity 就支持 .abc (alembic)文件的格式的导入。
  • 一种是在 GPU 侧,将数据写入到一张或几张贴图中,然后在 shader 中贴图进行采样、还原,然后在 vertex shader 中根据贴图中的数据来改变顶点的位置,这就是本文要介绍的 “顶点动画贴图” (VAT)技术。

VAT 烘焙的流程

VAT 技术很灵活,因为核心思想只是在贴图中存了一些数据,至于这个数据怎么存?存什么?怎么解析?完全都是可以自己控制的,因此也没有什么规范之类的。在 Houdini 中是支持导出 VAT 的,也有配套的 Unity/UE 中解析的 shader,Blender 似乎是没有内置的导出 VAT 的能力,一般都是靠自己写或者相关插件之类。其实也不一定要从 DCC 软件中导出 VAT,只要这些模型文件(例如 .usd, .abc, .fbx, ...)中保存了网格序列必要的信息,我们可以直接去解析这些文件,来制作 VAT。除了保存数据的贴图外,还需要一个基础的网格来承载基础的顶点数据,因为必须要有网格数据,才能用 shader 来进行绘制,每次渲染都是绘制的这个网格,只不过我们在 shader 中利用 VAT 改变了这个网格的顶点数据而已。

我们可以简单的分一分几种动画类型:

  • 拓扑改变的:例如流体
  • 拓扑不变的:例如布料

每种类型的处理会稍稍有些区别:

拓扑改变的#

  1. 首先需要遍历一下网格序列,找一下哪一帧的网格的面最多。原因是绘制的三角面的数量,如果我们随便找一帧作为基础网格,例如基础网格有 100 个三角面(face),而其他帧也许有 200 个三角面,那么无论如何也没法绘制 200 个三角面了,所以需要找一下最大的那个。对于某一帧的绘制,也许当前需要绘制的面的数量小于基础网格面的数量,这个也不要紧,可以将初始网格的所有顶点的位置都设置为 (0,0,0),所以多余的面也不会画出来。
  2. 计算贴图的尺寸,因为贴图的尺寸关系到我们如何进行采样。可以简单的计算一下,我们可以假设 y 方向代表的是不用的帧,而 x 方向代表的是同一帧内不同的顶点。例如一帧我们有 1000 个顶点(顶点可能会重复,例如 2 个面有 6 个顶点,不会共用顶点),那么我们可以选择 width = 512 的贴图,那么要存 1 帧的 1000 个顶点,需要 2 行,如果我们有 100 帧,那最终 VAT 的尺寸为 (512, 200)。
  3. 计算 顶点 uv 坐标,在计算完 VAT 的尺寸后,我们需要给基础网格的顶点计算 uv 坐标,来代表这个顶点在 VAT 对应的位置。如下:
# + 0.5 是为了采样的时候在像素的中心位置
# 1.0 - 是因为 uv 坐标一般左下是 (0,0),而图像一般左上是 (0,0)
for i in range(1000):
    u = ((i % 512) + 0.5) / 512 
    v = 1.0 - ((i // 512) + 0.5 / 200)
  1. 计算完成 uv 以后,我们就可以将 uv 数据写入网格顶点数据来,网格的顶点数据可以是 POS + TEXCOORD0 + NORMAL。
  2. 写入贴图,可以遍历每一帧,然后在每一帧按照面的顺序遍历每一个顶点,在贴图中,依次每 3 个顶点代表一个面。同理,法线数据(normal)也是类似顶点的方式,写入另一张贴图里。这里需要记得一件事情,如果是 RGB8,那么 RGB 和对应 xyz,但是 xyz 需要先归一化一下,即用 minmax 归一化的方法,因为 RGB 的只能存储 0-255。
  3. 保存元信息,这里的元信息可以保存帧数,所有顶点中的最大最小值,bbox 等自己可以用的到的信息。

这样我们最终得到了 VAT_pos, VAT_nor, mesh, meta 四个文件,分别对应顶点位置信息、法线信息、网格信息和元信息,有了这些数据就可以拿到游戏引擎中去解析了。

拓扑不变的#

拓扑也可以按照拓扑改变的方法可以进行制作,不过可以省略一些步骤,例如遍历网格序列寻找最大的面数,因为拓扑不变,所以可以用第一帧的网格作为基础网格,其他的做法基本都一样

有了 VAT 如何使用?

有了 VAT 以后,需要有可以解析的 shader 进行支持,即在 shader 里将 VAT 里的数据读出来,这个 shader 根据自己的烘焙的规则,然后自己进行解析。github上有一些开源的 shader,或者是 Houdini 配套的 shader 可以使用。本文先介绍一下 VAT 的概念以后烘焙的方法,下一篇来介绍一下在 shader 中解析的方法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK