Animation and Instancing question

Started by
3 comments, last by kauna 11 years, 1 month ago

Hello, talking about the storage and loading of models and animations, which would be better for a Game Engine:

1 - Have a mesh and a bone for each model, both in the same file, each bone system with 10~15 animations. (so each model has its own animations)

2 - Have alot of meshes and a low number of bones, but the files are separated from each other and the same bone (animations too) can be used for more then one mesh, each bone set can have alot of animations. (notice that in this case, using the same boneset and the same animations will cause a loss of uniqueness).

And now, if I need to show 120~150 models in each frame (animated and skinned by the GPU), 40 of them are the same type, is better:

1 - Use a instancing system for all models in the game, even if I only need 1 model for each type.

2 - Detect wich model need instancing (if they repeat more then one time) and use a diferent render system (other shader programs), use a non-instancing for the other models.

3 - Dont use instancing because the "gain" would be very low for this number of models.

All the "models" talked here are animated models, currently I use the MD5 file with GPU skinning but without instancing, and I would know if there are better ways to do all the process of animating.

If someone know a good tutorial or can put me on the way... I dont know how I could create a interpolated skeleton and use instancing for it, let me explain..:

I can compress all the bone transformations (matrices) for all animation for all frames in a simple texture and send it to the vertex shader, then read for each vertex for each model the repective animation/frame transformation. This is ok, I can use instancing here because I will always send the same data for the same model type, but, when I need to use a interpolate skeleton, should I do this interpolation on vertex shader too? (more loads from the texture could cause some lost of performance).

I would need calculate the interpolated skeleton on the CPU too anyway, because I need it for colision...

Any solutions/ideas?

- Im using directX but I think this applies to other systems

- Flick

Advertisement

Not a Game Design question. Moving elsewhere.

-- Tom Sloper -- sloperama.com

If you support both instancing and non-instancing, you'll have to keep at least two different versions the vertex shaders + possible permutations. I decided some time ago, that all the meshes will be drawed with instancing even if there is only one instance of it. This way I don't have to have several shaders and I don't code for handling special case.

In my opinion, It is finally a question of optimization to handle the special case of "1" instance and maybe it could be put in the category of "premature optimization" or "unnecessary optimization". I don't think that you'll get any performance advantage to handle the special case.

Cheers!

First lets talk about the resources both on disk and as represented in memory by your engine. You have three distinct pieces, polygonal mesh, skeletons (hierarchies of bones), and keyframes (rotations, translation and scales).

I suggest a superset of all possible bones. Thus if you support both bipedal and quadrupedal skeletons, your master bone list is a super set of both skeletons. The keyframe data will simply reference this 0-based bone superset when referencing which bone the keyframe(s) should operate on. This allows a single keyframe animation to work on several different character's skeletons.

It may or may not be possible to share a skeleton across several polygonal meshes. If possible do this as it will cut back on resources on disk. It will definitely be possible to specify multiple different textures per section of each polygonal mesh. This is a cheap and effective form of 3d palette swapping and can increase your assets considerably.

Now when it comes to loading this stuff into memory, we have different concerns than conserving memory. Consider this: It's attractive to think of saving some

memory per actor instance by having similar models share the same skeleton (i.e. every horse shares the horse skeleton, so there is only one copy of the horse skeleton bones and one copy of the horse polygonal mesh and one copy of each unique horse texture). This scheme would require serialized rendering of all horses, as you would need to pose each horses shared set of bones prior to rendering it. Furthermore you would only have one copy of the polygons for the horse mesh and would need to set the correct horse texture prior to rendering the mesh.

Additionally, as you have chosen GPU skinning, you must be sensitive to exceeding the number of constants registers by providing skin partitions that contain too many bones. A skin partition is a sub-section of a polygonal mesh (possibly the whole mesh) that is influenced by a subset of bones or textured with a different texture. Therefore your assets must not have skin partitions with more than 50 to 60 bones per partition (for 256 constant registers VS2.0). If your model's skin partitions are approaching this limit, you are again forced to serialize rendering in order to set each skin partition's bone palette to the constants registers prior to rendering.

I won't hazard any suggestions on how you can remove these obstacles to parallelization, but I think you see the ramifications of this choice, it will define the scalability of your engine to a great degree.

Additionally, as you have chosen GPU skinning, you must be sensitive to exceeding the number of constants registers by providing skin partitions that contain too many bones. A skin partition is a sub-section of a polygonal mesh (possibly the whole mesh) that is influenced by a subset of bones or textured with a different texture. Therefore your assets must not have skin partitions with more than 50 to 60 bones per partition (for 256 constant registers VS2.0). If your model's skin partitions are approaching this limit, you are again forced to serialize rendering in order to set each skin partition's bone palette to the constants registers prior to rendering.

Just to point out that (under D3D10/11) if you use a generic buffer object (as they use in games such as BF3), you may have several megabytes of data at hand and you don't need worry so much about the bone count and constant buffer size. Of course, less bones typically is always a good thing.

Cheers!

This topic is closed to new replies.

Advertisement