[CG] 顶点动画贴图 (Vertex Animation Texture, VAT)
什么是顶点动画?
简单来说,通过改变网格顶点的位置,使网格变形从而做成的动画。顶点动画的灵活度要远远高于骨骼动画。骨骼动画是靠骨骼(一堆有层级结构的节点,数量应该是远远小于网格顶点的数量的)的变化来驱动网格的形变,从自由度上来说,顶点动画每个网格的顶点都可以发生变化,因此自由度要远高于骨骼动画,可以做出骨骼动画达不到的一些效果,例如像流体这种拓扑发生变化的物体。
如何在游戏引擎中使用顶点动画?
在动画的每一帧,网格的顶点的位置、数量、拓扑都可以发生变化,因此对于这种动画,我们只能把每一帧的数据都给保存下来(当然也有网格序列的压缩方法,例如利用类似 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 改变了这个网格的顶点数据而已。
我们可以简单的分一分几种动画类型:
- 拓扑改变的:例如流体
- 拓扑不变的:例如布料
每种类型的处理会稍稍有些区别:
拓扑改变的
- 首先需要遍历一下网格序列,找一下哪一帧的网格的面最多。原因是绘制的三角面的数量,如果我们随便找一帧作为基础网格,例如基础网格有 100 个三角面(face),而其他帧也许有 200 个三角面,那么无论如何也没法绘制 200 个三角面了,所以需要找一下最大的那个。对于某一帧的绘制,也许当前需要绘制的面的数量小于基础网格面的数量,这个也不要紧,可以将初始网格的所有顶点的位置都设置为 (0,0,0),所以多余的面也不会画出来。
- 计算贴图的尺寸,因为贴图的尺寸关系到我们如何进行采样。可以简单的计算一下,我们可以假设 y 方向代表的是不用的帧,而 x 方向代表的是同一帧内不同的顶点。例如一帧我们有 1000 个顶点(顶点可能会重复,例如 2 个面有 6 个顶点,不会共用顶点),那么我们可以选择 width = 512 的贴图,那么要存 1 帧的 1000 个顶点,需要 2 行,如果我们有 100 帧,那最终 VAT 的尺寸为 (512, 200)。
- 计算 顶点 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)
- 计算完成 uv 以后,我们就可以将 uv 数据写入网格顶点数据来,网格的顶点数据可以是 POS + TEXCOORD0 + NORMAL。
- 写入贴图,可以遍历每一帧,然后在每一帧按照面的顺序遍历每一个顶点,在贴图中,依次每 3 个顶点代表一个面。同理,法线数据(normal)也是类似顶点的方式,写入另一张贴图里。这里需要记得一件事情,如果是 RGB8,那么 RGB 和对应 xyz,但是 xyz 需要先归一化一下,即用 minmax 归一化的方法,因为 RGB 的只能存储 0-255。
- 保存元信息,这里的元信息可以保存帧数,所有顶点中的最大最小值,bbox 等自己可以用的到的信息。
这样我们最终得到了 VAT_pos, VAT_nor, mesh, meta 四个文件,分别对应顶点位置信息、法线信息、网格信息和元信息,有了这些数据就可以拿到游戏引擎中去解析了。
拓扑不变的
拓扑也可以按照拓扑改变的方法可以进行制作,不过可以省略一些步骤,例如遍历网格序列寻找最大的面数,因为拓扑不变,所以可以用第一帧的网格作为基础网格,其他的做法基本都一样
有了 VAT 如何使用?
有了 VAT 以后,需要有可以解析的 shader 进行支持,即在 shader 里将 VAT 里的数据读出来,这个 shader 根据自己的烘焙的规则,然后自己进行解析。github上有一些开源的 shader,或者是 Houdini 配套的 shader 可以使用。本文先介绍一下 VAT 的概念以后烘焙的方法,下一篇来介绍一下在 shader 中解析的方法。
[CG] 顶点动画贴图 (Vertex Animation Texture, VAT)的更多相关文章
- 《The Cg Tutorial》阅读笔记——动画 Animation
这段时间阅读了英文版的NVidia官方的<The Cg Tutorial>,借此来学习基本的图形学知识和着色器编程. 在此做一个阅读笔记. 本文为大便一箩筐的原创内容,转载请注明出处,谢谢 ...
- Vertex Fetch Texture (VTF)
http://www.opengl.org/wiki/Vertex_Texture_Fetch Vertex Texture Fetch This article contains inacc ...
- unity下贴图混合(Texture Blending)
在unity制作自定义时,经常会遇到自定义妆容等问题,美术会提供大量的眉毛/胡子/腮红等贴图,来供用户选择. 美术给出的眉毛的小贴图如下: 在用户选用不同的胡子眉毛,可以将选定的小贴图和皮肤base贴 ...
- 0UE3 材质概要
材质概要 概述 参数 当创建材质时如何考虑颜色 材质表达式 Abs(求绝对值) 添加 AntialiasedTextureMask AppendVector(向量合并) BumpOffset(凸凹偏移 ...
- OpenGL之纹理贴图(Texture)
学习自: https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/ 先上一波效果图: 实际上就是:画了一个矩形,然后 ...
- Texture 纹理贴图
基础贴图Shader:只有纹理 1. 在属性中声明纹理贴图: _MainTex ("Texture", 2D) = "white" {} 2. 在Pass中声明 ...
- angr原理与实践(二)—— 各类图的生成(CFG CG ACFG DDG等)
本文系原创,转载请说明出处 Please Subscribe Wechat Official Account:信安科研人,获取更多的原创安全资讯 上一篇文章介绍了angr的原理,自此篇文章开始, ...
- 知识图谱-生物信息学-医学顶刊论文(Briefings in Bioinformatics-2021):生物信息学中的图表示学习:趋势、方法和应用
4.(2021.6.24)Briefings-生物信息学中的图表示学习:趋势.方法和应用 论文标题: Graph representation learning in bioinformatics: ...
- cg tut
Gesture Drawing with Alex Woo Gesture Drawing with Alex Woo and Louis Gonzales http://eisneim.com/?p ...
随机推荐
- k8s动态存储管理GlusterFS
1. 在node上安装Gluster客户端(Heketi要求GlusterFS集群至少有三个节点) 删除master标签 kubectl taint nodes --all node-role.kub ...
- MySQL十种锁,一篇文章带你全解析
MySQL有两个核心的知识点,索引和锁.前几篇文章已经详细讲解了MySQL索引实现机制,今天再一起学习一下MySQL的锁. 1 为什么要加锁? 当多个事务并发操作同一批数据的时候,如果不加锁,就无法保 ...
- 简单实现python接口自动化(一)
目的:excel中维护接口用例数据,通过python中requests库进行读取用例,并把运行结果与excel中的预期结果对比,最后把执行情况写入到excel中去. excel维护数据: 具体的接口名 ...
- Navicat中查询mysql版本
SELECT VERSION( ) FROM DUAL
- 数学公式 Latex 练习
\[1+x+x^2+x^3+\cdots=\frac{1}{1-x}\quad x\in(-1, 1) \] 证明:设左边式子项数为 \(n\) 那么可以得到: \[\begin{split} S & ...
- Tapdata Cloud 2.1.2 来啦:大波细节已就绪!字段类型可批量修改、支持微信扫码登录、新增支持 Vika 为目标
Tapdata Cloud cloud.tapdata.net 让数据实时可用 Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持 Oracle.MySQL.PG.SQL Ser ...
- HBase学习(二) 基本命令 Java api
一.Hbase shell 1.Region信息观察 创建表指定命名空间 在创建表的时候可以选择创建到bigdata17这个namespace中,如何实现呢? 使用这种格式即可:'命名空间名称:表名' ...
- SQL语句编写
mybatis插入数据 下面的item.avatarUrl取出的是java实体类里面的属性,所有需要大写 插入的SQL: INSERT INTO `one` VALUES(1,"第一个&qu ...
- for_in循环
for-in循环也可以简单称为for循环 in表达从(字符串,序列等)中依次取值,又称为遍历(全部都要取到) for-in遍历的对象必须是可迭代对象 目前可以简单认为只有字符串和序列是可迭代对象 它是 ...
- 平衡树——splay 一
splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...