XNA Light Pre-Pass: Skinned Meshes

Skinned animation is one of the most common animation techniques today (if not the most), so I couldn’t have left it out of this series. You can find more about it here. The main idea behind it is to store a skeleton (where the number of bones is far lower than number of vertices) and a mesh where every vertex/normal/tangent/etc is associated to one or more bones (usually less than four). When the skeleton animates (using pre-computed key frames and forward kinematics, or using procedural animation like ragdolls, inverse kinematics, or even Kinect), those vertices “follow” theirs bones and so you have your full mesh animated.

This feature is easily integrated in my current LPP renderer: the only extra information we need is the bone matrixes array. I based the importer/processor heavily on the XNA Skinned Model Sample, even the animated model is the “Dude” you can find on that sample. The full source code + assets is here, use it at your own risk!

I changed mainly two things on the importer:

  1. The key frames and the mesh can be scaled, so you can use the scale property in the importer options;
  2. Remember my ubbershader approach described some posts ago? For skinned meshes, I add the define “SKINNED_MESH” (LightPrePassProcessor.cs). This way, in compile time the shader decides what to do with this special mesh type

The main shader now handles that define using a different vertex format and a special algorithm to compute the skinned vertex using the bone matrixes + vertex information, like this:

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    float3 Normal : NORMAL0;
   float3 Binormal  : BINORMAL0;
   float3 Tangent  : TANGENT;
#ifdef SKINNED_MESH
    float4 BoneIndices : BLENDINDICES0;
    float4 BoneWeights : BLENDWEIGHT0;
#endif
};
#ifdef SKINNED_MESH
// Blend between the weighted bone matrices.
    float4x4 skinTransform = 0;
    skinTransform += Bones[input.BoneIndices.x] * input.BoneWeights.x;
    skinTransform += Bones[input.BoneIndices.y] * input.BoneWeights.y;
    skinTransform += Bones[input.BoneIndices.z] * input.BoneWeights.z;
    skinTransform += Bones[input.BoneIndices.w] * input.BoneWeights.w;
float4 skinPos = mul(input.Position, skinTransform);

I also added a new class “SkinnedMesh” inherited from “Mesh”, that holds also the bone matrixes and bind it to the effect when needed. I split the data from the animation itself to make it easier to change the animation player at some point (the animation player on XNA sample is very simple, it has no animation blending/transition/etc).

I think that’s all, this sample is really short compared to the last one, the code is very straight forward to understand, I swear.

For the next entry, I’m thinking about transparency, XBox project+optimizations or some post-processing fx. Feel free (and welcome!!) to add suggestions, comments, complaints, fixes, etc.

See ya!

J.Coluna

About jcoluna

Game developer and musician
This entry was posted in XNA and tagged , , , . Bookmark the permalink.

27 Responses to XNA Light Pre-Pass: Skinned Meshes

  1. Feedidy says:

    Amazing, as always.

  2. Tom Looman says:

    Awesome stuff. Thanks for providing the source to your project it really helped me improve my understanding of graphics programming. Looking forward to the next entry in the series🙂

  3. nobley says:

    Really awasome ..🙂
    Your source led me to learn about graphics programming to move forward,
    I think there is missing, namely shadow mapping for point light, when are you going to discuss this ?

  4. Marco says:

    Hi! On my notebook, with a Mobility Radeon HD4650 1 GB ram, game is a little slow, and when I add 40 trees the frame rate dies😦 I created a small for-loop where I test if camera’s frustum intersects the bounding box of every mesh, but XNA intersect method returns always true… So I tried to render no mesh at all and Gpu time is about 16 ms, that it seems to be very high… I hope that these info can be useful for you😉

    You are doing a very nice work, thank you for everything🙂

    Marco

  5. Marco says:

    Another thing that I’ve noticed is that with 0 trees the framerate is good, and gpu time is about 10-11 ms average, but only with 3 trees gpu times goes to 20 ms…

    Bye🙂

  6. Marco says:

    I’m sorry, ignore last reply😉 I was wrong🙂

  7. Matthew says:

    Awesome stuff once again man!
    Alpha blending post via Forward Rendering? is that what your thinking of for you next article?
    Did you have shadowed pointlights in your DBP app?
    Thanks

    • jcoluna says:

      Thanks dude!
      I meant alpha+additive blending but without lighting (just a rendering pass after reconstruct lighting stage).
      In my DBP app I didn’t use point lights. I used a single spot light with shadow + point light in the same position, “faking” the point shadows. I didn’t have too many walls surrounding a single light, so I choose the spot direction according to the level layout.
      I could put the point shadows shader that @Kris Olhovsky wrote that works with this framework, it’s a dual paraboloid shadow map technique.
      See ya!
      -JColuna

      • Matthew says:

        Ok that’s still sounds cool, Nice Kris got it working cool I remember reading that he was implementing a solution and that would be cool to see that implemented.

      • Feedidy says:

        I’d also like to see some additive blending – or some other way to do a particle system.

  8. Marco says:

    For the next post maybe you can talk about water😉

  9. Amer says:

    Do you support all types of light during PrePass?
    I mean spot, directional and point? Because under Directional seams to be written no supported.

    • jcoluna says:

      I currently support Directional, Spot (both with shadows) and Point (no shadows). The comment may be old stuff, because the first sample I released didn’t featured that.

      Thanks!

      -J.Coluna

      ________________________________

  10. Pingback: Define vertices | Totemicmusic

  11. Pingback: Windows Client Developer Roundup 076 for 7/25/2011 - Pete Brown's 10rem.net

  12. José Guerreiro says:

    Hello, your work is absolutely amazing!

    I was wondering if I can use your code for a commercial game I’m working on?

    Thanks for the attention.

    • jcoluna says:

      Yes, you can! Feel free to use it, and if you could, just mention me on the credits😉

      See ya! -J.Coluna

      ________________________________

  13. Marco says:

    When you will post the new entry? :):)

  14. Marco says:

    Hi🙂

    Any news? ;;)

    Good work!

    Bye🙂

  15. Chris says:

    Hey, I really like how you’ve got your skinned mesh pipeline set up. Never thought about doing that with the defines that way. Coming from someone else who’s developing their own deferred/LPP rendering engine, it’s real interesting to see a different approach to designing the architecture for it. I’d be happy to share my code with you, let me know if you’re interested. No shadow mapping yet in mine, though :p

  16. Hi there I am so gratecul I found your weblog, I really found yyou by accident, while I
    was searching on Bing for spmething else, Regardless I am here now and would jut like to say thanks a lot for a remarkable post and a all round thrilling blog (I also love the theme/design),
    I don’t have time to ggo through it all at thee moment but I have saved it and also added your RSS feeds,
    so when I have time I will be back to read a lot more, Please
    do keep up the awesome jo.

  17. Hello, I hope you’re reading this, I have a problem with SkinnedMesh, in override function OnDraw i have NullReferenceException. In your project you have 14 parameters in EffectMaterial, but in my solution I have only 13, the missing one is “Bones” which I need to draw animated models. Did someone had similiar problem? I’ve searched for many hours for solution, but failed to find anything😦

  18. Pingback: c# - XNA EffectMaterial Parameter missing - CSS PHP

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s