100 humanoids on the screen, 3500 tri each.

Started by
5 comments, last by simonjacoby 15 years, 3 months ago
I'm looking to get about 100 humanoids on the screen with no dynamic lod system for animated .x characters. Each Humanoid - 3500 triangles My question is how many pieces can make up a humanoid before you take a severe performance hit? Hair.x (Skinned & able to animate) Head.x (Skinned & able to animate) Upperbody.x (Skinned & able to animate) Lowerbody.x (Skinned & able to animate) If each humanoid was made up of 4 pieces with say 2-3 static attachments would that be ok?
Advertisement
depends on algorithms you use to skin and draw them
The best way to find out is to try it on the target platform.

What shader model do you have on the target platform?
Feel free to 'rate me down', especially when I prove you wrong, because it will make you feel better for a second....
This all havely depends on the platform and api you are using. Also, remember then if you are going to render shadows using shadowmapping for example, you need to render all pieces one extra time per frame. This also holds for water reflection etc.

So there is no simple answer to this question then just trying it.

Dietger
In my opinion, use of Geometry Shader to calculate the vertices plus abit of hardware instancing. The geometry shader should solve the problem of requiring to calculate the vertices for multiple draw. You might use instancing to batch thoes that are of the same time.

Perhaps another way you can do is to probably merge models that are of close timings into a single batch and consider the average timing. The human eye is probably unable to detect the difference in a mesh at T=4.3s and T=4.35.
I'm guessing that with that many variations for each character, you're gonna be draw-call limited on any recent hardware, regardless if your platform is a recent console or any fairly recent PC GPU, so anything that you can do to get that as low as possible is probably a good idea. I'm also guessing that the problem here is that each character could be unique (sounds like your trying to do some sort of RPG where the characters can all have different gear or something like that).

If you target DX10, you're probably best of using geometry instancing like littlekid suggested. There's an example on nvidias developer page (http://developer.download.nvidia.com/SDK/10.5/direct3d/samples.html) called skinned instancing, where they have a crowd of 10000 dwarves all separately animated. You could probably get some ideas by checking it out.

If you don't have DX10-hardware as baseline (which you probably don't), and you're just looking for pure performance, you may want to consider sacrificing memory by pre-instancing all or some of your geometry. The most extreme example would be for each character:

3500 verts * 100 objects * 32 bytes/vert gives you around 10MB of vertex data which is pretty manageable. You will also have to use some sort of texture-atlasing technique to be able to draw it all in one draw-call. Assuming a 512x512 texture + mips in DXT1 format for each character, that'll cost you about 170k * 100 = 17 MB. So all in all about 27MB (probably a few megs more for your index-buffers). If you want higher-resolution textures, 1024's for all characters is gonna cost you about 70MB. You'll need some sort of texture management to handle this gracefully, because textures is what will kill this approach.

If you bunch them together one character at the time you can draw them with one draw-call, which would give you 100 draw-calls for 100 characters, including their gear. You could probably put several (or all) of your vertex/index data in big buffers, and draw ranges of that buffer. If you're lucky (depending on how the characters are placed, and how you decide to cull them) you can even draw several characters in a single draw call (also depending on how many bones you have and how many shader constants you use for each character). This way you can have less than 100 draw-calls for 100 unique characters on pre-DX10 hw.

The nice thing with this approach is that it will work for any GPU capable of skinning in vertex shaders (even DX8-class GPU's), and it's fast.

The bad thing is that it eats lots of memory and requires you to code a robust instancing (and texture atlasing) system.

This is of course an extreme example and you're probably better off memory-wise by using some sort of variation of this, for example not instancing the entire character + gear but perhaps just instancing the gear and draw upper and lower body separate for each character.

Using different resolution textures depending on how close the characters are to the camera could probably work also. You could use low resolution for the characters furthest away from the camera, and only use high resolution (1024) for the ones closest to the camera. This would of course require you to update them as the characters move around, which could become a problem.

Just my 2 cents :)

/Simon



This topic is closed to new replies.

Advertisement