{ "name" : "ArmatureSkin", "ubo" : [ "UBOGlobal", "UBOModel", "UBOArmature" ], "uniforms" : [ ] }<\shader> { "name":"u_joints", "type":"mat2x4" }, { "name":"u_jointScale", "type":"vec3" }, { "name":"u_jointCount", "type":"int" } [ { "name":"ArmatureSkin" } ]<\materials> "useBlending":false #version 300 es layout(location=0) in vec4 a_position; layout(location=1) in vec3 a_norm; layout(location=2) in vec2 a_uv; layout(location=8) in vec4 a_boneIndex; layout(location=9) in vec4 a_boneWeight; uniform UBOGlobal{ mat4 projViewMatrix; vec3 cameraPos; float globalTime; vec2 screenSize; float deltaTime; }; uniform UBOModel{ mat4 modelMatrix; mat3 normalMatrix; }; uniform UBOArmature{ mat2x4[90] bones; vec3[90] scale; int boneCount; } Arm; //uniform int u_jointCount; //uniform mat2x4[3] u_joints; //uniform vec3[3] u_jointScale; vec3 dqBoneTransform(vec3 vpos,int iJointCnt, mat2x4[60] aryJoint, vec4 jointIdx, vec4 jointWeight){ /* NORMALIZE DATA First */ float t = 0.0; if(iJointCnt == 2) t = 1.0 / (jointWeight.x + jointWeight.y); else if(iJointCnt == 3) t = 1.0 / (jointWeight.x + jointWeight.y + jointWeight.z); else if(iJointCnt == 4) t = 1.0 / (jointWeight.x + jointWeight.y + jointWeight.z + jointWeight.w); mat2x4 dqSum; for(int i=0; i < iJointCnt; i++){ dqSum += aryJoint[ int(jointIdx[i]) ] * jointWeight[i] * t; } /*RAW DATA - May Not be Normalized mat2x4 dqSum; for(int i=0; i < iJointCnt; i++){ dqSum += aryJoint[ int(jointIdx[i]) ] * jointWeight[i]; } */ //vec3 v = a_position.xyz; vec4 Qr = dqSum[0].xyzw; //real (rot) vec4 Qd = dqSum[1].xyzw; //dual (trans) vec3 pos = vpos + cross(2.0 * Qr.xyz, cross(Qr.xyz, vpos) + Qr.w * vpos); //Rotate Vector vec3 tran = 2.0 * (Qr.w * Qd.xyz - Qd.w * Qr.xyz + cross(Qr.xyz, Qd.xyz)); //Pull out Translation from DQ return pos + tran; } vec3 dqVecTransform(mat2x4 dq, vec3 v){ vec4 Qr = dq[0].xyzw; //real (rot) vec4 Qd = dq[1].xyzw; //dual (trans) vec3 pos = v + cross(2.0 * Qr.xyz, cross(Qr.xyz, v) + Qr.w * v); //Rotate Vector vec3 tran = 2.0 * (Qr.w * Qd.xyz - Qd.w * Qr.xyz + cross(Qr.xyz, Qd.xyz)); //Pull out Translation from DQ return pos + tran; } vec3 dqBoneTransform_2(vec3 pos, mat2x4[70] bDQ, vec4 bIndex, vec4 bWeight, vec3[70] bScale){ /* NORMALIZE DATA First */ int a = int( bIndex.x ), b = int( bIndex.y ); float t = 1.0 / (bWeight.x + bWeight.y); bWeight.xy *= t; /* APPLY WEIGHTS */ mat2x4 dqSum = bDQ[ a ] * bWeight.x + bDQ[ b ] * bWeight.y; vec3 wScale = bScale[ a ] * bWeight.x + bScale[ b ] * bWeight.y; /* SCALE, ROTATE - TRANSLATE */ return dqVecTransform(dqSum, pos * wScale); } vec3 dqBoneTransform_4(vec3 pos, mat2x4[90] bDQ, vec4 bIndex, vec4 bWeight, vec3[90] bScale){ /* NORMALIZE DATA FIRST */ int a = int( bIndex.x ), b = int( bIndex.y ), c = int( bIndex.z ), d = int( bIndex.w ); bWeight *= 1.0 / (bWeight.x + bWeight.y + bWeight.z + bWeight.w); // 1 Div, 4 Mul, instead of 4 Div. /* APPLY WEIGHTS */ mat2x4 dqSum = bDQ[ a ] * bWeight.x + bDQ[ b ] * bWeight.y + bDQ[ c ] * bWeight.z + bDQ[ d ] * bWeight.w; dqSum *= 1.0 / length( dqSum[0] ); // Normalize DQ by the length of the Quaternion vec3 wScale = bScale[ a ] * bWeight.x + bScale[ b ] * bWeight.y + bScale[ c ] * bWeight.z + bScale[ d ] * bWeight.w; /* SCALE, ROTATE - TRANSLATE */ return dqVecTransform(dqSum, pos * wScale); } void main(void){ gl_PointSize = 5.0; //int tmp = u_jointCount + 1; //vec3 pos = boneScale(a_position.xyz, u_jointCount, u_jointScale, a_jointIdx, a_jointWeight); //pos = dqBoneTransform(a_position.xyz, u_jointCount, u_joints, a_jointIdx, a_jointWeight); //vec3 pos = dqBoneTransform(a_position.xyz, u_jointCount, u_joints, a_jointIdx, a_jointWeight); //vec3 pos = dqBoneTransform(a_position.xyz, Arm.count, Arm.joints, a_jointIdx, a_jointWeight); //vec3 pos = dqBoneTransform_2(a_position.xyz, Arm.bones, a_boneIndex, a_boneWeight, Arm.scale); vec3 pos = dqBoneTransform_4(a_position.xyz, Arm.bones, a_boneIndex, a_boneWeight, Arm.scale); gl_Position = projViewMatrix * vec4(pos, 1.0); // modelMatrix * //gl_Position = projViewMatrix * modelMatrix * vec4(a_position.xyz, 1.0); } <\vertex> #version 300 es precision mediump float; out vec4 oFragColor; void main(void){ oFragColor = vec4(0.0, 0.0, 0.0, 1.0); } <\fragment>