Understanding Source Engine BSP PVS for Better Map Performance
Learn how Source Engine’s precomputed PVS determines which map leaves are drawn, how to verify it during compile, and what pitfalls to avoid for better performance.
07 Jul 2026, 09:33 UTC

Why Your Indoor Map Feels Slow
You have a detailed indoor map with plenty of props and lighting, yet the frame rate drops noticeably when the player looks toward a crowded hallway. The culprit is often not the raw polygon count but the visibility decision made by the Source Engine’s pre‑computed PVS (Potentially Visible Set). When the engine builds a map, it splits the space into leaves and creates a leaf‑to‑leaf visibility matrix. At runtime the camera checks this matrix to skip rendering entire leaves that are guaranteed to be occluded. If the matrix is too permissive, many leaves are drawn even though they are hidden, wasting fill‑rate and vertex work.
How PVS Is Generated at Compile Time
The PVS lump is produced by the VVis stage of the map compile pipeline. VBSP first creates the BSP tree and leaf structure; VVis then samples points inside each leaf and determines which other leaves can be seen from those samples, storing the results as a compressed bit‑matrix. The process is deterministic for a given set of compile options.
vbsp.exe -game csgo -threads 4 mymap.vmf
vvis.exe -game csgo -fast mymap
vrad.exe -game csgo -both -threads 4 mymap
The -fast flag tells VVis to use a quicker, less accurate sampling method, which reduces compile time but may produce a more permissive PVS (more leaves marked visible). Removing the flag yields the default, higher‑quality visibility at the cost of longer compile times.
Checking the PVS Data
After VVis finishes, its console output includes a summary such as:
Visibility leaves: 1248, potential visible sets: 3421
These numbers give a quick sense of how many leaves the engine considers and how large the visibility matrix is. You can also open the resulting .bsp with a tool like VBSPView or Nem’s BSP viewer to inspect the raw visibility lump.
In‑game, you can visualize which leaves the engine thinks are visible:
r_showportals 1– draws the portal boundaries that separate leaves.r_showtris 1– renders triangles shaded by leaf visibility, making over‑draw obvious.
Common Pitfalls and Workarounds
Because PVS is static, any geometry that moves after compile – such as rotating doors, elevators, or scripted props – is not considered by the matrix. If such objects occlude the view, the engine may still render leaves behind them, causing visible “leaks.” The standard solutions are:
- Place
func_areaportalbrushes tied to the moving object so the portal opens and closes with it. - Use hint brushes to manually split leaves and force the compiler to create additional portals that better match the moving geometry.
- For small, frequently moving props, mark them as
movepushorprop_dynamicwith themovepushflag so they are excluded from PVS checks and rendered as dynamic objects.
Another common issue is overly aggressive visibility caused by the -fast flag or by insufficient detail in the map’s geometry (large, flat walls with no detail). This can lead to drawing far‑away rooms that should be occluded, hurting performance. Adding subtle detail brushes or converting flat walls into detail brushes helps VVis make finer leaf divisions.
Trade‑offs and Practical Tips
Balancing compile time, PVS accuracy, and runtime performance is a mapper’s ongoing task:
- Use the default VVis settings for final builds; reserve
-fastfor rapid iteration. - Keep an eye on the “Visibility leaves” count during compile – a sudden jump often indicates that a new area has been opened up unintentionally.
- After major geometry changes, re‑run VVis and verify the leaf count and in‑game visuals with
r_showportals 1. - Remember that dynamic objects and viewmodels bypass PVS entirely; rely on them only for elements that truly need to move.
By understanding how the Source Engine’s PVS works and checking the visibility data at each compile stage, you can keep indoor maps both visually crisp and frame‑rate friendly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.