BSP Map Optimization: Difference between revisions
m (→Brushwork) |
|||
Line 44: | Line 44: | ||
* The compile tools divide the map every 1024 units. In practice, you should try to put your major level divisions along these lines, to keep the compile tools from spliting the faces any more than necessary. | * The compile tools divide the map every 1024 units. In practice, you should try to put your major level divisions along these lines, to keep the compile tools from spliting the faces any more than necessary. | ||
* It's advisable to keep your geometry sized in powers of 2. This speeds up compile times, and is BSP friendly. | * It's advisable to keep your geometry sized in powers of 2. This speeds up compile times, and is BSP friendly. | ||
* Keep your geometry a power of 2 whenever possible. Not only does it run better but you will most likely get an increase in framerate. | |||
* Generally speaking, angled brushes are a bad idea in the BSP tree. If you have to have angled brushes, box them in with hint brushes, or make them func_details. This keeps the tree divisions to a minimum. | * Generally speaking, angled brushes are a bad idea in the BSP tree. If you have to have angled brushes, box them in with hint brushes, or make them func_details. This keeps the tree divisions to a minimum. | ||
Revision as of 11:03, 2 March 2006
Introduction
BSP-style game engines require a special set of knowledge, to know how to create levels that will run well in the engine. This article will attempt to explain some of the techniques and methods used to make a level run well in the Source engine.
All computer and video games are limited by how much detail can be rendered to the screen. This is currently one of the primary performance bottlenecks in game design. One of the main jobs of a level designer is to balance artistic detail and gameplay with issues of performance. In Source, we don't have to be as concerned with the low level issues of polygon counts and memory usage, but they are still ever present.
This article will assume the reader knows how to make a map that is free of leaks, and be able to compile it and run it in the game engine. This article is geared toward beginning level designers, but there should be information useful to advanced designers also.
This will cover the theory, practice, and some practical examples of the concepts taught here.
Theory
Basic Considerations
The whole goal of map optimization is to not render anything that isn't necessary. This is accomplished in a BSP engine like Source, through a number of techniques.
BSP Tree
The first technique is using the visibility tree to full advantage. The visibility tree is precalculated in Source during the VIS step of compile. The tree uses the visleafs that were generated during the BSP step of compile to precalculate the PVS of every leaf in the map. The goal in level optimization is to minimize the PVS of each leaf that the player is most likely to be in, to maximize game performance. This is accomplished in practice by using hint brushes to divide leafs, to mimimize the PVS for those leafs.
Level designers should use the BSP tree to their advantage. One does this by designing the map around it, and taking it into consideration at all steps of design. A level designer should also try to build against the BSP tree. BSP levels are immediately recognizeable because of the straight, right angles in them. This can be avoided if a designer knows how. You can't just rotate your hallways 45 degrees, and expect it to work, as BSP engines don't like that. But with careful consideration, this can be accomplished.
A competent designer knows the quirks that BSP imposes upon level design. In Source, the BSP tree is automatically divided every 1024 units. This is used by designing your levels around these divisions. If possible, the designer should place divisions in brushwork along these lines, so they conincide with the breaks in the map.
The next step is to analyze the map, and any brushes that don't significantly block the player's visibility, should be removed from visibility determination by making them detail brushes. Func_detail brushes, or detail brushes, don't divide the BSP tree.
After basic BSP tree optimization, it's a good idea to address portal optimization, and then model optimization.
If you properly optimize your map, your compile times should be significantly shorter than an unoptimized map.
Portals
Portals are areas of space that separate larger areas on either side. Portals are things like doorways, windows, hallways, or any type of entrance and exit. The level design in Half-Life takes full advantage of tunnels, doors, and various other types of portals to separate game-play spaces in the world. This technique is a staple of BSP level design. In Source, portals are less obvious, but just as frequently used. Most of the windows on buildings and doorways in Half-Life 2 have a special type of entity known as an areaportal, that separates the world-space. These areaportals further optimize drawing of the leafs and portals.
Practice
General
In practice, the best method for handling optimization is to plan the map ahead of time. If you lay out the paths in the map, whether single player or multiplayer, it should become fairly apparent where you will run into problems with visibility. With a little experience, you should recognize where more d
Brushwork
Be careful with your brushwork. If you have to rotate or resize brushes, remember to snap them to the grid. Don't vertex edit if you don't have to. The clip tool can accomplish almost any effect you need, and it's a lot safer to work with.
Some things to keep in mind:
- BSP engines love indoor areas. They handle them well because corridors and hallways are easy to determine visibility for. Outdoor areas require a rather different design approach.
- The compile tools divide the map every 1024 units. In practice, you should try to put your major level divisions along these lines, to keep the compile tools from spliting the faces any more than necessary.
- It's advisable to keep your geometry sized in powers of 2. This speeds up compile times, and is BSP friendly.
- Keep your geometry a power of 2 whenever possible. Not only does it run better but you will most likely get an increase in framerate.
- Generally speaking, angled brushes are a bad idea in the BSP tree. If you have to have angled brushes, box them in with hint brushes, or make them func_details. This keeps the tree divisions to a minimum.
Best Practices
Stick to the Grid
It's always a good idea to lay out the map on a large grid setting, like 64. Block in all the major architechture and geometry, and check lines of sight now, so you can easily readjust things before it gets too complex.
While BSP engines like straight, perfect boxes, it's not very aesthetically pleasing, and very quickly becomes boring after all you see is crate after crate. There is a cure to what ails you, though. The trick is to use angled corridors, buildings, and streets to break up the monotony. Keep careful track of how you lay out your angled geometry though, otherwise this could easily backfire on you, and your VIS times will skyrocket. Careful brush manipulation will generally produce beautiful architecture, that you can't tell from the real thing.
Level your Playing Field
In the real world, some city streets are level as a pool table. But most have more curves than your doctor's handwriting. This has to be addressed carefully in a BSP engine. In most of the "pool table" type levels you'll see, there's small level changes, like sidewalks, and dips in alleyways. Now, every level should reflect these small elevation changes; they make or break the reality of the world. But there's some tricks to implementing them. Again, the BSP engine rears it's ugly head. BSP wishes that everything was flat, and didn't add any extra geometry. Actually, this we can do. Simply, make the sidewalks detail brushes, and have nodraw blocks underneath the sidewalks, at the level of the street. This makes everything level with the street, leaving us with a simple, neat level plane at the bottom of the map. This is the best possible scenerio for VIS; it will keep view leaves to a minimum.
Detail Brushes
Func_details are used to limit the visibility calculations during
func_details don't divide the BSP tree, and can't block visibility. Use these for angled brushes, small brushes, and anything that doesn't significantly block the player's view.
- You can put as many brushes as you want in a func_detail. It won't make a difference if you have a group of brushes all as one func_detail, or each as individual func_details.
- If it doesn't contribute to blocking the view somehow, make it a func_detail.
- Anything that's angled, make it a func_detail. BSP hates angled faces. If you can't func_detail it, put a hint brush around it, so it doesn't carve up the tree any more than necessary. That's why you'll see hint brushes in my maps over all angled faces.
Portals
Areas such as buildings and tunnels, that lead from an enclosed space to an open space typically should have areaportals over them. Areaportals act to cull geometry that cannot be seen through them. Because BSP visibility is based upon what the leaf the player is standing in can "see", and not what the player can see, there are inaccuracies that cause things to be drawn that don't need to be. Areaportals help here, by doing their calculations based on what the player can actually see. Areaportals always have to seal the areas they separate. In practice, this means if you have a building with multiple entrances and/or windows, you have to have an areaportal over each in order for them to "seal" the interior of the building from the exterior. Be careful with using areaportals in closed states in multiplayer maps (this includes areaportal_windows). They will close off every players' view, and not just the local player, which is bad news.
- Areaportals have to seal an area to function. If they don't, they'll produce leak errors on compile, and generate a pointfile you can use to find where they aren't sealed.
- Areaportals are more accurate at visibility determination in engine, but they are more costly. Use them wisely.
Hint brushes
Hints are used to divide visleafs.
- If you only need to make one slice with a HINT brush, texture five sides of the brush with SKIP, and the sixth side with HINT.
- Don't use any more HINTs than you have to. The more leafs in the map, the slower it will compile. Although this may sound counter-intuitive to the last statement, proper use of hints can speed up your compile times, as visleafs will have smaller PVS.
- Generally visleafs will stretch to the ceiling of the map, which will let them "see" over your buildings, drawing what's on the other side, whether the player can see it or not. Counteract this by using hint brushes parallel to the ground plane, at the roofline of the building.
Radiosity Optimization
In Half-Life, there wasn't a lot you can do to optimize the radiosity solution. But in Source, we now have a couple of options. We now have control over the lightmap resolution, which will limit the BSP's filesize, and will help cut down video memory usage. Anything that the player won't come near, it's recommended that the light map resolution is reduced to 32 or 64. We can also speed compile times a bit by limiting the distance that lights can cast.
Examples
Exercises
Compile your map with the following options: BSP with the -glview option, and VIS with the -fast option. Turn off Hammer's Auto visgroup for this compile. This should hide all the ents and func_details that don't carve up the BSP tree, since we are only interested in the BSP tree, and that is the only thing that affects visibility.
Load it into glview, and look at how the compile tools carve up the level.
Run the engine and have a look at the leafs in the engine. You are specifically looking for the shapes of the leafs, and how everything triangulates.
Turn these on:
mat_viewleaf 1
mat_wireframe 1
- Note: You can also set
mat_wireframe
to 2 and 3 for different triangle display modes.
If you are paying attention, you should notice how different areas of the level pop in and out of view
Tricks
This is useful for viewing how your map is turned into triangles by the compile tools. Remember, less triangles means faster rendering.
This will let you cycle through wireframe modes by pressing F1.
bind f1 "incrementvar mat_wireframe 0 3 1"
Related Links
- Optimization - This article covers definitions and explains some of the concepts of optimization.
- Wikipedia:Binary_space_partitioning - An explanation of BSP.
- Visibility determination - This explains what the 2nd compile step actually does.
- Controlling Geometry Visibility and Compile Times -
- Visleafs - Visibility Determination Leafs
- PVS - Potentially Viewable Set