Appearance
CompatibleFaceBlendShape 协议
用三层并行的数据结构,让同一份面捕解算结果同时喂给 ARKit 协议模型、VRM 协议模型和带特殊表情通道的模型,谁也不用作废重做。
技术问题
虚拟人项目里,模型和协议是绑死的:ARKit 系模型吃 52 个基础表情通道,VRM 系模型吃 VRMBlendShapeProxy 定义的那套基准表情,两边互不兼容。
这带来两个实际成本。一是美术侧:要同时支持两种模型,建模蒙皮阶段就得做两套 BlendShape。二是存量资产:线上已经存在大量基于某一种协议的模型,换协议等于让用户重做一遍适配。另外,ARKit 的 52 个通道只有基础表情,没有喜怒哀乐这类特殊表情;VRM 的基准表情数量又太少,表现力不够。
现有方案不足
- 协议各自为政:ARKit 与 VRM 之间不能互相转换,驱动层要写两套取值逻辑。
- 表现力与兼容性二选一:基础协议通道全但无特殊表情,卡通协议有特殊表情但通道少、效果不佳。
- 存量模型迁移成本高:任何新协议如果只定义自己的一套通道,线上老模型就全部失效。
核心思路
不改任何一家的协议,而是把各家协议作为并行层级装进同一个数据结构。解算层一次计算,同时填充所有层;驱动层按模型自己的协议,从对应层级取数。
mermaid
flowchart TD
A["面捕解算器<br>每帧输出面捕数据"] --> B["CompatibleFaceData"]
subgraph B["三层并行结构"]
C["ARKit 层<br>52 个基础表情通道"]
D["VRM 层<br>基准表情通道"]
E["Effect 层<br>喜怒哀乐等特殊表情"]
end
B --> F{"驱动层按模型<br>协议取数"}
F --> G["ARKit 模型"]
F --> H["VRM 模型"]
F --> I["带特殊表情<br>通道的模型"]关键实现
三层并行,而非互相转换
层与层之间不做转换——转换意味着误差累积和规则维护。每层的数据都由解算器独立填充,保证各协议拿到的都是一手解算结果。
驱动流程
每帧的驱动只有四步:
- 解算器得出当帧面捕数据;
- 获取目标模型,得到模型的驱动类型;
- 按驱动类型从对应层级取 BlendShape 数据;
- 赋值到模型的 BlendShape 通道。
协议判断不在框架内做——业务端天然知道自己加载的是什么模型,框架只保证每层数据都在。
特殊表情层
Effect 层的喜怒哀乐等表情值不是美术手 K 的,而是由面捕特征点经自研推导算法计算得出(见 BlendShape 基本表情转换特殊表情)。模型只要在建模时做了对应的特殊表情通道,就能直接被驱动。
可扩展性
协议类型不做限定。后续要接入新的 BS 协议(例如商汤),只需要在结构中扩展一个新层级,已有层级和驱动逻辑不受影响。
应用场景
- 虚拟直播 PC 端:一套面捕链路同时驱动 ARKit 系和 VRM 系模型。
- 存量模型接入:线上已有模型不需要重做 BlendShape 适配。
- 特殊表情玩法:支持喜怒哀乐的模型直接获得更丰富的表情表现。
关联案例
- CompatibleFaceData 通用协议:协议的工程落地。
- ARKit 与 VRM 桥接:双协议模型的实际驱动。
- 基于 Mediapipe 的面部捕捉算法:本协议上游的解算链路。