Linear Blend Skinning vs Dual Quaternion Skinning in GLSL
Skeletal animation in real-time graphics relies primarily on two vertex skinning algorithms: Linear Blend Skinning (LBS) and Dual Quaternion Skinning (DQS). While LBS blends affine transformation matrices directly, DQS blends dual quaternions to represent combined rotation and translation. This article breaks down the mathematical and practical differences between implementing LBS and DQS calculations within OpenGL Shading Language (GLSL) vertex shaders, examining their performance trade-offs, code structures, and visual artifacts.
Mathematical Representation and Data Structures
In GLSL, the two techniques rely on completely different input structures passed to the vertex shader:
- Linear Blend Skinning: Bone transformations are
passed as an array of 4x4 matrices (
mat4 boneMatrices[]) or encoded in a texture buffer. Each matrix represents the full rotation, scale, and translation for a joint. - Dual Quaternion Skinning: Bone transformations are
passed as pairs of 4D vectors (
vec4) representing the real part (rotation quaternion) and dual part (translation quaternion). A bone is typically represented as a struct containing twovec4values or indexed from an array:vec4 boneDQs[MAX_BONES * 2].
GLSL Calculation: Linear Blend Skinning
LBS calculates the final vertex position via a weighted sum of bone
matrices. The vertex attributes include bone indices
(ivec4) and bone weights (vec4).
// Linear Blend Skinning in GLSL
mat4 skinMatrix =
boneMatrices[boneIndices.x] * boneWeights.x +
boneMatrices[boneIndices.y] * boneWeights.y +
boneMatrices[boneIndices.z] * boneWeights.z +
boneMatrices[boneIndices.w] * boneWeights.w;
vec4 skinnedPosition = skinMatrix * vec4(inPosition, 1.0);
vec3 skinnedNormal = mat3(skinMatrix) * inNormal;Advantages and Disadvantages of LBS
- ALU Cost: Very low. Modern GPUs have dedicated hardware for matrix-vector multiplication.
- Artifacts: LBS suffers from the "candy-wrapper" artifact. Because matrices are linearly interpolated, rotational components do not interpolate along the shortest arc on a sphere. Twisting joints (like wrists or forearms) cause the mesh to collapse and lose volume.
GLSL Calculation: Dual Quaternion Skinning
DQS uses dual quaternion linear blending (DLB). It linearly blends the real and dual parts, normalizes the result to maintain a rigid transformation, and then transforms the position and normal vectors using quaternion algebra.
To prevent antipodal cancellation (where quaternions representing the same rotation cancel each other out), the shader must check the dot product of each quaternion with the base quaternion and flip signs if necessary.
// Dual Quaternion Skinning in GLSL
vec4 real = vec4(0.0);
vec4 dual = vec4(0.0);
vec4 dq0_real = boneDQs[boneIndices.x * 2];
vec4 dq0_dual = boneDQs[boneIndices.x * 2 + 1];
for (int i = 0; i < 4; ++i) {
int idx = boneIndices[i] * 2;
vec4 r = boneDQs[idx];
vec4 d = boneDQs[idx + 1];
// Ensure shortest path interpolation
float weight = boneWeights[i];
if (dot(r, dq0_real) < 0.0) {
weight = -weight;
}
real += r * weight;
dual += d * weight;
}
// Normalize the blended dual quaternion
float len = length(real);
real /= len;
dual /= len;
// Transform position: p' = p + 2 * cross(real.xyz, cross(real.xyz, p) + real.w * p) + 2 * (real.w * dual.xyz - dual.w * real.xyz + cross(real.xyz, dual.xyz))
vec3 t = 2.0 * (real.w * dual.xyz - dual.w * real.xyz + cross(real.xyz, dual.xyz));
vec3 skinnedPosition = inPosition + 2.0 * cross(real.xyz, cross(real.xyz, inPosition) + real.w * inPosition) + t;
// Transform normal (rotates by the real quaternion component only)
vec3 skinnedNormal = inNormal + 2.0 * cross(real.xyz, cross(real.xyz, inNormal) + real.w * inNormal);Advantages and Disadvantages of DQS
- ALU Cost: Higher than LBS. DQS requires dot
products, conditional sign flipping, normalization
(
inversesqrt), and multiple vector cross products to extract the transformed point. - Memory Bandwidth: Lower than LBS. Storing two
vec4types takes 8 floats per bone, compared to 12 to 16 floats for amat4ormat4x3. - Artifacts: DQS completely eliminates the candy-wrapper artifact and preserves volume during extreme joint twists. However, it can produce unnatural "joint-bulging" around sharp bends (like elbows or knees) and does not natively support non-uniform scaling without complex adjustments.
Summary of Differences
| Feature | Linear Blend Skinning (LBS) | Dual Quaternion Skinning (DQS) |
|---|---|---|
| Data Footprint per Bone | 16 floats (mat4) or 12 floats
(mat4x3) |
8 floats (2x vec4) |
| Shader Complexity | Simple matrix-vector arithmetic | Quaternion blending, normalization, cross products |
| GPU ALU Overhead | Low | Moderate |
| Twisting Behavior | Mesh collapses (candy-wrapper effect) | Mesh volume is strictly preserved |
| Bending Behavior | Tends to pinch | Tends to bulge |
| Scaling Support | Handles uniform and non-uniform scaling natively | Requires matrix fallback or specialized scale handling |