Reducing draw calls / increasing performance
by Aleksander Elvemo · in Torque 3D Professional · 03/12/2010 (7:55 am) · 34 replies
Hi!
I have some questions wich are puzzling me. I've tried to search and got many answers, but some the questions remains unanswered.
In my game I try to push in as many ai-characters as possible (strategygame). So without any form for AI-functions running/thinking, I have just run my tests with 90 simple boxed shaped humanoids. Each of these has a polycount of 120. Every humanoid also has a simple 1024x1024 basic texture, which is almost a singlecolor.
Now, I have made a function which spawns 90 of these in a mission which is the standard blank emptyRoom.mis that loads when you press F11 when you're not currently in a mission.
Readings from the emptyRoom without any models:
FPS: 160
Draw Calls: 25
PolyCount: <5000
After adding 90 models with 120 poly, that should be total 10800 polys give the readings;
FPS: 35
Draw Calls: <4000
PolyCount: 50 000
Now some things are a bit wierd I feel here. First of all, the low box humanoid is a LOD version of a higher poly model, but I'm hundred percent sure that the 90 models on screen indeed is that low poly version, and the number itself, 120, comes from the shape editor which I found by selecting that particular LOD version.
Should I be expecting: <5000 (level itself) + 10800 polys, or should it actually be around 50 000? I was expecting a 1/5 of the values im getting. Also I read a comment that draw calls never should go above 2-3000, and im at 4000+! Are there any clues to why the performance is so bad?
To validate my results I will confirm at once that I have tested in fullscreen mode, with the camera standing completely still, only using a single command for spawning 90 models, and using the function metrics(fps) and metrics(gfx).
Hope anyone could enlighten me! Thanks for any replies in advance :)
EDIT:
I found out the model does not use one texture, but 3 at 512x512
Also, could mesh hiding be a part of the problem? Atm the models are hiding about 10 meshes (boxes mostly)
The whole model is also 11 seperate meshes, so that every part can be mesh hided, can this be the reason performance falls?
I have some questions wich are puzzling me. I've tried to search and got many answers, but some the questions remains unanswered.
In my game I try to push in as many ai-characters as possible (strategygame). So without any form for AI-functions running/thinking, I have just run my tests with 90 simple boxed shaped humanoids. Each of these has a polycount of 120. Every humanoid also has a simple 1024x1024 basic texture, which is almost a singlecolor.
Now, I have made a function which spawns 90 of these in a mission which is the standard blank emptyRoom.mis that loads when you press F11 when you're not currently in a mission.
Readings from the emptyRoom without any models:
FPS: 160
Draw Calls: 25
PolyCount: <5000
After adding 90 models with 120 poly, that should be total 10800 polys give the readings;
FPS: 35
Draw Calls: <4000
PolyCount: 50 000
Now some things are a bit wierd I feel here. First of all, the low box humanoid is a LOD version of a higher poly model, but I'm hundred percent sure that the 90 models on screen indeed is that low poly version, and the number itself, 120, comes from the shape editor which I found by selecting that particular LOD version.
Should I be expecting: <5000 (level itself) + 10800 polys, or should it actually be around 50 000? I was expecting a 1/5 of the values im getting. Also I read a comment that draw calls never should go above 2-3000, and im at 4000+! Are there any clues to why the performance is so bad?
To validate my results I will confirm at once that I have tested in fullscreen mode, with the camera standing completely still, only using a single command for spawning 90 models, and using the function metrics(fps) and metrics(gfx).
Hope anyone could enlighten me! Thanks for any replies in advance :)
EDIT:
I found out the model does not use one texture, but 3 at 512x512
Also, could mesh hiding be a part of the problem? Atm the models are hiding about 10 meshes (boxes mostly)
The whole model is also 11 seperate meshes, so that every part can be mesh hided, can this be the reason performance falls?
#2
FPS: 500+
Draw Calls: 5
PolyCount: 1600
with models:
FPS: 65+
Draw calls: 600+
PolyCount: 12 000 +
This looks very promising! Draw calls dropped like a stone, and the polycount where much more like I expected!
The question I'm left with is;
How should I proceed with getting better shadow performance?
03/12/2010 (9:08 am)
W basic lightning:FPS: 500+
Draw Calls: 5
PolyCount: 1600
with models:
FPS: 65+
Draw calls: 600+
PolyCount: 12 000 +
This looks very promising! Draw calls dropped like a stone, and the polycount where much more like I expected!
The question I'm left with is;
How should I proceed with getting better shadow performance?
#3
Hope that helps
Spence
03/12/2010 (9:12 am)
I'm not totally sure but when you have multiple textures for a single model the engine draws the model once for each texture. This is what's causing the high draw call number. I can't explain the high poly count though.Hope that helps
Spence
#4
Thanks for the tips everyone! :)
03/12/2010 (9:18 am)
I shall try to merge the textures together and post the results!Thanks for the tips everyone! :)
#5
I saved some 1500 drawcalls per 25 AI by mergin several textures into 1.
Everytime a model has more than a single texture it has to be drawn again - decreasing performance. If you can put all of those 3 x512's into one texture, it should save quite a bit on drawcalls, and won't signifcantly increase total texture memory.
More mesh objects decrease performance (as opposed to a single mesh) but having them hidden shouldn't affect performance.
LOD models "aggressively". You can lose tonnes of polys at distance - if it looks like a stick figure at distance then make it a stick figure as a model, and also cut out extra nodes/bones at distance. Make sure your final LOD only has a single texture if the others have more.
Also remember dynamic shadowing can devour performance - especially the more objects which cast shadows, and distance can be tweaked as can shadow size and quality. The more shadows, the more re-drawing, the more polys, the more drawcalls.
And of course what sort of system and GPU you have will give different results.
Here's a little demo of my most complex scene with a lot of lights (GTS250):
High quality shadows:
50=fps 2300=drawcalls 700k+=polys
No shadows (Advanced Lighting):
120=fps 621=drawcalls 130k+=polys
Basic Lighting:
170=fps 322=drawcalls 50k+=polys
So in a complex scene, you can see just how much shadows from multiple lights cast over many objects eat up performance.
edit: lol, it took me ages to write that ... :)
03/12/2010 (9:23 am)
Apparently Crysis drawcalls were (mostly) kept under 2000.I saved some 1500 drawcalls per 25 AI by mergin several textures into 1.
Everytime a model has more than a single texture it has to be drawn again - decreasing performance. If you can put all of those 3 x512's into one texture, it should save quite a bit on drawcalls, and won't signifcantly increase total texture memory.
More mesh objects decrease performance (as opposed to a single mesh) but having them hidden shouldn't affect performance.
LOD models "aggressively". You can lose tonnes of polys at distance - if it looks like a stick figure at distance then make it a stick figure as a model, and also cut out extra nodes/bones at distance. Make sure your final LOD only has a single texture if the others have more.
Also remember dynamic shadowing can devour performance - especially the more objects which cast shadows, and distance can be tweaked as can shadow size and quality. The more shadows, the more re-drawing, the more polys, the more drawcalls.
And of course what sort of system and GPU you have will give different results.
Here's a little demo of my most complex scene with a lot of lights (GTS250):
High quality shadows:
50=fps 2300=drawcalls 700k+=polys
No shadows (Advanced Lighting):
120=fps 621=drawcalls 130k+=polys
Basic Lighting:
170=fps 322=drawcalls 50k+=polys
So in a complex scene, you can see just how much shadows from multiple lights cast over many objects eat up performance.
edit: lol, it took me ages to write that ... :)
#6
Wow! Tons of info, thanks!
One thing that puzzles me is where does the Basic and Advance Lighting differ? I mean, does the rise in polys come from the shadows?
Also, should: texture number/number of meshes/LOD affect draw calls differently in basic and advance lighting? Since the tests are run with exactly the same models/mission is it reasonable to assume that its basicly the lighting/shadows' fault that the performance drops?
Or is multiple textures/multiple meshes/LOD's more important in advanced lighting than in basic lighting?
03/12/2010 (9:36 am)
@Steve:Wow! Tons of info, thanks!
One thing that puzzles me is where does the Basic and Advance Lighting differ? I mean, does the rise in polys come from the shadows?
Also, should: texture number/number of meshes/LOD affect draw calls differently in basic and advance lighting? Since the tests are run with exactly the same models/mission is it reasonable to assume that its basicly the lighting/shadows' fault that the performance drops?
Or is multiple textures/multiple meshes/LOD's more important in advanced lighting than in basic lighting?
#7
You can have fps, polys, drawcalls and shadow polys/draws with:
metrics("FPS GFX SHADOW");
Advanced lighting also has things like spec and normal map textures to take into account whilst Basic doesn't, hence Basic's super low drawcall.
LODs are very important, less stuff to render, less stuff to repeatedly render. If you've 7 textures with normals and specular, then that's a whole lot of re-rendering before shadows even start so try and keep texture numbers down. Also try to keep texture sizes down (it is a tradeoff here). 4x512s take up as much texture memory as 1x1024, but have to be drawn 4 times.
Apparently "skinned meshes" (AI/players) are more expensive than anything else too.
03/12/2010 (9:53 am)
I think shadows have to be drawn by drawing the polys again = hence more polys. You can have fps, polys, drawcalls and shadow polys/draws with:
metrics("FPS GFX SHADOW");
Advanced lighting also has things like spec and normal map textures to take into account whilst Basic doesn't, hence Basic's super low drawcall.
LODs are very important, less stuff to render, less stuff to repeatedly render. If you've 7 textures with normals and specular, then that's a whole lot of re-rendering before shadows even start so try and keep texture numbers down. Also try to keep texture sizes down (it is a tradeoff here). 4x512s take up as much texture memory as 1x1024, but have to be drawn 4 times.
Apparently "skinned meshes" (AI/players) are more expensive than anything else too.
#8
How do multiple meshes per character affect drawcalls? We have a lot of meshes right now, to make it possible to cut off limbs in melee combat. (Which, needless to say, is awesome!) Will they affect draw calls in the same way multiple textures do, even if they share texture(s)?
03/12/2010 (10:00 am)
Good to know. I guess I'll have to merge some textures then. How do multiple meshes per character affect drawcalls? We have a lot of meshes right now, to make it possible to cut off limbs in melee combat. (Which, needless to say, is awesome!) Will they affect draw calls in the same way multiple textures do, even if they share texture(s)?
#9
The directional shadows (used by the Sun and ScatterSky) use PSSM ("Parallel Split Shadow Map"). If you have four splits, there are four renders for each split. Shadow casters are likely to be rendered an extra 3 or 4 times due to this.
The best solution is preventing non-building objects from casting shadows after a certain distance or at certain LODs. The Forest object does this already, but I don't know if there's any editor option for disabling shadows on specific LODs. You could assign a different material to your non-shadow LODs and uncheck the "cast shadows" box in the material editor.
03/12/2010 (10:07 am)
In AL the visible scene has to be rendered twice, at least. Once to fill up the G-buffer, and another time to receive lighting. This is due to the deferred lighting.The directional shadows (used by the Sun and ScatterSky) use PSSM ("Parallel Split Shadow Map"). If you have four splits, there are four renders for each split. Shadow casters are likely to be rendered an extra 3 or 4 times due to this.
The best solution is preventing non-building objects from casting shadows after a certain distance or at certain LODs. The Forest object does this already, but I don't know if there's any editor option for disabling shadows on specific LODs. You could assign a different material to your non-shadow LODs and uncheck the "cast shadows" box in the material editor.
#10
03/12/2010 (10:56 am)
use auto billboarding for anything you can. it will help tremendously.
#11
03/12/2010 (11:29 am)
Another tip I read somewhere was that you should make sure that your objects come in at a scale of "1 1 1" as much as you can. From what I understand, if the scale is higher, it's more costly to the rendering of the shadows than if the scale was normal. I haven't done any metrics on that myself, but there is a thread or two floating around about it.
#12
Now there's something I hadn't thought of.
03/12/2010 (11:58 am)
Quote:
You could assign a different material to your non-shadow LODs and uncheck the "cast shadows" box in the material editor.
Now there's something I hadn't thought of.
#13
My main issue is how to handle different texture combinations (as half the reason as to why the textures were so split up in the first place, is so that players could choose what kind of clothes they want to wear, and so on). Is there any other way of handling this than making one megatexture for each combination of textures?
03/15/2010 (10:09 am)
Worked quite well, actually. Merged all the parts of my LOD-model, merged and scaled down the textures they use, and disabled cast shadows for them. This increased performance by quite a bit. Now to make more detailed model to go in between the proper mesh and the boxman.My main issue is how to handle different texture combinations (as half the reason as to why the textures were so split up in the first place, is so that players could choose what kind of clothes they want to wear, and so on). Is there any other way of handling this than making one megatexture for each combination of textures?
#14
You'll be seeing this feature in a T3D release very soon.
03/23/2010 (12:04 pm)
Some new exciting news... before GDC i got hardware mesh instancing working with materials in Torque 3D. In our scenes in Pacific where we have alot of instanced trees we get a 75% to 50% reduction in draw calls.You'll be seeing this feature in a T3D release very soon.
#15
03/23/2010 (12:22 pm)
Oh, that is just plain awesome :)
#16
... that was more info than you wanted, right?
03/23/2010 (1:11 pm)
I nearly needed to change my pants with that news!... that was more info than you wanted, right?
#17
03/23/2010 (2:27 pm)
Great news thanks Tom !
#18
Speaking of limb damage... Valve's presentation at GDC 2010 seems like a nearly perfect system for any game wanting to do damage to their characters:
Rendering Wounds inLeft 4 Dead 2
03/23/2010 (3:49 pm)
Quote:We have a lot of meshes right now, to make it possible to cut off limbs in melee combat. (Which, needless to say, is awesome!)
Speaking of limb damage... Valve's presentation at GDC 2010 seems like a nearly perfect system for any game wanting to do damage to their characters:
Rendering Wounds inLeft 4 Dead 2
#19
03/31/2010 (12:16 pm)
@Tom Is it too much to ask for that as a standard T3D feature? :p It's ingenious, but seems sort of complex to implement.
#20
This means making your character use a single texture, which has reserved UV areas for each piece of clothing. Example:
04/01/2010 (6:08 am)
@Christian: if you're willing to dive into source, a nice approach to clothing combinations is building an atlas texture when the character is loaded or when changing clothes. It requires a little more strict QA on your models, though.This means making your character use a single texture, which has reserved UV areas for each piece of clothing. Example:
+-------------------------+ | | | | | SHIRT | | | | | SKIN |------------| | | | | | PANTS | | | | +-------------------------+Then all you need is code to assemble the texture based on that character's current clothing settings and replace its material.
Torque 3D Owner Nicolas Buquet
Try the same test in Basic lighting and post the results please.
Nicolas Buquet
www.buquet-net.com/cv/