Hey, I’ve recently began investigating how would I implement hardware skinning. As of yet I don’t have any experience with shaders so I’ll probably missay some things.
I figure if I have a model with it’s skeleton, I only need to pass a shader the transformations regarding the bones. The shader should then apply the transformations to meshes(vertices) that are “assigned” to each bone. How would I achive that the shader only operates on the vertices that belong to a certain bone?
// additional vertex attributes. max 4 influence
// if vertex have less than 4 influences, then set unused slots to 0.0
attribute vec4 vWeight;
attribute vec4 vBoneIndex;
// max 30 bones. you may increase this number
uniform mat4 bones[30];
varying vec4 col;
// this function calculate skin matrix based on vertex bone indices and weights
// keep in mind that sum of weights must be 1.0f
mat4 BuildSkinMatrix()
{
mat4 result; // not initialised?
int i;
for (i=0; i<4; i++)
{
result = result + (vWeight[i] * bones [int(vBoneIndex[i])]);
}
return result;
}
void main(void)
{
vec4 vtx;
vec4 nrm;
col = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
mat4 skinmatrix = BuildSkinMatrix();
// skin vertex
vtx = skinmatrix * gl_Vertex;
// skin normal
nrm = skinmatrix * vec4(gl_Normal, 0.0);
// if you need to skin tangents and binormals, do it here
// transform skinned normal
nrm = vec4(gl_NormalMatrix * nrm.xyz, 0.0);
// transorm skinned vertex
gl_Position = gl_ModelViewProjectionMatrix * vtx;
}
thanks for the code, one more thing though. If I understood the code correctly, you do the transformations on the vertices with a certain bone(id) attribute. I presume one would have to tell the vertex the id of the bone when loading the model . how would I do that?
Instead of keeping list of vertices for each bone, make list of bones for each vertex. You can do this in loading time or during model export.
Here is a example of vertex structure:
typedef struct tagChVertex
{
float pos[3]; // position
float norm[3]; // normal
float tex0[2]; // mapping coordinate
float col[4]; // vertex color
float weights[4]; // weights[i] is in relation with boneindices[i];
float boneindices[4]; // up to four indices in array of mat4 in vertex shader
float tangent[3]; // tangent
float binormal[3]; / binormal
} tChVertex;