• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0

Skeletal Animation Shader for an Assimp Model

5 posts in this topic

Hi guys
I'm having some trouble getting my skeletal animation working. I've imported the model with Assimp, created the bone hierarchy, calculated all the bone transforms, so on and so forth. I've debugged through the code and the bone information *looks* like it's updating as I'd expect. The issue I'm having seems to come from the shader. As soon as I start using the bone information to update the position, the model ceases to display. I'm not sure whether this is because the bone information hasn't been successfully passed to the shader, the multiplications are wrong, or for some other reason (such as the model is now positioned out-of-view of the camera). If required I can post the entire contents of the class so you can see the entire process. Any input would be ace.
Here's the vertex shader code:

    #version 330
    layout (location = 0) in vec3 inPosition;
    layout (location = 1) in vec2 inCoord;
    layout (location = 2) in vec3 inNormal;
    layout (location = 3) in ivec4 BoneIDs;
    layout (location = 4) in vec4 Weights;
    smooth out vec3 vNormal;
    smooth out vec2 vTexCoord;
    smooth out vec3 vWorldPos;
    smooth out vec4 vEyeSpacePos;
    uniform struct Matrices
     mat4 projMatrix;
     mat4 modelMatrix;
     mat4 viewMatrix;                                                                           
     mat4 normalMatrix;
    } matrices;
    const int MAX_BONES = 100;
    uniform mat4 gBones[MAX_BONES];
    void main()
      mat4 BoneTransform = gBones[BoneIDs[0]] * Weights[0];
      BoneTransform     += gBones[BoneIDs[1]] * Weights[1];
      BoneTransform     += gBones[BoneIDs[2]] * Weights[2];
      BoneTransform     += gBones[BoneIDs[3]] * Weights[3];
      mat4 m_MV = matrices.viewMatrix*matrices.modelMatrix;  
      mat4 m_MVP = matrices.projMatrix*matrices.viewMatrix*matrices.modelMatrix;
      vTexCoord = inCoord;
      vec4 m_transPos = BoneTransform * vec4(inPosition, 1.0);
      vEyeSpacePos = m_MV * m_transPos;
      gl_Position = m_MVP * m_transPos;
        vec4 m_normal = BoneTransform * vec4(inNormal, 1.0);
        vNormal      = (matrices.modelMatrix * m_normal).xyz;
        vWorldPos    = (matrices.modelMatrix * m_transPos).xyz;      
Here's the Draw() function as it stands, in which the bone information and uniforms are passed to the shader:

    void Sprite::Draw()
     g_mainSP.SetUniform("matrices.projMatrix", g_projMat);
     g_mainSP.SetUniform("matrices.viewMatrix", g_viewMat);
     g_mainSP.SetModelAndNormalMatrix("matrices.modelMatrix", "matrices.normalMatrix", g_modelMat);
     for (uint i = 0; i < g_transforms.size(); i++) {
     g_mainSP.SetBoneTransform(i, g_transforms[i]);
     g_mainSP.SetUniform("gSampler", 0);
     g_mainSP.SetUniform("vColor", glm::vec4(1, 1, 1, 1));
     g_ambient.SetUniformData(&g_mainSP, "sunLight");
     if (!g_loaded)return;
     for (uint i = 0; i < g_subMeshes.size(); i++) 
     const uint m_matIndex = g_subMeshes[i].materialIndex;
     aiMesh* m_mesh = g_scene->mMeshes[i];
     (void*)(sizeof(uint)* g_subMeshes[i].baseIndex),
  void ShaderProgram::SetBoneTransform(glm::uint p_index, const glm::mat4& p_transform)
     glUniformMatrix4fv(g_boneLoc[p_index], 1, GL_TRUE, glm::value_ptr<GLfloat>(p_transform));

Share this post

Link to post
Share on other sites

I'm not sure whether this is because the bone information hasn't been successfully passed to the shader, the multiplications are wrong, or for some other reason (such as the model is now positioned out-of-view of the camera)


What have you tried to determine those values? Staring at code isn't nearly as effective as looking at actual values. There are two pieces to debugging - the values have to be correct, and the code has to use them correctly.


Also, you're reserving 400 registers for just your bone matrices. Does your shader version/GPU support that? Do you seriously have models with 100 bones?

Edited by Buckeye

Share this post

Link to post
Share on other sites



Thanks for the quick reply. This is the first time I've had to do skeletal animation, so I'm basing most things to do with the bones/animation side of things off the tutorial found here. Using the project included with that tutorial, I can debug both pieces of code at once to determine whether my values (bone location, indices, etc.) conform. Thus far the only difference I've been able to detect has been in the bone matrix transformations passed to glUniformMatrix4fv, but I'd expect that, considering the values are calculated from times and furthermore, the range of the matrix values seems correct.


You're quite right about the model not having 100 bones (it's around 30 I believe), however I'm hoping to use this shader for other models which may have more bones, in order to ensure that animations as a whole are working correctly. Once I'm certain they are, I'll be re-visiting the shader to only reserve the necessary number of bones for the model. Considering the project along with the tutorial works and that my computer has quite a reasonable spec, I don't see why similar code shouldn't work in my project.


Share this post

Link to post
Share on other sites

Considering the project along with the tutorial works and that my computer has quite a reasonable spec, I don't see why similar code shouldn't work in my project.


But it doesn't work. ohmy.png


Skinned mesh animation is one of the most difficult subjects to get working in intermediate programming. If you just guess or assume things should work, it will likely take a long time to get your code running properly. You've asked for help and gotten a suggestion of something to look at which might take 2 minutes, but your response is to dismiss the oberservation, saying it shouldn't be the problem.


First: You have to want to find the problem. If you're program doesn't work properly, you're going to have to do something to the code to get it fixed.


Second: The suggestion wasn't frivolous. GPUs do have limitations. Why wouldn't you check that your shader version is compatible with your hardware?


Third: It might take you 2 minutes to change the buffer size (to, say, 40?), recompile and run the app. It's been over 12 hours that you've had the problem. Why wouldn't you take 2 minutes of that time for a quick test?


That being said, you can try using identity matrices for both the inverse bind pose and animation matrices. That should result in the vertices being rendered in bind pose without any change other than world-view-projection conversion to screen space. That will give you a good indication if the shader is working in that regard.


Share this post

Link to post
Share on other sites

Sorry, at the time of that post I didn't have access to the code. I've just altered the MAX_BONES to 40, but sadly it hasn't made a difference. The shader version used above is the same as the other shaders in the project so I assumed this wasn't the issue. When I get a chance I'm going to try your suggestion and then have another thorough debug of both my project and the tutorial to see if I spot any discrepancies. Thanks for your help so far!


Share this post

Link to post
Share on other sites
I've tried passing the identity matrix for the animation matrix / inverse bind pose doesn't make a difference either, the mesh still isn't rendering (even when passing the identity matrix directly to the shader). This being said, if in the shader itself I set the bone matrix to the identity, the mesh does indeed render in bind pose, so this suggests the bone information isn't being sent to the shader properly, although I can't pinpoint why as the VBO containing the bone information is in the same VAO as the VBO containing the vertex/texture/normal and IBO and the locations are correct.
One additional thing I noticed during my debug comparison is that the result of some matrix multiplications *are* different (as unlike the tutorial I'm using GLM as a maths library), so some issues could be from GLM's row-major vs. OpenGL's column major, but I'll deal with this once I have something displaying!

Share this post

Link to post
Share on other sites

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
Sign in to follow this  
Followers 0