Sign in to follow this  

Rendering lots of little soldiers...500 how to keep speed up?

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm making a strategy game where the terrain will just consist of rolling hills. So the terrain parts are fine, I can optimise that to the max. But drawing lots of 3D skeletal animated soldiers is a bit confusing to me. 500 or so onscreen. For my terrain I'm just grouping the same textured tiles and using one draw command to draw a hole bunch. But with lots of little men, I thought you would have to use matrices to move them around and animate etc, so I would be calling about 500 draw commands in between a bunch of matrix calculations. I believe this may be quite slow?, btw the men are quite tiny, so there isnt much detail per model, basically just body shaped parts, also im thinking of just loading .x files in and then just placing the models together eg arms,legs torsos to make a man and animate him. What are the ways of drawing lots of men and fast? thanks

Share this post


Link to post
Share on other sites
You can group your soldiers into different animation states, e.g. you hav only say 5 different states and assign them to 100 soldiers each. This way you basically just process state transitions and bone setups for only 5 soldiers instead of 500 and then re-use these states by just translating the meshes to their output positions.

IIRC there was an article about that at gamasutra.com, I'm not quite sure, though.

Share this post


Link to post
Share on other sites
I'm working on a similar project (in mine I'm using md2's) I am precalcing all the frames and a bunch of mid-frames as displists then just displaying, that way each soldier can have his own current anim offset (time from start) and still take advantage of pre-calcing. But if you wanted to use segments, you could put the segments in display lists and that would speed stuff up aswell. K.

Share this post


Link to post
Share on other sites
500 animated objects is a lot. Also, with so many soldiers, you are getting into the realm of a particle system. The solution is to do more work on the CPU that will reduce the number of draws. Perhaps doing the transformations on the CPU and filling a vertex buffer with a soldier's pre-transformed vertexes is faster than the overhead of a draw. So for each soldier, apply its world matrix to the vertexes and copy them into a vertex buffer. Then do a single draw to draw all the soldiers.

If the soldiers are small and simple, you could precompute the animations. Then, for each soldier it is just a matter of using the precomputed mesh for the soldier's animation frame. That would save the time of animating all 500 soldiers every frame. You can also reduce the animation overhead by animating the soldiers at a lower frame rate (like 10 fps).

Share this post


Link to post
Share on other sites
how would you draw the animations pictures for billboards? looks hard


I thought maybe create the little soldiers out of a couple of triangles only, eg maybe 6-7 triangles for a leg, 8-10 triangles for the torso etc. Then test each of those triangles against the terrain triangles, so you could have the soldiers been blown to bits and their body parts could realistically bounce across the terrain.

Or would that just be way to slow with 500.

But I like the idea of sticking all the soldiers into a single vb with one draw call.

With premade animations, i want the terrain to have a bit of an effect on the soldiers so say they are walking or crawling up terrain, their guns or arms wouldnt cut through the landscape.
So im not sure about doing the premade animations


edit just realised what i just said is similar to s_p_oneil's idea, but anyway what you think?


[Edited by - johnnyBravo on August 19, 2004 8:05:25 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by johnnyBravo
how would you draw the animations pictures for billboards? looks hard


That's easy enough. You just render the men to the back buffer or some other render target, then copy the pixels into a texture buffer. The technique is called impostoring, and there are a number of articles out there that explain how to do it (a Google search on "impostor" and "billboard" should find them).

It is up to you whether you pre-render a fixed set of billboard textures or render them on the fly. Which you should choose depends on what you're doing and how you want it to look. Also depending on what you're doing, you may not want to use impostors when the camera gets within a certain distance.

EDIT: Oh yeah, you can also render directly to a texture if the card and API both support it. (It seems to be more widely supported in DirectX 9.0 than it is in OpenGL right now.)

Share this post


Link to post
Share on other sites
Quote:
Original post by johnnyBravo
I thought maybe create the little soldiers out of a couple of triangles only, eg maybe 6-7 triangles for a leg, 8-10 triangles for the torso etc. Then test each of those triangles against the terrain triangles, so you could have the soldiers been blown to bits and their body parts could realistically bounce across the terrain.

Or would that just be way to slow with 500.


It's not difficult to switch to a different animation when the little soldiers get blown up. You could either use particles for the flying body parts, or full 3D triangle meshes.

Quote:

With premade animations, i want the terrain to have a bit of an effect on the soldiers so say they are walking or crawling up terrain, their guns or arms wouldnt cut through the landscape.
So im not sure about doing the premade animations


This could be difficult, as you may have too many different pre-generated textures. They are small textures though, so it may not be that bad. You could easily create one large texture (i.e. 256x256 or 512x512), and fit many poses for one soldier inside of it.

Also keep in mind that it is possible to render into a texture one frame and use it for 10 frames, then update it and use it for 10 more frames. When rendering a squad moving together in formation, you may even be able to use one billboard rendered once for all the men in the squad for a few frames. Be careful though. If you use a dynamically-generated texture and don't reuse it often enough, it won't save you any time.

Share this post


Link to post
Share on other sites
I wouldnt use skeletal animation for a RTS. It is just way too much overhead for 500 soldiers, instead by using a model with pre-calculated frames (MD2 like), you can save alot of speed.

I also agree on the drawing them with 1 call advice. Since each unit type will be using the same texture, you can buffer their vertices/normals/uv coordinates into 1 VB and draw them in 1 call.

As for their interaction with the terrain, you could rotate/orient them when they are walking up a hill. This will produce about the same result as orienting each bone for 500 soldiers would. Having each bone doing collission detection against the terrain is pretty expensive and would not really be better in a RTS where they are being viewed from so far away.

Share this post


Link to post
Share on other sites
Ok, I guess I'll have to use premade animations etc.

I was thinking for billboarding idea, you could have one model drawn, then rotate, animate and set the camera on it,'take a picture of it at its current stance' then put that picture onto the billboard. to be drawn.

Then I would have only one model, and 6 vertices per soldier.

What do you think?

Would that be fast, like animating and rotating the single model 500 times and taking little snap shots of it(im not sure how fast the method is, ive got a tutorial somewhere on that) to be placed onto the billboards?

thanks

Share this post


Link to post
Share on other sites
Impostors in your case rely on several hacks :
- treat projection as quasi isometric view + scaling for projection (distance to camera front plane).
- discretized rotations around the vertical axis. For instance 8 or 16 angles.
- discretized animation frames
- eventually blend your bilboards.

Then for instance 1024 steps and 32*32 bilboards in 32 bits RGBA you need :

16*1024*32*32*4 = 2^(4+10+5+5+2) = 2^26 that is 32M of cache.

1024 can be 32 different animations of 32 frames (1 second at 32 FPS). Maybe more than what you need.

Share this post


Link to post
Share on other sites
you could mix models and billboards. if the "man" is far enough away that you wont notice it use a billboard, and as you zoom in switch to using a model. It'd probably take some time to tweak the values and animations to make it look smooth, but i'm sure it'd be possible to get looking okish in no time ;)
its what i'm planning on doing for my rts anyway, if i ever get done with my terrain engine that is.

Share this post


Link to post
Share on other sites
Quote:
Original post by SoDdit
if i ever get done with my terrain engine that is.


lol, im just going to generate my terrain randomly, then maybe later on I will make a map editor :), I gotta learn vertex shaders i believe.

Share this post


Link to post
Share on other sites
atm i generate my terrain randomly, then texture it using a pixel shader (with a perlin noise texture to add some randomness). i need to improve my shader so that it uses the color value to determin the mix of the various terrain features (grass, mud, rock and sand) tho to do this i'll need a vertex shader as well or i'll loose the light shading. plus i need to update the directx part of the code to use the shader as atm only the oGL part does.

Share this post


Link to post
Share on other sites
So with the billboarding idea,

Would it be best to preanimate everything at every animation eg, every walk movement, every shoot movement etc, then times those to the power of like 16 or 32.

The only problem is, that storing textures for this would run possibly into the thousands.

Would this be too much of a drain on the memory?

As the idea of drawing the model at the right animation then taking a picture of that and sending it to the billboard doesn't stop you from drawing 500 men or so to get all the soldier's animations

Share this post


Link to post
Share on other sites
Hi,

If you're going to do this via billboards I recommend download a demo of Total War - medieval or Shogun. The animations they use are extractable but i think you're need to find a utility to do that (check out for mods of the game). Just looking at these will be very instructional and provide a good idea of the amount of animations, textures and memory you'll need.

Check out http://www.totalwar.com/ for download links.

Of course those two games are old tech, the state of the art is going to be Total War: Rome. I think they must still use imposters, but mixed with 3D models and the quality is far better than the old games.

Anyway if you'll looking at just doing 500 entities I'd go with whoever recommended the MD2 format. Its simple to use, with low cpu overhead at the cost of system ram. I've had a good 2-3 hundred md2 models running around at about 60 fps, and thats ina a hgihgly unoptimised engine.

Share this post


Link to post
Share on other sites
Quote:
Original post by noisecrime
I've had a good 2-3 hundred md2 models running around at about 60 fps, and thats ina a hgihgly unoptimised engine.


You wouldn't have a demo of that would you? I'd like to see that very much

Share this post


Link to post
Share on other sites
In my RTS engine, I can have 500 units 'running' arround, I simply do all of the transformations on the CPU, and draw a group of them when my buffer gets to a certain size. It especialy helped me to take advantage of the CPU's (athlon) 3DNow! instructions. SSE, SSE2, and SSE3 would also do this very well. It greatly improved my time.

Im not sure, but with many of the newer graphics cards, it might not be to big of a stretch to do the transformations in the GPU as a vertex shader. This was what I was going to be working on next, but I got sidetracked with some other stuff. I would love to see how well it works implemented.

Dwiel

Share this post


Link to post
Share on other sites
Imposters work great when all the units are facing in the same direction and are doing the same animation like in the picture.

If each of the 500 units are doing a different animation or facing in a different direction, it will be slower because you end up rendering each unit twice.

Share this post


Link to post
Share on other sites
All depends on what class hardware you are targeting. So set/choose a minimum target spec and work from there.

For DX7 class hardware you will be heavy on the cpu no matter what. Either you tranform vertices on the CPU or do one character per draw call(which can only be accomplished by what is stated in the next sentence). This also will up your memory consumption since you'll only be able to accomplish the above efficiently is by having each frame of animation store as post skeletal transformed vertices. If you want to go the CPU route the models need to be lowpoly enough to do the skeletal animation with sufficient speed if not use the technique from the previous sentence.

For DX8 class hardware you are inbetween, less CPU because you'll have enough matrix constants to perform skeletal animation in the GPU, but thats still one draw call per character. Your second option here is to again have the vertices stored for each frame of animation, and then use "one bone skinning" to instanciate N models per draw call.

For DX9a..b hardware same as DX8 except you can do more characters per draw call.

For DX9c you have instancing/vertex stream frequency which can be used to really effectively take advantage of the hardware.

So its all about what hardware you want to support, what code paths you want to implement, load/init time choice of optimal method for system, benchmarking to see whats optimal for your particular case, and of course proper choice of data structures for a particular code path. (i.e. if you choose to transform vertices on cpu, parallel arrays where position data is kept in its own array and each element is aligned on a 16 byte boundry)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Infinisearch
For DX9c you have instancing/vertex stream frequency which can be used to really effectively take advantage of the hardware.


So the intancing/vertex stream frequency is an actual setting for the vertex buffer?

Quote:
Original post by JohnBolton
Imposters work great when all the units are facing in the same direction and are doing the same animation like in the picture.

If each of the 500 units are doing a different animation or facing in a different direction, it will be slower because you end up rendering each unit twice.


Oh yeah, I never considered that, i guess if i gave the men only 16 rotations, and if I had only a few animations,, it should be quite fast.

Share this post


Link to post
Share on other sites
Yeah, you need billboards, that's also how large groups of trees are rendered. Also, with large numbers of simple models, the fastest thing to do is rotate/translate them in software so you can draw them in batches on the same vertex buffers... but rotation is slow. So you should precompute the rotated vertices for all keyframes of all the models, maybe in 5 degree increments or even 15 degrees. In a RTS, things are only rotated around the vertical axis (yaw) so that makes this very feasible.

Share this post


Link to post
Share on other sites
You could try grouping them and then using different levels of detail for each group. The closest ones to the camera could have a fully detailed model, and the furthest ones away could just be little billboarded images.

Share this post


Link to post
Share on other sites
Quote:
Original post by tolleyc
You could try grouping them and then using different levels of detail for each group. The closest ones to the camera could have a fully detailed model, and the furthest ones away could just be little billboarded images.


Ah I just want to draw all the units the same way, I think right now its just too much hassle.

Maybe once the games complete, but I don't think i'd get that much more better looking graphics by doing that.

Share this post


Link to post
Share on other sites

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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