• entries
    743
  • comments
    1924
  • views
    580406

Skinning shader

Sign in to follow this  

68 views

I've now got the mesh skinning working on the GPU via a shader.


matrix world;
matrix view;
matrix viewproj;

matrix matrixarray[20];

vector lightdir=vector(-1,1,-1,0);

struct VS_INPUT
{
vector position : POSITION;
vector normal : NORMAL;
float2 texcoord : TEXCOORD;
float2 bone : BLENDINDICES;
float2 weight : BLENDWEIGHT;
};

struct VS_OUTPUT
{
vector position : POSITION;
vector diffuse : COLOR;
float2 texcoord : TEXCOORD;
};

VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output=(VS_OUTPUT)0;

vector pos=(vector)0;
float3 norm=(float3)0;

pos+=mul(input.position,matrixarray[input.bone[0]])*input.weight[0];
pos+=mul(input.position,matrixarray[input.bone[1]])*input.weight[1];

norm+=mul(input.normal,(float3x3)matrixarray[input.bone[0]])*input.weight[0];
norm+=mul(input.normal,(float3x3)matrixarray[input.bone[1]])*input.weight[1];

input.normal=vector(norm.x,norm.y,norm.z,0);
input.normal=normalize(input.normal);

output.position=mul(pos,world);
output.position=mul(output.position,viewproj);

output.texcoord=input.texcoord;

vector light=mul(lightdir,view);
input.normal=mul(input.normal,view);

float s=dot(light,input.normal);
if(s<0.3f) s=0.3f;

output.diffuse=vector(s,s,s,1);

return output;
}



I drew some inspiration from ScootA's post in this thread when I was struggling to get the normals transformed correctly.

Obviously the lighting model is very simple but that is really not the point of this exercise.

So really now, it is time to move on to starting to keyframe animate. From some reading I get the impression that I'll have to shift from using XYZ rotations to quaternions, which scares me a bit.

[LATER]

Got an interpolated animation between two keyframes working on a simple basis. Was really easy actually. I didn't need to worry about quaternions at all for my purposes - I just do a linear interpolation between each pair of x, y and z components of the two rotations.

Weirdly, I think I'm over the worst now on this project. I have to decide how to structure animations and how to chose which two frames to interpolate between, and how much, based on an animation with more than two keyframes that are inequal time distances apart, but that is not really learning new skills, just pondering lots.

From there, smoothly going from one animation to another is just an extension of interpolating between two frames.

And for playing multiple animations on different parts of the model at a time, I think all I need to do is give each bone in each animation a high and low priority - high being play me on this bone, low being play me on this bone only if no other animation is being played.

[LATER]

Got the next step working okay - I can now load an array of keyframes from a file with each frame having irregular time intervals and interpolate the correct position based on a time value.

The frame times are listed in the file between 0 and 1, but the file also contains a duration value which is how long the animation takes to run from start to finish. When you feed a time delta into the Animation class's Step() method, it works out the correct normalised time value then poses the skeleton.

To make an animation cyclic, you just add the first frame to the end and give it a time value of 1. This could be easily done by the loader if a flag was specified or something.

---------------------------

So basically this is all the proof of concept stuff done. I can export a mesh including a skeleton from Milkshape, load it with my own code, compute a matrix palette based on the bone orientations and use a vertex shader to render the model in the correct pose.

I can keyframe at irregular intervals and interpolate between the correct keyframes based on a time value, and the duration of the animation is independant of the animation data so animation speeds can be easily changed.

So the next step is to start working on animation exporters for Milkshape that I can load into my test app.

[LATER]

That's all done. I can define an animation in Milkshape then export it to a file, load the file into the demo application and apply it to the model. And the same animation could be applied to a different model as long as it had the same skeleton structure.

I've added a position transformation to each frame as well as a rotation, so the current animation can bounce the model up and down slightly as he runs. I don't think I'm going to bother with scaling but movement as well as rotation is handy.

Must go to sleep now, but plan for tomorrow night is to make an AnimationController class that can smoothly interpolate between one animation and another over a fixed time duration. Shouldn't be too much hassle since it is really just the same as interpolating between frames in the same animation.

Very happy with today's progress.
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now