Optimizing Static Occlusion in Source Engine Maps with Leaf Portals
Learn how to use areaportal brushes and multi‑threaded BSP/VVIS compilation to tighten leaf visibility, cut render load, and avoid common pitfalls in Source engine map building.
28 Nov 2025, 10:54 UTC

Why Leaf Portals Matter
In Source engine maps, each BSP leaf represents a convex space. The engine uses the visibility lump to decide which leaves are potentially visible from the player’s eye. If a leaf is outside the view frustum or behind an opaque portal, the engine skips rendering it entirely. This static occlusion culling can cut draw calls by 30‑80% on large maps, but only if the visibility data is accurate.
Practical Decision: Carve with areaportal Brushes
The most reliable way to shape visibility is to add func_areaportal brushes in Hammer. These are invisible, solid brushes that the engine treats as opaque boundaries, cutting visibility between the leaves they separate.
Entity: func_areaportal
Position: 0 0 0
Brush: 0 0 0 0 0 1000 0 1000 0 1000 0 0 1000 1000 0
Brush: -1000 0 0 0 0 0 0 1000 0 -1000 1000 0
Place the brush so it spans the full height of the area you want to hide. The brush must not intersect moving entities (doors, pistons, etc.) or you’ll get visual glitches. Once added, rebuild the map.
Speed Up Compilation with Multi‑Threading
Large maps can take minutes to compile. The -threads N flag tells vvis and bsp to use multiple CPU cores. On a quad‑core machine, -threads 4 often halves the build time.
map mymap -threads 4
Make sure your machine has enough RAM; each thread consumes memory for visibility calculations. A 16‑GB system is a safe baseline for most large maps.
Verifying Leaf Culling
After compiling, launch the map and enable console variables to see the portal system in action.
r_showportals 1– draws portal lines where the engine will cut visibility.r_leafcount 1– displays the number of leaves currently considered visible.r_drawothermodels 5– forces the engine to render all other models; any that disappear when portals are enabled are correctly culled.
Typical results: a correctly placed areaportal reduces r_leafcount from 2000 to 800 in a large interior, and you’ll notice a drop in FPS spikes when moving through the area.
Limits and Common Pitfalls
- Static Only: Portals only affect static geometry. Dynamic objects (func_door, rotating lights) are always rendered if they’re within the player’s view.
- Over‑Portaling: Too many small portals increase compile memory and can actually hurt runtime performance because the engine has to check more visibility connections.
- Misplacement: A portal that cuts through a player’s starting position or a projectile’s path will cause sudden pop‑ins or frame rate hitches.
- Complex Geometry: Adding dense geometry without matching portals expands the visibility graph, leading to longer VVIS times.
Common Mistakes to Avoid
- Adding portals that intersect
func_doorbrushes. The engine will ignore the portal because the door’s geometry is dynamic. - Forgetting to set the brush to “solid” in Hammer. A non‑solid brush will not block visibility.
- Using negative coordinates that place the portal outside the map bounds. Such portals are ignored by the engine.
- Relying solely on
r_showportalsfor validation. Always cross‑check withr_leafcountand visual tests.
Practical Checklist
| Step | What to Do | Why |
|---|---|---|
| 1 | Create areaportal brushes around static choke points. | Defines visibility boundaries. |
| 2 | Compile with -threads N matching your CPU cores. | Reduces build time. |
| 3 | Test with r_showportals and r_leafcount. | Confirms portals are active. |
| 4 | Run gameplay tests for pop‑in or clipping. | Ensures player experience is intact. |
Conclusion
By carving visibility with areaportal brushes and leveraging multi‑threaded compilation, you can dramatically reduce draw calls and compile times for large Source engine maps. Just remember that portals are static, so dynamic objects will still render. Verify your setup with the console variables above, and keep an eye on compile memory usage to avoid over‑portaling. With these practices, your maps will run smoother and build faster.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.