Performance: Essential Must-Knows: Difference between revisions
Nbohr1more (talk | contribs) |
Nbohr1more (talk | contribs) |
||
Line 67: | Line 67: | ||
The console command com_showFps 1 allows you to see the framerate at any part of your map, so that you have an idea of how changes you make affect the FPS in a given area. | The console command com_showFps 1 allows you to see the framerate at any part of your map, so that you have an idea of how changes you make affect the FPS in a given area. | ||
===Triangle Counts=== | ===Triangle Counts=== | ||
Line 73: | Line 72: | ||
[http://www.modwiki.net/wiki/CVars_%28Doom_3%29 Modwiki Cvars] | [http://www.modwiki.net/wiki/CVars_%28Doom_3%29 Modwiki Cvars] | ||
===Light Counts=== | ===Light Counts=== | ||
Line 86: | Line 84: | ||
r_showOverDraw ... 1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw | r_showOverDraw ... 1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw | ||
[http://www.modwiki.net/wiki/CVars_%28Doom_3%29 Modwiki Cvars] | [http://www.modwiki.net/wiki/CVars_%28Doom_3%29 Modwiki Cvars] |
Revision as of 03:19, 5 April 2011
written by Fidcal
This article relates to performance issues for mappers. For performance information for players, see Performance Tweaks
All mappers should know the following but remember not to blindly follow every rule but consider the balance between performance and presentation on a case by case basis. Don't spoil a beautiful view or an interesting interaction to gain efficiency unless it is worth the trade.
Build Airtight. Seal out the Void. Avoid Leaks
Building Airtight
Probably the first thing to learn when building a map (mission) with the Doom3 software engine is that you are building in a void and your map must be airtight, sealed against the void, much like a spaceship. Nothing to do with air of course but with the way the software renders your map. These are the rules:
- Your map must not have any gaps in its outer walls leading to the void. The tiniest hairline, near invisible gap caused by two angled lines that are not grid snapped can be enough to cause a leak.
- The origin coordinates of any entity must not be in, or exposed to, the void. Keep in mind that it is possible for the origin of an entity to be outside its visible shape. Such an entity may appear to be inside while its origin is outside in the void. And of course no entity must form part of the outer wall so if you convert a beam or group of brushes to func_static for instance, they must not form part of the outer wall.
- Some materials (textures) such as nodraw do not seal against the void. Such textures must not be used on the surfaces of any brush open to the void.
- There is a rare type of leak caused if the worldspawn entity has the 'angle' property - just delete that property.
The above rules also apply between areas within your map separated by Visportals to reduce what needs to be rendered at any one time. So one area can leak to another area within the outer walls of your map. This is like internal bleeding - there may be no visible symptom but the patient is not functioning very well! With an external leak you will get an error when compiling your map with dmap and the compilation will abort. But with an internal leak no error is reported and the map will compile if it is otherwise OK. The map will work but performance will be reduced because the software will waste effort rendering areas that are not needed. So, there should be no gaps in the separating walls; no entity must form part or all of the separating walls; textures like nodraw should not be used on those walls.
How to detect and fix leaks
Note there is more on fixing leaks at Leaking maps
External Leaks to the Void
If your map leaks to the void then you will get a 'Leaked' error in the console while trying to dmap and the compilation will abort and generate a 'pointfile' with a filename prefix the same as your map and the suffix .lin instead of .map in the same folder as your map. In Dark Radiant you can use this to track the path of the leak, determine the cause, and fix it. Use the File menu option 'Pointfile' and a red line is drawn along the path of the leak. You can use Ctrl+Shift+L to move the camera along the line towards the leak to the void (useful to spot an actual leak) and Ctrl+Shift+K to move towards the entity at the other end (useful if an entities origin is outside in the void.) With the above rules in mind you will be looking for gaps, entities making up part of the outer walls or else an entities origin outside the walls in the void. If you think you have found and fixed the problem but get the error again check carefully as it might be a different leak or you missed the first one.
Internal Leaks
Internal leaks between visportalled areas do not cause a formal error or stop map compilation but they will affect performance and sound propagation. No pointfile is generated so how can you detect them or even know they have occurred? You might realize you have such a leak two ways:
- If you have a visportal that remains open when you would expect it to be closed or unprocessed yet it seems to be set up correctly (see Visportals.)
- You hear sounds from another area as if they were coming directly through walls.
To detect internal leaks you need to deliberately create a temporary external leak and ensure the earliest entity open to the leak is in the area you want to test in your map. The only sure way to do this every time is to use the very first entity in your map. This is often info_player_start or your first light so it might not be convenient to move it from where you actually want it in the game to where you want to test for a leak so it might be a good idea to create an unused entity just for the purpose of detecting leaks when you first start your map. Just a brush with nodraw assigned to a func_static entity and give it a distinctive name like LeakTester so you can find it whenever needed. If you have already started your map you can add a new entity and make it into the first. Close Dark Radiant, and move the entity up just above the original first entity but you need to make sure you copy and paste it correctly. Look at the end of the map in a plain text editor and the entity should begin with a comment eg, //entity 99. Cut and paste including that comment down to the end of the map if you just added it. Paste back in just above the original // entity 1 (not entity 0 which is worldspawn) then save the map with a new name just in case of error so you can go back to the original. When you next save from Dark Radiant the new entity will be renumbered to // entity 1 but you need not wait for that as dmap will treat it as the first entity and refer to it as entity #1.
To test an internal visportalled area that has no external walls to the void....
- Deliberately make a leak in the outer wall (to the void) of your map where the area is located by just peeling back a brush a few units.
- Drag your first entity inside the area to be tested.
- Visportals seal the area internally when closed in game but they will not do this during dmap compilation so they must be temporarily changed. ALL surfaces of the visportal brush should be changed. Don't use nodraw or any texture that will not seal but use stone or wood or maybe something very distinctive unused elsewhere in the map then you can use Dark Radiant's replace textures to restore nodraw after then you need only add the visportal texture manually. If you have visportals inside entity doors then you need to move those doors away temporarily. Much better - don't put visportals inside doors! The visportal surface only needs to contact part of one surface of a door to make it work (see Visportals) in which case you don't need to move them away.
- Save the map with a new name so the original is kept as a backup (always play safe)
- Run dmap in the console. I usually do a 'clear' command first too to clear the console so there is less clutter.
- When the 'leak' error appears use the Page up key to scroll up and you should see it refer to the entity relevant to the leak. Make sure it is your first entity if that is what you are testing as described here.
- Back in Dark Radiant, select Pointfile from the file menu then Shift+Ctrl+K repeatedly to move the camera along the red line from the leak to the entity or just look. If the entity is outside of the internal area being tested then it is not your first entity and confirms that your area is sealed correctly. If however, it is your #1 entity then you have a leak in your inner area. NOTE: It sometimes happens that the first entity is referred to in the console leak error message but the pointfile leads to a different entity nearby. The pointfile is just a list of coordinates along the leak path and its final coordinate is the origin of this other entity. Presumably the pointfile is created differently. I wouldn't worry so long as the console message gave the first entity. Especially if the pointfile entity is within the inner area you are testing anyway.
- If there is a leak from the internal area then use Shift+Ctrl+K and Shift+Ctrl+L to move the camera along the red line. You need to follow the bends to see where the leak is in the walls to the test area. No need to go all the way out to the external leak you created deliberately - you know about that - how is it leaking from within the inner area to next area? Remember the above 'rules' and you need to be looking for gaps or if any part of the wall is an entity.
- If you can fix it then redo the dmap to see if there is any other leak. Only stop when the only leak leads to an entity in the outer area from your gap to the void. That means your inner area is sealed.
- Job nearly done. Close up your gap. Remember to retexture your visportals! Save and test again and now there should be no leaks.
Render-Sectioning using Visportals
If visportals are not used then the entire map will be rendered at once wherever the player is - greatly reducing performance to the point where most maps are not likely to be playable at all. It is crucial that the map should be compartmentalized using visportals. Study the Visportals tutorial for details.
Useful Cvars
Frames Per Second
The console command com_showFps 1 allows you to see the framerate at any part of your map, so that you have an idea of how changes you make affect the FPS in a given area.
Triangle Counts
r_showTris ... enables wireframe rendering of the world, 1 = only draw visible ones, 2 = draw all front facing, 3 = draw all
Light Counts
r_showLightCount ... 1 = colors surfaces based on light count, 2 = also count everything through walls, 3 = also print overdraw
Overdraw
(Shows how much is drawn that the viewer never sees. Good for scenes with lots of alpha-test materials or post-processing.)
r_showOverDraw ... 1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw
Caulk
Read Caulk about when to use the texture common > caulk to remove faces from the rendering process.
Collision Model Removal on some func_static Entities
For models that neither the player nor any AI nor any object can reach or interact with then some memory can be saved by setting the property:
noclipmodel 1
All moving game elements would then pass through the model so only normally use on inaccessible model features.
func_static v worldspawn Brushes
By converting worldspawn brushes to func_static...
- You can add the property noshadows = 1 so that it doesn't cast shadows, improving frame rates.
- It avoids creation of millions of polys in certain situations where the engine converts a brush into loads.
- It reduces pathfinding complexity (see Preventing and Reducing Pathfinding Complexity in Select Locations in Pathfinding)
But be careful to use r_showtris = 3 in the console to check the results. It sometimes happens that large func_statics get processed through visportals. For example, an L-shaped room with the ceiling criss-crossing with beams all converted to one giant func_static and all within the portal area sealed by the door. Yet outside one could clearly see all their tris. By splitting the beams into two groups, one in each 'leg' of the L so making two separate func_statics, they were effectively as good and no longer showed outside. So don't be tempted eg, to convert all trim throughout a house into one giant func_static.
Texture Batching
Another thing that can be done with Func_Static is to batch repeated textures together. If your scene has lots of the same texture on decorative features or geometry that is not split by too many visportals then it may improve rendering speed to combine all the geometry in the scene that has the same texture (or a large percentage of the same texture) into a single Func_Static. One specific but common scenario is a scene that has lots of decal patches with the same texture. These can be combined into Func_Static's to reduce draw calls. Lunaran's "Strombine" map for Quake 4 used this method and improved performance to the point that his map was rendering "as fast as if it had a third of the polygons in the worst corners".
(Note: Quake 4 has a built-in r_showBatchSize command that can be used to diagnose batching performance in detail.)
Patches, Fixed Tesselation
Setting patches to fixed tesselation instead of automatic can significantly decrease the number of polygons.
AI Performance Options
Pathfinding Complexity Reduction
see Preventing and Reducing Pathfinding Complexity in Select Locations in Pathfinding
Interleaved Thinking
see Interleaved Thinking optimization
Neverdormant 0
Adding "neverdormant" "0" to an AI will cause it to suspend all activity when not in view. Use sparingly.
Lighting Performance Options
Lighting overlaps
Generally be cautious about the light from more than one source falling into the same geometry triangle. This overlapping lighting makes the rendering calculations more complex and reduces game performance resulting in slowdown. The console command r_showtris 2 shows what is currently rendered (as triangular wireframes) so you can check any suspect areas. Often you can add trim and other detail to split up large triangles to reduce this.
Virtual Ambient Light
Dark Mod provides a virtual main ambient light to help performance on low end systems. See Virtual_Darkness#Virtual_Ambient_Light
AmbientLight Keyword
Other than the ambient_world (see entry above) you may use ambient lights to add subtle lighting variation to areas. They do not produce normals or specular so it is recommended that you do not use these as primary light sources but instead for faked radiance. Ambient lighting has much less performance impact than other light methods. Another way to think of decorative ambient light placement is "anti-grime decals".
( For an advanced use of ambient lighting see Light Textures and Falloff Images )
Shadow Casting Removal
Where appropriate, remove shadows from lights, entity brushes, and models by settings the property noshadows = 1 (see func_static v worldspawn Brushes)
Brushwork Shadowmesh
Just as you can create a simple shadow-casting mesh for a detailed model to save on performance, you can also set a complex entity brush noshadows = 1 then build a simpler entity brush with shadowed nodraw brushes (texture common caulk shadow and shadow2 ) inside it. Discussion
Moving Lights vs. Static Lights
Moving lights have a considerable performance impact. Be sure to use this effect sparingly.
No Dynamic Interactions
This is a last resort optimization.
If you are sure that no dynamic lighting will hit a surface and that neither the player nor AI can use a lantern\torch or activate a light of any kind near a surface, then you may set the property "noDynamicInteractions = 1".
The lighting, shaders, specular, etc will be baked-into the affected entity or brush. No light will affect the appearance; it will always have the same appearance no matter what. This can be used for distant "decorative" geometry or scenarios where a large amount of terrain is being traversed by a player with a vehicle with multiple dynamic lights (see the Monorail map in Doom 3 for an example).
shadowopt : use it with dmap
CAUTION! THIS FEATURE CAUSED PATHFINDING ERRORS IN ONE MAP
For better performance, when you compile your map with dmap use...
dmap shadowopt 2 <mapname>
You can also try values 0 to 5 but at the time of writing 2 is considered likely the best.
This page also refers : http://www.modwiki.net/wiki/Dmap_(console_command)
Other References
This is a useful article on optimising... http://www.modwiki.net/wiki/Optimising_maps
Optimizing maps thread: Optimizing Maps