Optimization (Non-Geometry): Difference between revisions
mNo edit summary |
mNo edit summary |
||
Line 1: | Line 1: | ||
This article deals with map optimizations that do not involve manipulation of geometry or the [[BSP]]. For those, see [[Optimization (Geometry)]]. For the main article, see [[Optimization]]. | This article deals with map optimizations that do not involve manipulation of geometry or the [[BSP]]. For those, see [[Optimization (Geometry)]]. For the main article, see [[Optimization]]. | ||
==Physics== | |||
One of the neat things about Source is its use of physics simulation, and physically-simulated objects will certainly have a place in the vast majority of maps. However, simulating several physics objects simultaneously can lead to performance drops, especially in multiplayer. | One of the neat things about Source is its use of physics simulation, and physically-simulated objects will certainly have a place in the vast majority of maps. However, simulating several physics objects simultaneously can lead to performance drops, especially in multiplayer. | ||
Line 13: | Line 13: | ||
If an object does not need to be physically simulated (it's not going to move, or it will move only because it's parented to something else) then it should not be a physics object. In the case of props, convert them to [[prop_dynamic]] or [[prop_dynamic_override]]. In the case of brushes, instead of [[func_physbox]] use a [[func_brush]] (if it moves passively because it's parented to something else) or [[func_movelinear]] (if it's just supposed to move along a straight line) or whatever is appropriate. Most any func_''whatever'' is cheaper than [[func_physbox]]. | If an object does not need to be physically simulated (it's not going to move, or it will move only because it's parented to something else) then it should not be a physics object. In the case of props, convert them to [[prop_dynamic]] or [[prop_dynamic_override]]. In the case of brushes, instead of [[func_physbox]] use a [[func_brush]] (if it moves passively because it's parented to something else) or [[func_movelinear]] (if it's just supposed to move along a straight line) or whatever is appropriate. Most any func_''whatever'' is cheaper than [[func_physbox]]. | ||
==Shaders== | |||
[[Shader]]s are a class of nifty new technology featured in the newer versions of DirectX. They allow some really nice special effects--in Source they have primarily been used to make things either reflective or refractive or both. For example, water in Source is a particularly complex shader, especially "expensive" water. Other examples of the use of shaders include the wavy glass in some doors, lenses such as glasses or the magnifying glass in Dr. Kleiner's lab, and those strange tanks full of transparent goo. | [[Shader]]s are a class of nifty new technology featured in the newer versions of DirectX. They allow some really nice special effects--in Source they have primarily been used to make things either reflective or refractive or both. For example, water in Source is a particularly complex shader, especially "expensive" water. Other examples of the use of shaders include the wavy glass in some doors, lenses such as glasses or the magnifying glass in Dr. Kleiner's lab, and those strange tanks full of transparent goo. | ||
Line 22: | Line 22: | ||
Other than water, if shaders are slowing you down you should either reduce the number of shader-using materials and entities, or rig it so there are fewer per [[PVS]]. | Other than water, if shaders are slowing you down you should either reduce the number of shader-using materials and entities, or rig it so there are fewer per [[PVS]]. | ||
==Client-side/Server-side== | |||
This section applies only to multiplayer mods. Network traffic is expensive, and a mapper for multiplayer mods should keep this in mind when doing anything tricky with, say, physics, logic entities, and chained input/output. The main thing to keep in mind is that your map, while being played, exists in three places: | This section applies only to multiplayer mods. Network traffic is expensive, and a mapper for multiplayer mods should keep this in mind when doing anything tricky with, say, physics, logic entities, and chained input/output. The main thing to keep in mind is that your map, while being played, exists in three places: | ||
* It is being simulated on the server. This is '''server-side''' work. | * It is being simulated on the server. This is '''server-side''' work. | ||
Line 43: | Line 43: | ||
However, the network is there to be used, so don't overdo attempts to optimize in this regard. This topic is mostly informational; see the Physics section for a more practical example of how the network effects maps. If you want to seriously optimize on this point, be sure to discuss it with a coder for the mod in question. | However, the network is there to be used, so don't overdo attempts to optimize in this regard. This topic is mostly informational; see the Physics section for a more practical example of how the network effects maps. If you want to seriously optimize on this point, be sure to discuss it with a coder for the mod in question. | ||
==Dynamic Lights== | |||
The Source engine is not well-suited to drawing dynamic lights. While they can look nice, you should limit their usage if you care about your framerate. As a guideline, you should have no more than one dynamic light per [[PVS]]. | The Source engine is not well-suited to drawing dynamic lights. While they can look nice, you should limit their usage if you care about your framerate. As a guideline, you should have no more than one dynamic light per [[PVS]]. | ||
Revision as of 09:24, 13 September 2005
This article deals with map optimizations that do not involve manipulation of geometry or the BSP. For those, see Optimization (Geometry). For the main article, see Optimization.
Physics
One of the neat things about Source is its use of physics simulation, and physically-simulated objects will certainly have a place in the vast majority of maps. However, simulating several physics objects simultaneously can lead to performance drops, especially in multiplayer.
In singleplayer mods such as HL2, you can safely use a lot of physical simulation in your maps. Check showbudget, the Physics meter, for an indication of whether you're using too much. Keep in mind that physics objects in motion are more expensive than they are when at rest. Additionally, physics constraints cost too.
In multiplayer mods such as HL2DM physics come at even more of a cost, since a lot of data needs to be sent across the network, which in turn causes a slow-down for everyone. As a general rule, use fewer physics objects in multiplayer than you would in singleplayer. You might notice that simulation quality is reduced for multiplayer (for example, a moving platform looks like it's moving smoothly, but if you try to ride it you will discover that it is jerky--especially if it's going upwards); this is to reduce the network traffic and client-side processing (see later section). For physics objects, you have the option of sacrificing more simulation quality for more speed: by using a prop_physics_multiplayer instead of a prop_physics, that object is easier on the network. Some models might have problems with this (sawblades, for example, if I remember correctly) and in this case you might be better off using something that can handle being a prop_physics_multiplayer.
In either multi- or singleplayer, whenever you have multiple physics constraints acting on an object you should assign them all to a constraint system (phys_constraintsystem). This simplifies the engine's work, resulting in both faster and smoother simulation.
If an object does not need to be physically simulated (it's not going to move, or it will move only because it's parented to something else) then it should not be a physics object. In the case of props, convert them to prop_dynamic or prop_dynamic_override. In the case of brushes, instead of func_physbox use a func_brush (if it moves passively because it's parented to something else) or func_movelinear (if it's just supposed to move along a straight line) or whatever is appropriate. Most any func_whatever is cheaper than func_physbox.
Shaders
Shaders are a class of nifty new technology featured in the newer versions of DirectX. They allow some really nice special effects--in Source they have primarily been used to make things either reflective or refractive or both. For example, water in Source is a particularly complex shader, especially "expensive" water. Other examples of the use of shaders include the wavy glass in some doors, lenses such as glasses or the magnifying glass in Dr. Kleiner's lab, and those strange tanks full of transparent goo.
Overuse of shaders can be expensive, though, especially depending on the video card (although Valve has done a lot to try to make shaders cheaper for people who have less-advanced video cards). You can tell when shaders are causing a slow-down in your map by consulting showbudget: the Swap Buffers meter will be to the right.
Water is a special shader, and can be especially problematic when used incorrectly. There are two types of water: "cheap" water and "expensive" water. The cheap water is faster to draw, but the expensive water looks nicer (it reflects, for one thing). If you have water in your map you should use a water_lod_control to control how far away from the viewer the graphics engine is allowed to use cheap water instead of expensive.
Other than water, if shaders are slowing you down you should either reduce the number of shader-using materials and entities, or rig it so there are fewer per PVS.
Client-side/Server-side
This section applies only to multiplayer mods. Network traffic is expensive, and a mapper for multiplayer mods should keep this in mind when doing anything tricky with, say, physics, logic entities, and chained input/output. The main thing to keep in mind is that your map, while being played, exists in three places:
- It is being simulated on the server. This is server-side work.
- It is being simulated on each client (players' computers). For simplicity we consider only one client at a time as an abstract of what's happening for each client. This is client-side work.
- Lots of information is being sent across a network so that the client-side and server-side versions of the world stay the same. This is network traffic.
The network is usually the slowest part of a multiplayer game, and it is very expensive to send information across it (this is most true for modem users, but also for broadband, and to a lesser extent for LANs). Many events that can occur in maps will generate network traffic; it will be to your map's benefit to restrict this as much as possible. One way the Source engine helps is by letting the client-side do things that it can do unsupervised by the server. For example, the client can draw a crate just fine without the server's help, so all drawing of crates is done client-side, instead of having the server draw it and send the picture across the netwotk to the client. Other things must be done on the server, such as keeping track of where bullets are flying. The Source engine and mods decide what things should be done server-side and what others should be done client-side. As a mapper you have no control over this, but should understand that it is true.
How does this help in map optimization? Let's start with an example (this is a real example, as it's something I've done in a map). Suppose we want a red blinker atop a tower in our skybox. It's far away, so we don't actually use a light entity, just a sprite (env_sprite) since that looks fine and doesn't involve the cost of dynamic lighting. Unfortunately, the sprite isn't animated, so we have to make it blink ourselves. The first way that comes to mind is to use a logic_timer to turn toggle the sprite every second. This works fine... but what happens when the timer fires? Does the server have to send a message to the clients to tell them to toggle the sprite? Or is the timer simulated client-side, and no message needs to be sent? I actually don't know (if the timer is named, it's probably server-side; otherwise, perhaps not, but I'm not sure) but I do know a way that's certain to be done purely client-side, without any network traffic: instead of using a logic_timer, just go into the sprite's properties and change it to Slow Strobe. This is a purely visual effect, and can therefore be done on the client side. Did we save any network traffic? Maybe, maybe not, but hopefully the example illustrates how one can be try to prevent problems.
So some guidelines and suggestions:
- Objects without names are less likely to involve network traffic. Don't name objects unless you have reason to.
- If you want a single-use timer rather than a periodic one, don't use logic_timer--use the Delay setting on an Output instead.
- Avoid network-intensive objects (see Physics section above).
- Whenever an Output results in something observable happening (a noise, a spark, a door openning, etc), network traffic will be involved.
- If an entity has no Outputs (besides the OnUser ones), then it is probably purely client-side unless named. See, for example, env_spark. This might not apply if you use the OnUser outputs.
- If an entity has no Outputs or Inputs (except OnUser and FireUser ones) then it is almost certainly purely client-side, as there's no way for the server to send it a useful message. This might not apply if you use OnUser/FireUser.
- Don't use OnUser/FireUser outputs--that's what logic_relay is for. Usually it wouldn't hurt, but in some cases it might try to make something a network object that shouldn't be. (This is not experimentally verified, but logic_relay is better anyway.)
However, the network is there to be used, so don't overdo attempts to optimize in this regard. This topic is mostly informational; see the Physics section for a more practical example of how the network effects maps. If you want to seriously optimize on this point, be sure to discuss it with a coder for the mod in question.
Dynamic Lights
The Source engine is not well-suited to drawing dynamic lights. While they can look nice, you should limit their usage if you care about your framerate. As a guideline, you should have no more than one dynamic light per PVS.
Most lighting in Source is precalculated--that's what the RAD step of compilation does. Lighting is slow, but extremely important towards making a map look nice; therefore the majority of lighting is done ahead of time, during compilation, so that maps can look nice and run fast. The limitation is that lights, being precalculated, aren't allowed to change over time. Dynamic lights are used to get around this limitation: they can flicker, move around, or whatever. But remember that lighting is slow; trying to do lighting calculations in-game is possible, but not cheap. So avoid it whenever you can. If you simply need the effect, use as few dynamic lights as possible.
The most obvious cause of dynamic lights is the light_dynamic entity. But any named light or light_spot is also a dynamic light. Additionally, any point_spotlight with the No Dynamic Light flag unchecked is also a dynamic light.
The easiest way to tell whether dynamic lights are a problem is to use showbudget and examine the Dynamic Light Rendering meter.