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); } }