Skip to content

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>通道的模型"]

关键实现 ​

三层并行,而非互相转换 ​

层与层之间不做转换——转换意味着误差累积和规则维护。每层的数据都由解算器独立填充,保证各协议拿到的都是一手解算结果。

驱动流程 ​

每帧的驱动只有四步:

  1. 解算器得出当帧面捕数据;
  2. 获取目标模型,得到模型的驱动类型;
  3. 按驱动类型从对应层级取 BlendShape 数据;
  4. 赋值到模型的 BlendShape 通道。

协议判断不在框架内做——业务端天然知道自己加载的是什么模型,框架只保证每层数据都在。

特殊表情层 ​

Effect 层的喜怒哀乐等表情值不是美术手 K 的,而是由面捕特征点经自研推导算法计算得出(见 BlendShape 基本表情转换特殊表情)。模型只要在建模时做了对应的特殊表情通道,就能直接被驱动。

可扩展性 ​

协议类型不做限定。后续要接入新的 BS 协议(例如商汤),只需要在结构中扩展一个新层级,已有层级和驱动逻辑不受影响。

应用场景 ​

  • 虚拟直播 PC 端:一套面捕链路同时驱动 ARKit 系和 VRM 系模型。
  • 存量模型接入:线上已有模型不需要重做 BlendShape 适配。
  • 特殊表情玩法:支持喜怒哀乐的模型直接获得更丰富的表情表现。

关联案例 ​

罗子初 · AI 座舱专家 · 8年端侧研发

Lv.1