We have a solid skeletal animation system in our engine. It allows to set up to three animations onto each bone and blend them seamlessly. The animation update (fetching animation matrix given current time) and blending (two slerps for the three matrices) is done on the CPU while the actuall skinning (vertex transforms) is done on the GPU. Each vertex in our engine can be affected by up to four bones.
I am now considering moving the aforementioned update and blend functionality onto the GPU. Our CPU is loaded much more than the GPU even though these two operations are already done in parallel. This is how it can be done:
- At compile time, all the animation data for each skeletal model for each timestep is baked into textures.
- The update and blend functionality is done on the GPU in a single Draw() call by instancing quads. One quad is required for each bone on the scene. Each quad will render 16 pixels - the resulting matrix. To compute this matrix, I will need to sample the animation texture from (1) 4*12 = 48 times (to get three animation matrices for the current frame) and perform 2 slerps. I think I will be doing it in the vertex shader.
- At the skinning phase, I will sample the texture, rendered at stage (2) 4*16=64 times to get four matrices for the four bones, that can affect current vertex. It will be a GPU performance hit, but that is the main purpose of this process: to free up CPU cycles.
So my question is, has anyone ever tried this? Is it even worth thinking about? This system will take quite some time to implement and if there is some serious flaw in it, I would like to know about it. From my perspective it sounds good. At the same time I have never heard of anyone using such a system, which alerts me. Everywhere I read, the animation data is passed into the vertex shader as a huge array of matrices, which implies standard CPU update/blend system.
I wonder how games like StarCraft 2 do the update and blending. They have situations when there are tones of skeletal creatures on the screen (200 zerglings is standard, each has 2000 polygons, idk how many bones though...)?
UPDATE: I am working with XNA 4.0 that is DirectX 9, that is 224 uniforms in the shader.