BSP maps must be completely internally sealed. No part of the interior of the level, the world, should connect with the outside, the void. Even the sky must be sealed off with a brush using the
tools/toolsskybox texture. When there is any kind of gap to the void, a leak is generated when the map is compiled by VBSP. When a leak occurs, VBSP cannot tell which part of the level is inside, and what part is outside, and it will not work properly.
This example shows a map with an obvious gap in the geometry, leading to the void. This will generate a leak error message when it is compiled:
When a map like this is compiled, with a gap to the void, VBSP generates an error similar to this in the compile log:
ProcessBlock_Thread: 0...1...2...3...4...5...6...7...8...9...10 (0) **** leaked **** Entity light (-1607.69 -1094.12 -183.00) leaked!
With this error message, VBSP is telling you that there has been a leak in the level, and the first entity it found when attempting to get into the level from the void (in this case, a light entity). It also gives you the location of that entity, expressed in X, Y, and Z world unit coordinates.
- 1 Effects of leaks
- 2 Wasting time with leaks
- 3 Finding leaks
- 4 Other causes of leaks
- 5 Situations that do not leak
- 6 Conclusion: An ounce of prevention
Effects of leaks
A leak in a level has a number of bad effects. VBSP will report the leak, and it will not correctly produce a portalfile (
mapname.prt), if at all. The portal file is used by VVIS to perform its visibility calculations. Since there is no portal file, VVIS will not run correctly/at all. When this happens, VRAD will also work incorrectly, or only perform direct lighting - no light bounces.
Maps are usually not playable at all. VVIS may tell the engine to render the entire map at once, which is bad for framerates, or have entire areas be invisible. At worst, a leak can make VRAD render your entire map black.
Wasting time with leaks
VBSP will always report any leaks it finds, but spending hours of full compile time and game execution just to find out that your map is broken after compilation, simply isn't efficient. Make sure you've tested that your map doesn't have a leak before you even begin to worry about your map's visibility and lighting. If you notice that VBSP leaked while the compile is happening, press Ctrl+C to abort the compile.
Sometimes these gaps aren't quite as obvious as the above example. They can be a fraction of a unit wide and still cause a leak. VBSP provides you with a pointfile to help you locate the leak. It draws a line from the void of the map to the entity it found during the leak check. After receiving a leak error, a
mapname.lin file will be created in the same directory as your .vmf map file.
Loading a Pointfile
The pointfile can be loaded into the Hammer Editor to show you precisely where the leak is inside the level. To load a pointfile for the level, use the Load Pointfile command in the Map menu.
This image shows the pointfile loaded into the previous example. Notice that the red line appears in both the 3D and 2D views, and is traced back from the entity through the gap.
Using this visual aid, you can find the source of the leak by following the red line to the outside of the level. It's best to start at the entity specified by VBSP, and then follow the line until you find the gap in the geometry. Close the gap and recompile the level to see if you have fixed the leak.
Finding the endpoint
If you're having trouble locating the start entity, you can use the Go to Coordinates command on the View menu to find the entity and the start of the pointfile line. Simply enter the coordinates given by VBSP for the entity location, and the 2D and 3D views will be centered on that location. Follow the line to find your leak.
Another method to find the source of the leak is to zoom out in one or more of the 2D views. After loading the pointfile, zoom out until you see the red line. Follow the line until you reach the entity at the one of the endpoints. Then select the entity, and choose Center 3D Views on Selection from the View menu. Now you can follow the pointfile line to find the leak.
Other causes of leaks
Besides gaps in outside geometry, there are other map errors that can cause VBSP to generate a leak error.
Entities outside the level
All entities need to be inside the playable level space or skybox. VBSP treats all brush entities as if they are not there, so attempting to seal a map with a brush entity, such as a func_door, will create the same condition as if there were a gap in their place.
Improperly constructed areaportals
Leak error messages can also be generated when an areaportal does not properly seal the two areas it connects. Find leaks with areaportals using the same methods as geometry gap leaks.
Special geometry does not seal the world
Displacements and water also do not seal maps and will cause leaks. You can fix this type of leak by adding a solid brush behind them to seal the map. Using a brush with the
tools/toolsnodraw material will seal the map, but not add any additional rendering cost, so it's a great way to seal the map behind displacements. Water should be sealed off with whatever is sealing off the area above it (probably
tools/toolsskybox or another typical texture, such as bricks.) Do not use nodraw to seal off water, as this will cause a weird trailing effect.
Mismatched entity origins
A more subtle cause of leaks can be with any entities that have origin helpers, such as func_door_rotating or func_rot_button. While the entity itself may be inside the world, if the origin helper is outside the map, the entity will cause a leak. If you find a pointfile heading to a empty spot outside of the map, and there is no entity there, an origin helper is a good thing to look for.
One way to quickly tell if an entity origin is causing the leak is to:
- Load the pointfile.
- Find the endpoint(s) of the pointfile.
- Choose Select All from the Edit Menu.
- Make sure Show Helpers is checked on the View Menu.
- If you see an origin helper appear at the pointfile, you know that's the problem.
If you have an origin helper causing a leak, you can select the object and manually move the origin back into the world, use the Center Origins command from the Tools Menu, or simply right-click on the origin helper and select Center on entity.
Mismatched entity origins usually occur when a brush entity with one of these helpers is moved while in Solids mode. Moving a brush entity in solids mode does not move the entity's origin helper.
Brushes with translucent materials, like glass, can cause leaks in one circumstance. That being, when a brush with a translucent texture is facing the void. It doesn't matter on which side the translucent texture is, as having at least one side translucent makes the brush incapable of sealing the level.
In this case your pointfile will go straight through a brush into the nearest entity. Check if it's possible to see out into the void and vice versa through any of the 6 faces of the brush that the pointfile is passing through. Alternatively, this can be easily fixed with the Apply current texture tool with the tools/nodraw texture and then texturing the visible sides with the texture they originally were.
Func_viscluster can also cause leaks when they cross areaportal surfaces, or are too close to them. Disabling all func_visclusters and compiling to see if the leak is gone should be done, at least as last resort. To do: How do you actually fix this?
Although very rare, it is possible VBSP reports false leaks in your level. If you are sure that there should not be a leak reported by VBSP, copy your map and paste it into a fresh new map file. If it compiles fine, then your old file could have been corrupted.
Not having any entities inside the level
Not having any type of entity inside the level will cause a leak. This is why pointfiles originate at an entity, because VBSP uses entities as a reference point for what is the inside of a map. Your map should always at least have a spawn entity in it.
Not covering func_detail with solid brushes, can also cause leaks which can be hard to find if someone doesn't realise that it's caused through a func_detail.
Situations that do not leak
There are a number of situations which in fact do not cause a leak, even though it appears an entity is positioned outside the map.
Instances are not entities - during loading, their contents are merged into the map. This means brushes inside an instance can seal a map, and the location of the actual func_instance entity is not important, as long as any entities in the instance get placed inside the map.
Only the origin matters
Only the origin of the entity is considered when looking for leaks. The actual geometry of a brush or model can be partially or entirely inside the void, as long as the origin point is inside the map. Of course no lights are able to reach the void, so these entities should probably be unlit or invisible.
Entities at the origin and inside brushes
Entities with their origin at exactly
0 0 0, or with their origin inside a solid brush do not leak. They are effectively ignored when determining the inside and outside of the level.
Conclusion: An ounce of prevention
Using the pointfile tools makes finding leaks relatively painless, but one of the most important ways to fix leaks is by preventing them in the first place. Taking your time when building, and making sure brushes are snapped properly to the grid can go a long way towards eliminating leaks before they occur. The cleaner and more organized your geometry, the more likely you are to be able to spot leaks when they occur, or even prevent them from happening in the first place. You can also help prevent lots of extra work by compiling your level as you go along, instead of building your whole level before trying to compile it. Finding one leak at a time while the map is only partially complete is a lot easier and faster than finding leaks in a complete map that is full of geometry.