Ducklexander

MetaHuman 轉 VRChat Avatar|Webcam Face Tracking

· Unity

把 MetaHuman 轉成 VRChat avatar,並用筆電 webcam 即時驅動表情。這篇主要記錄 Blender、Unity 與 VRChat 製作過程和遇到的問題。

簡介

MetaHuman 之前好像只能在 Unreal 用。後來看到有人把它帶進 Blender,就開始想說,既然都可以進Blender,那應該也可以進Unity,也可以做成 VRChat avatar,用筆電的 webcam 即時帶動表情之類的。那如果這條路也走得通,說不定也可以試看看MetaHuman進到 Quest 3 Standalone的VR內容中。

目前,我先完成了純PC 版的。Avatar 的臉有 172 個從 Epic RigLogic rig 烘焙出來的 blendshapes,再透過免費的 webcam tracker 和 OSC 即時控制表情。

在 VRChat 中,用我筆電的 webcam 驅動臉部表情
在 YouTube 觀看

工具和比較完整的步驟都放在 GitHub:metahuman-to-vrchat。這篇主要就寫一下我是怎麼做的,還有哪些地方讓我卡了一陣子這樣。

Unreal 到 VRChat

先前 MetaHuman 的使用和 Unreal Engine 綁得很緊。從 UE 5.6 起,它納入了一般 Unreal Engine EULA,在營收低於 100 萬美元的條件下,是可以免費用於其他引擎和平台。所以我現在才能把自己製作的 MetaHuman avatar 上傳到 VRChat。原始資產的公開散布是另一回事,所以本次的 repo 只放了工具;而 DNA files、textures 和 mesh 需要大家用自己的。

另一個難題是臉。VRChat 基本上是靠 blendshapes 做表情(據我所知),但MetaHuman 用的是 RigLogic,包含大量 facial joints 和 corrective shapes。如果直接匯出 FBX,這些表情不會跟著過去。所以我最後讓 rig 逐一做出表情,再把結果烘焙成 blendshapes。

製作流程

Unreal Engine 5.6   MetaHuman Creator -> head.dna、body.dna、textures、hair cards
Blender 5.1         Poly Hammer Character DNA 執行 RigLogic -> 烘焙 172 個 shape keys -> Avatar.fbx
Python              重新打包 textures、翻轉 normal maps、繪製 hair strand atlas
Unity 2022.3.22f1   import settings、Poiyomi materials、Jerry's ARKit face-tracking template
VRChat              webcam -> FoxyFace -> VRCFaceTracking -> OSC -> avatar

Blender 這段由 headless script 處理。在我的筆電上,從 head.dna 重新產生 FBX 不到兩分鐘。我後來拿封存資料重跑公開版本,產出的 FBX 和當初上傳的檔案在位元層級完全相同,總算能確認整理 repo 時沒有把流程改壞。

Blender

最後烘焙出來的是 172 個 shapes,包含 ARKit 52、VRChat visemes、Unified Expressions 的額外表情、MetaHuman 專用 controls 和情緒預設。與即時 RigLogic 比較,最大誤差是 0.00036 mm。

這裡最讓我意外的是,免費版 Poly Hammer addon 的 shape-key import 選項其實沒有作用。少了 corrective shapes,嘴唇和眼皮那些細微變化就不見了,最後還是得自己從 DNA 讀出來。 第一次烘焙也很有迷惑性:script 順利跑完、產生 169 個 shapes,但只有第一個帶了正確的 correctives。問題只寫在 stderr。

也有試過 Blender 的「New Shape From Mix」,結果它會忽略 armature,而 MetaHuman 的表情大部分正是靠 armature 帶動。有些 controls 在 neutral face 上也完全不動,像 lips-together,就得用 open jaw 當基準去烘焙差值。這些細節都收進 repo 的流程裡了。

Textures 和頭髮

一開始會以為 normal maps 不用翻轉,結果毛孔的受光方向全錯了,畫面卻不會報任何錯。後來用 skin maps 做了個有 control 的小測試,才確認 Unreal 和 Unity 的 green channel 方向不同。

頭髮也沒辦法直接匯出一張 texture。MetaHuman 用 procedural strand shader,我改成替頭髮、睫毛和眉毛畫 strand atlas,再把 hair cards 對上去。最難處理的居然是眉毛:936 張 cards 重疊在一起,只要每張稍微太不透明,就會變成一整塊黑色。(.m.)

Unity & VRChat

Unity 這段表面上是在調設定,實際上很容易被沒有提示的錯誤絆住。有一次關掉 FBX 的「Convert Units」,avatar 直接變成 170 公尺高。而Read/Write 和 Streaming Mip Maps 也得開,不然 SDK 不讓 build。後來我做了一個小型 editor package,幫忙套用和檢查這些設定。

材質方面,Poiyomi 的預設值比較適合 toon avatars。這個角色因為是寫實臉,原本在不同 world 裡看起來都不太吃環境光;改了四個數值後,臉才會跟著場景的冷暖色變化。

上傳前,還要把 Poiyomi materials 鎖定成 generated shaders。有次眼睛的 material 漏掉了,在 VRChat 裡直接變成洋紅色。現在 package 會擋下還沒鎖定的 material。

整理 repo 時又發現一個尷尬的問題:skin scattering LUT 在 editor 裡看起來沒事,鎖定 shader 後卻把陰影中的臉頰染紅。我已經上傳的 avatar 就有這個狀況;工具裡目前把 LUT 移除了。

用 webcam 帶動表情

目前Face Tracking是用 FoxyFace 從 webcam 畫面抓 MediaPipe landmarks,再經過 VRCFaceTracking 和 OSC 送進 VRChat,最後由 Jerry's ARKit template 對應到 52 個 ARKit blendshapes。

第一次接起來時,三個環節剛好各壞各的:VRChat 的 OSC 沒開、VRCFaceTracking module 被我用複製 DLL 的方式安裝(其實得從 module registry 裝),FoxyFace 本身也沒在跑。後來查各個 UDP port 被哪個 process 佔用,幾秒就找出原因。這個檢查也放進 repo 了。

現在整條流程已經能跑,avatar 的臉也會跟著我動。不過 FoxyFace 還沒校正,眼睛目前看起來半閉。我有錄到一組 eyelid parameter 數值,但當時 OSC parser 有 bug,尾端的數值也像是我離開了鏡頭範圍,所以先不拿它當結論。校正完成後,我會再補真正的前後比較。

目前的限制

PC 上的 Performance Rank 是 Very Poor,主要因為模型有 110,616 個 triangles。頭部又承載了 blendshapes,不能直接大幅減面而不影響臉部細節。其他指標是 Good 或 Excellent,但很多玩家預設會隱藏 Very Poor avatars。

目前也是 Desktop mode 的做法。戴上 headset 後,webcam 會看不到臉;如果要在 VR 裡追蹤表情,還需要 face tracking 和 eye tracking 的硬體,並換掉追蹤用的 module (但我現在還沒有XD)。 目前這版也只在我自己的 Windows 11 筆電和指定版本上測過;更新版的 Blender addon 和 FoxyFace 還沒測。

之後想做的

接下來可能會想試試 hair physics bones,還有追蹤關閉時自動眨眼。自動眨眼需要的 shape 已經是工具裡的一個選項。之後如果要用 headset 玩,可能才會再來研究看看 VR tracking 的配置這樣。

Repo 和逐步說明:github.com/Ducklexander/metahuman-to-vrchat