Eyes were the warmup. Mouth is where SAUCE learns to speak. If the eyes are the window to the soul, the mouth is the door β and we need that door to open, close, purse, pout, and sync to audio without exploding the vertex count.
Why Mouth Is Harder Than Eyes
Eyes blink. Thatβs one state transition: open β closed. The UV slides horizontally, shader does the rest, done.
Mouths speak. Thatβs not one transition β thatβs a continuous deformation problem. Every phoneme in every language reshapes the lips, jaw, and cheeks differently. And because SAUCE isnβt a static portrait β itβs a 3D character that tilts, turns, and animates β those deformations need to work from every angle.
The good news: we already solved the hard part. The eye pipeline (Gemini β Hunyuan3D β 3D Studio β Blender β Paint.NET) proved the AI-assisted workflow works. Now weβre adapting it for mouths with one critical addition: shapekeys.
The Pipeline: Same Players, New Rules
| Stage | Eye Pipeline | Mouth Pipeline |
|---|---|---|
| 1. Concept | Gemini redraws eye concept | Gemini redraws mouth expression |
| 2. 3D Gen | Hunyuan3D β base mesh | Hunyuan3D β base mesh |
| 3. Retopo | 3D Studio β clean quads | 3D Studio β clean quads + lip loops |
| 4. Assembly | Blender β UV fix, integrate | Blender β shapekeys, UV fix, integrate |
| 5. Texture | Paint.NET β atlas export | Paint.NET β expression atlas |
The only new stage is shapekey creation β everything else is the same pipeline with mouth-specific conventions.
The Trait Inventory: 15 Mouths, One Base
From the collection tree (devlog1), we have 15 mouth traits to support:
| Trait | Rarity | Type | Notes |
|---|---|---|---|
| Bored | #20 | Flat UV | Neutral, slightly open |
| Buck Teeth | #20 | Flat UV | Protruding upper incisors |
| Cat Mouth | #20 | Flat UV | Small, pursed |
| Clown Smile | #20 | Flat UV | Wide, painted aesthetic |
| Frown | #20 | Flat UV | Downturned corners |
| Grin | #20 | Flat UV | Teeth showing, friendly |
| Lisp | #20 | Flat UV | Tongue-forward |
| Meh | #20 | Flat UV | Flat line, dead inside |
| Open | #20 | Flat UV | Mid-open, surprised |
| Smile | #20 | Flat UV | Classic upturned |
| Smirk | #20 | Flat UV | Asymmetric, one side up |
| Tongue Out | #20 | Flat UV | Playful, non-speech |
| Toothless | #20 | Flat UV | Gums visible |
| Vampire | #20 | Flat UV | Fang reveal |
| Wide Open | #20 | Flat UV | Scream/sing pose |
All 15 are currently flat UV textures. The goal: each becomes a 3D mouth with the same shapekey set, so any SAUCE head can speak regardless of which mouth trait is equipped.
The Base Mesh: Mouth-Specific Topology
The SAUCE mouth base mesh follows rules learned from the eye radial topology:
- Concentric lip loops: 3 edge loops minimum (outer lip, mid-lip, inner lip)
- Radial corner fans: Edge flow radiates from mouth corners for natural creasing
- Jaw adjacency: Lower lip loops connect to chin geometry, not floating
- Quad purity: No triangles in the deform zone β quads deform predictably
- Symmetry plane: Mirror across X, break only for asymmetric traits (Smirk)
Target stats:
- Mouth mesh: ~120β180 tris
- Lip deformation zone: ~40 vertices
- Full head with mouth: consistent with existing SAUCE base
UV Shapekey Standards: The Core Spec
This is the heart of the document. Every mouth trait β flat or 3D β needs these shapekeys to support speech animation.
Shapekey Naming Convention
Mouth_<Category>_<Name>
Examples:
Mouth_Phoneme_AAβ wide open βahβ soundMouth_State_Closedβ rest/neutralMouth_State_Wideβ grin width (non-speech)Mouth_Emotion_Frownβ sad downturn
Required Shapekey Set (16 Total)
1. Rest State (1 shapekey)
| Name | Description | Vertices Affected |
|---|---|---|
Mouth_State_Closed |
Lips together, neutral expression | All mouth verts |
2. Viseme Shapekeys (11 shapekeys)
Based on the standard OVRLipSync viseme set (industry standard for VR/chat avatars):
| Name | Phoneme Mapping | Mouth Shape |
|---|---|---|
Mouth_Viseme_sil |
Silence / closed | Lips fully closed, rest pose |
Mouth_Viseme_AA |
A, a, ah | Jaw dropped, mouth wide open |
Mouth_Viseme_E |
E, e, eh | Teeth showing, corners pulled back |
Mouth_Viseme_I |
I, i, ee | Wide horizontal, teeth closed |
Mouth_Viseme_O |
O, o, oh | Lips rounded, protruded |
Mouth_Viseme_U |
U, u, oo | Lips pursed, small circle |
Mouth_Viseme_PP |
B, P, M | Lips pressed together (plosive) |
Mouth_Viseme_FF |
F, V | Lower lip tucked under upper teeth |
Mouth_Viseme_TH |
Th, th | Tongue between teeth (if visible) |
Mouth_Viseme_DD |
D, T, N, L | Tongue up, slight teeth part |
Mouth_Viseme_CH |
Ch, J, Sh | Teeth nearly closed, slight smile |
3. Emotional/Expression Shapekeys (4 shapekeys)
| Name | Description | Use Case |
|---|---|---|
Mouth_Emotion_Smile |
Corners up, teeth showing | Happy states |
Mouth_Emotion_Frown |
Corners down, brow involvement | Sad/angry states |
Mouth_Emotion_Surprise |
Jaw drop + rounded lips | Shock states |
Mouth_Emotion_Pursed |
Lips pressed tight | Disapproval, thinking |
Shapekey Value Rules
- Range: 0.0 to 1.0 (Blender standard)
- Default rest: All shapekeys at 0.0, base mesh =
Mouth_State_Closed - Combinability: Visemes are mutually exclusive β only one viseme active at a time
- Emotion overlay: Emotional shapekeys CAN combine with visemes (e.g., smiling while saying βohβ)
- Combination method: Additive blending β
final = base + (viseme * weight) + (emotion * weight) - Max total weight: Clamp at 1.5 to prevent over-deformation

UV Atlas Layout: Expression States
For flat-texture mouth traits (the 15 existing variants), the UV atlas follows the eye pattern but with more columns:
+--------+--------+--------+--------+
| Closed | Open | Wide | Pursed |
+--------+--------+--------+--------+
| Smile | Frown | Ooh | Aah |
+--------+--------+--------+--------+
Atlas spec:
- Dimensions: 1024Γ512 minimum (4Γ2 grid of 256Γ256 expression tiles)
- Grid: 4 columns Γ 2 rows = 8 expression states per trait
- States per tile: Closed, Open (surprise), Wide (grin), Pursed, Smile, Frown, Ooh (rounded), Aah (wide)
- Shader logic: UV offset driven by animation state, same as eye blink
- Alpha channel: Teeth and inner mouth masked for layering over face texture
For 3D mouth traits (future mechanical/expression variants), the atlas becomes a single diffuse + normal + roughness β the shapekeys handle all deformation.
Lip-Sync Compatibility: The Translation Layer
SAUCE needs to talk. Whether itβs a user voice chat, pre-recorded audio, or AI TTS, the mouth must sync. Hereβs the compatibility matrix:
OVRLipSync (Meta / VRChat standard)
| OVRLipSync Viseme | SAUCE Shapekey |
|---|---|
| sil | Mouth_Viseme_sil |
| AA | Mouth_Viseme_AA |
| E | Mouth_Viseme_E |
| ih | Mouth_Viseme_I |
| oh | Mouth_Viseme_O |
| ou | Mouth_Viseme_U |
OVRLipSync outputs 6 visemes + laughter/blink. Our 11-shapekey set is a superset β we map 6-to-11 and fill gaps with nearest-neighbor.
Rhubarb Lip-Sync (offline, free)
Rhubarb outputs 9 mouth shapes (A, B, C, D, E, F, G, H, X). Map:
- A β
Mouth_Viseme_AA - B β
Mouth_Viseme_PP - C β
Mouth_Viseme_E - D β
Mouth_Viseme_TH - E β
Mouth_Viseme_O - F β
Mouth_Viseme_U - G β
Mouth_Viseme_FF - H β
Mouth_Viseme_I - X β
Mouth_State_Closed
Custom JSON Animation Format
For web-based SAUCE implementations (three.js and friends):
{
"track": "mouth_viseme",
"keyframes": [
{"time": 0.0, "value": "sil"},
{"time": 0.12, "value": "AA"},
{"time": 0.28, "value": "PP"},
{"time": 0.45, "value": "sil"}
]
}
The runtime maps string viseme IDs to shapekey indices. 16 shapekeys = index 0β15.
Blender Implementation: Shapekey Creation Workflow
For the artist (me, in Blender at 2 AM):
- Duplicate base mesh β create shapekey from mix
- Enter edit mode on the new shapekey
- Deform only lip vertices β jaw vertices follow if jaw is separate mesh
- Use proportional editing (O key) with smooth falloff for natural deformation
- Test in object mode β slider from 0 to 1, check silhouette from front and side
- Name strictly β
Mouth_Viseme_AA, notah_mouthorwide_open - Set slider range β 0 to 1, never negative
- Pin for preview β pin the shapekey at 1.0 to sculpt the next variant
Proportional Editing Settings
| Shapekey Type | Prop. Edit Falloff | Radius |
|---|---|---|
| Viseme (open) | Smooth | Medium |
| Viseme (closed) | Sharp | Small |
| Emotion (smile) | Root | Large |
| Emotion (frown) | Linear | Medium |
Paint.NET: The Expression Atlas
For flat-texture mouth traits, Paint.NET stays the texture source. The workflow:
- Base mouth shape β neutral closed, lips together
- Duplicate layer β one per expression state
- Transform each layer β warp lips to match shapekey target
- Export grid β 4Γ2 tiles, 1024Γ512 total
- Name convention:
mouth_<traitname>_<YYYY-MM-DD>_<HHMM>.webp
Critical: Each tile must align pixel-perfect with the UV shell. One pixel offset = lip seam in engine. Zoom to 800%, use grid snap, check alignment against UV reference overlay.

Integration: From Blender to SAUCE
The export pipeline:
- Blender β Shapekeys baked, base mesh frozen
- Export format: GLB (glTF 2.0) with morph targets
- Morph target naming: Preserved from shapekey names
- Engine import: Three.js family β
mesh.morphTargetInfluences - Runtime animation: AnimationMixer or custom driver updates influence array
Three.js Morph Target Example
// Access morph targets by name
const mouthMesh = scene.getObjectByName('mouth')
const morphDict = mouthMesh.morphTargetDictionary
// Set viseme influence (0.0 to 1.0)
mouthMesh.morphTargetInfluences[morphDict['Mouth_Viseme_AA']] = 0.85
// Blend with emotion
mouthMesh.morphTargetInfluences[morphDict['Mouth_Emotion_Smile']] = 0.3
Vertex Count Budget
- Each shapekey = full vertex position array for deformable verts
- 120 mouth verts Γ 16 shapekeys = 1,920 extra vertex positions
- In GLB: stored as morph target accessors (~23KB uncompressed)
- Acceptable overhead for the expressiveness gain
Quality Gates: Definition of Done
Before a mouth trait graduates from βin progressβ to βcollection readyβ:
- All 16 shapekeys created and named correctly
- No vertex pinching at 1.0 influence (check from 45Β° angle)
- Viseme set produces readable lip-sync on test audio
- Texture atlas exported (flat traits) or material assigned (3D traits)
- Weight painted to head rig (if using bones + shapekeys)
- Exported to GLB and reimported cleanly
- Tested in a live web build with
morphTargetInfluencesdriver - Screenshots: front view, 3/4 view, profile, all shapekeys at 1.0
The Mechanical Mouth Future
Just like Ekubo and Kanoβs bionic eyes, some mouth traits deserve 3D geometry:
- Vampire β fangs protrude in
Mouth_Viseme_PP - Buck Teeth β incisors extend in
Mouth_Viseme_AA - Clown Smile β painted grin widens asymmetrically
- Tongue Out β tongue mesh with independent bone
These follow the same shapekey spec but add geometry-specific deformation. The jaw opens, the fangs track with it, the tongue extends on its own bone layer.
Summary: The Spec At a Glance
| Element | Standard |
|---|---|
| Base mesh tris | 120β180 |
| Lip loops | 3 minimum |
| Shapekey count | 16 (1 rest + 11 visemes + 4 emotions) |
| Shapekey range | 0.0 β 1.0 |
| Viseme standard | OVRLipSync compatible |
| Atlas format | 1024Γ512, 4Γ2 grid, 8 states |
| Export format | GLB with morph targets |
| Runtime | Three.js morphTargetInfluences |
Next
This document is the spec. The next task is the execution: take one trait (probably Smile β simplest geometry, most recognizable) and run it through the full pipeline with shapekeys. If Smile works, the other 14 are variations on the same rig.
The mouth is where SAUCE stops being a picture and starts being a person. Letβs make it count. π«
Days until June 30 deadline: 32 | Pipeline: locked | Shapekeys: specified | Status: ready to sculpt
