Overview
Morph targets (also called blend shapes) allow smooth interpolation between different vertex positions, enabling facial animations, corrective shapes, and other mesh deformations. A MorphTargetBuffer stores multiple target shapes, each containing vertex offsets from the base mesh.Morphing Modes
MorphTargetBuffer operates in a hybrid model:1. Automatic (Built-in Attributes)
For positions and tangents, the buffer holds data internally:- Enable via
withPositions(true)orwithTangents(true) - Upload data with
setPositionsAt()orsetTangentsAt() - Filament automatically applies morphing in the vertex shader
2. Manual (Custom Attributes)
For UVs, colors, or other custom data:- Enable via
enableCustomMorphing(true) - Create and manage a separate
Textureto hold morph data - Bind the texture to your material as a
sampler2DArray - Manually call
morphData2,morphData3, ormorphData4in the vertex shader
Creating a MorphTargetBuffer
Builder Methods
vertexCount
Sets the number of vertices per morph target.count
Sets the number of morph targets.withPositions
Enables automatic position morphing.withTangents
Enables automatic tangent/normal morphing.enableCustomMorphing
Enables manual morphing for custom attributes.morphData2, morphData3, morphData4) but does NOT allocate storage. You must provide a texture with the morph data.
name
Associates a debug name with the buffer.build
Creates the MorphTargetBuffer.Uploading Morph Data
setPositionsAt (float3)
Uploads position offsets for a target.targetIndex- Which morph target (0 to count-1)positions- Array of position offsets (not absolute positions)count- Number of verticesoffset- Starting vertex index in the target
float4 version with w=1.0.
setPositionsAt (float4)
Uploads position offsets with explicit 4th component.setTangentsAt
Uploads tangent offsets for a target.Basic Example
From the hellomorphing sample:Attaching to Renderables
morphing() Methods:
- morphing(MorphTargetBuffer)* - Attaches the buffer to all primitives
- morphing(primitiveIndex, targetCount, offset) - Configures which targets each primitive uses
primitiveIndex- Which primitive (if renderable has multiple)targetCount- How many targets this primitive usesoffset- Starting target index in the buffer
Setting Morph Weights
Control the blend between targets using weights:setMorphWeights
instance- The renderable instanceweights- Array of weight values (0.0 to 1.0 typical, but can exceed)count- Number of weightsoffset- Starting target index
0.0- Target has no effect1.0- Target fully applied- Values can exceed 1.0 for exaggerated effects
- Final vertex position = base + sum(weight[i] * offset[i])
Multiple Primitives Example
When a renderable has multiple primitives sharing morph targets:Query Methods
getVertexCount
Returns the vertex count of the buffer.getCount
Returns the number of morph targets.hasPositions
Returns true if the buffer has position morphing enabled.hasTangents
Returns true if the buffer has tangent morphing enabled.isCustomMorphingEnabled
Returns true if custom morphing is enabled.Custom Morphing (Advanced)
For morphing custom attributes like UVs or vertex colors:1. Enable Custom Morphing
2. Create Texture with Morph Data
3. Bind to Material
4. Use in Vertex Shader
morphData2(sampler2DArray, vertexId)- Returns vec2morphData3(sampler2DArray, vertexId)- Returns vec3morphData4(sampler2DArray, vertexId)- Returns vec4
Performance Tips
- Minimize active targets - Use only necessary morph targets; fewer targets = better performance
- Share buffers - Reuse MorphTargetBuffer across multiple renderables when possible
- Optimize target count - Typical facial animation uses 50-100 targets; consider which are essential
- Use sparse targets - Many vertices can have zero offsets; consider sparse encoding for custom morphing
Cleanup
Related Resources
- RenderableManager - Set up morphing renderables
- VertexBuffer - Define base mesh geometry
- SkinningBuffer - Combine morphing with skeletal animation