RAGBAZRAGBAZ
sections
home pricing
learn
school face lesson game search docs
demos
face demo glither wasm
governance
buyer page formal spec
schoolcomputer vision

Face Mesh Morphing Techniques

Face morphing looks like image blending, but the convincing version is geometry first: stable face points, a shared triangle topology, and texture coordinates that move with the expression.

Face Points

A face mesh begins as landmark points. Each point marks a stable semantic place on the face: a mouth corner, eyelid edge, brow ridge, nose bridge, cheek contour, or jaw point.

Most browser pipelines store those points in normalized image space so the same data works for any render size.

x: 0.0 left  -> 1.0 right
y: 0.0 top   -> 1.0 bottom
z: relative depth

The critical rule is point-index identity. Point 61 in expression A and point 61 in expression B must mean the same anatomical point, or the morph will twist.

From Points To Triangles

A renderer cannot draw a cloud of points as a face surface. It needs triangles, and the same triangle list should be reused for every expression.

Stable topologyTriangle indices stay constant between expressions, keeping eyebrows, lips, and jawlines from reconnecting during animation.
Local motionEach triangle carries nearby texture detail, so a smile can move the mouth without dragging the whole image sheet.

Voronoi And Delaunay Intuition

A Voronoi diagram answers: which landmark owns each patch of nearby image space? Its dual, the Delaunay triangulation, connects landmarks so triangle edges tend to avoid long skinny slivers.

That matters for faces because skinny triangles stretch texture aggressively. Delaunay-style connectivity gives better local neighborhoods for cheeks, lips, and eyes.

Morphing Positions

The simplest morph is linear interpolation. At time t, each vertex is somewhere between expression A and expression B.

P(t) = A + (B - A) * t

When every landmark index is consistent, the whole face appears to change expression. When an index is wrong, a lip vertex may jump into an eyelid or a cheek can fold through the mouth.

Texture Coordinates And Dual UVs

Geometry motion is only half the trick. The shader also needs to sample each source texture at the correct landmark coordinates. The face viewer keeps two UV attributes: one for expression A and one for expression B.

color = mix(textureA(uvA), textureB(uvB), t)

This is why the texture follows the face points instead of sliding over a static rectangle. The destination mouth texture is sampled from the destination mouth coordinates, even while the geometry is halfway through the morph.

Transforms

Normalized image points must be transformed into the coordinate system used by the canvas or Three.js scene. A common mapping centers the face and flips the Y axis so screen coordinates become world coordinates.

world_x = (x - 0.5) * 2
world_y = -(y - 0.5) * 2
world_z = z * depth_scale

Scale, rotation, and translation are then safe to expose as controls because they operate on the mesh after the landmark topology has been built.

Debugging Checklist

  • Draw the points before drawing triangles.
  • Toggle wireframe to inspect topology during the blend.
  • Check the same landmark index on both expressions.
  • Verify UVs against both source images, not just the current geometry.
  • Keep privacy boundaries explicit: this is a morphing demo, not identity verification.

Open the live surface at face.ragbaz.cc, or read the implementation handoff in the Atlas experiment notes.