Simple example

Area of influence 8
-

Vertex Shader :
uniform vec4 uBonesQuatRotation[ BONES ];
uniform vec4 uBonesQuatTranslat[ BONES ];
uniform mat4 uBonesTransformation[ BONES ];
uniform bool linear;

varying vec3 vNormal;
attribute vec2 bones;
attribute vec2 weights;

void main() {
if(bones[0] == 1.0)
    vNormal = vec3(weights[0],0.0,weights[1]);
else if(bones[0] == 3.0)
    vNormal = vec3(weights[1],0.0,weights[0]);
else
    vNormal = vec3(0.0,weights[0],0.0);
    
mat4 mv = projectionMatrix * 
            modelViewMatrix;

if(linear){
    vec4 wPosition = vec4(0.0);
    
    for (int i = 0; i < 2; i++) {
        wPosition += weights[i] * (
                        uBonesTransformation[ int(bones[i]) ] *
                        vec4( position, 1.0));
    }
    gl_Position =  mv * wPosition;
}
else{
    vec4 wRotQuat = vec4(0.0);
    vec4 wTransQuat = vec4(0.0);
    for (int i = 0; i < 2; i++) {
        float w = weights[i];
        if( dot(uBonesQuatRotation[int(bones[i])], wRotQuat) < 0.0 )
            w *= -1.0;
        wRotQuat += uBonesQuatRotation[int(bones[i])] * w;
        wTransQuat += uBonesQuatTranslat[int(bones[i])] * w;
    }

    float xRot = wRotQuat[0];
    float yRot = wRotQuat[1];
    float zRot = wRotQuat[2];
    float wRot = wRotQuat[3];
    
    float length = sqrt(xRot * xRot + yRot * yRot
    + zRot * zRot + wRot * wRot);
    wRotQuat = wRotQuat / length;
    wTransQuat = wTransQuat / length;
    
    float xR = wRotQuat[0];
    float yR = wRotQuat[1];
    float zR = wRotQuat[2];
    float wR = wRotQuat[3];
    float xT = wTransQuat[0];
    float yT = wTransQuat[1];
    float zT = wTransQuat[2];
    float wT = wTransQuat[3];
    
    float t0 = 2.0 * (-wT * xR + xT * wR - yT * zR + zT * yR);
    float t1 = 2.0 * (-wT * yR + xT * zR + yT * wR - zT * xR);
    float t2 = 2.0 * (-wT * zR - xT * yR + yT * xR + zT * wR);
    mat4 weightedJointMatrix = mat4(
        1.0 - (2.0 * yR * yR) - (2.0 * zR * zR),
        (2.0 * xR * yR) + (2.0 * wR * zR),
        (2.0 * xR * zR) - (2.0 * wR * yR),
        0,
        (2.0 * xR * yR) - (2.0 * wR * zR),
        1.0 - (2.0 * xR * xR) - (2.0 * zR * zR),
        (2.0 * yR * zR) + (2.0 * wR * xR),
        0,
        (2.0 * xR * zR) + (2.0 * wR * yR),
        (2.0 * yR * zR) - (2.0 * wR * xR),
        1.0 - (2.0 * xR * xR) - (2.0 * yR * yR),
        0,
        t0,
        t1,
        t2,
        1
        );
    
    gl_Position =  mv * weightedJointMatrix * vec4( position, 1.0);
}
}