Reputation: 1198
I am currently working on animating an model using joint's and vertex weight's. My question isn't program specific but GLSL based. In my shader I have the following info loaded
uniform mat4 projection,camera,model;
in vec3 vertex;
struct Joint
{
mat4 invBind;
mat4 global;
};
uniform Joint transforms[16];
in ivec4 jointIndices;
in vec4 weights;
Here Joint in an structure that is used to transform an vertex. It has 2 types of info
invBind:- this matrix is the inverse of an joint's local bind transform in global/model space which is used to transform the model from model space to local joint space
global:- this matrix is used to transform an vertex from an joint's local space to it's final global/model[or world] space
global=parent_global_joint_transform*joint_local_bind_transform. I have loaded my model from blender .dae file and so "joint_local_bind_transform" is transposed and then used
in ivec4 jointIndices:- is the list of all possible joint's that affect this vertex
in vec4 weights:- is the weight associated with the corresponding joint affecting this vertex
I have an array of size 16 of these joint's because there are that many joint's in my model
So with all this information how do we calculate gl_Position?. Is there more information that need's to be loaded as uniforms or as vertex attributes?. Sorry for my noobish question but many tutorial's don't give an straight forward answer.
An simple vertex shader code answer would be nice. Thank You
Upvotes: 0
Views: 784
Reputation: 32587
Without any guarantee of correctness, something like the following should work for simple linear blend skinning. If it is not working directly, you should be able to understand what is going on and adapt accordingly:
//make a 4D vector from the vertex' position
vec4 position = vec4(vertex, 1.0);
//accumulate the final position
vec4 p = vec4(0, 0, 0, 0);
for(int i = 0; i < 4; ++i)
{
Joint joint = transforms[jointIndices[i]];
p += weights[i] * joint.global * joint.invBind * position;
}
gl_Position = p;
In the loop, you iterate all influencing bones. For every bone, you calculate the vertex' position in the bone's coordinate system and transform it back to the global coordinate system according to the bone's orientation in the current frame. Finally, you just blend the result for all influencing bones.
To reduce the amount of data you are transferring to the GPU, you can also precalculate joint.global * joint.invBind
.
Upvotes: 1