Visclusters and Optimization - an in-Depth Look

A Tutorial for Source Engine

Sign up to access this!
Before we begin, this tutorial requires knowledge of how visleafs work, and is intended as an extra measure to optimization, not a replacement. 

If you're new to visleafs and optimization, please read and practice the following write-ups found on the Valve Developer Community :
[Visibility Optimization]



Viscluster is a function-brush-based entity available in orange box games. It is used by making a trigger volume and tying it to func_viscluster.

In short, visclusters group together multiple visleafs in one area, and tell the compiler not to process sight between each visleaf in that area. 

This is useful because sometimes, no matter how well we optimize using func_detail, hint / skip, and areaportals, hammer will still cut visleafs where we don't want it to. Visclusters, while they don't actually remove the visleafs, optimize the engine by telling all the visleafs within it's custer not to calculate visibilty to each other. Basically, it calculates all visleafs into one numportal, instead of many smaller numportals for each visleaf.

Here is a quick view of what Visclusters can do for a map. In the example below, I have properly added hint/skip, areaportals, and func_details to my map, but I still have some unfavorable visleafs. It's time to add some visclusters.

[fullsize image]

[fullsize image]

By checking my compile log I can see that without visclusters I have :
  • 80 portalclusters
  • 159 numportals
And with visclusters I have :
  • 27 portalclusters
  • 36 numportals
Keep in mind that my map is currently very small and yet we can still see a very large difference in VVIS compile. 

We wouldn't notice much of a difference in game, but visclusters essentially simplify the calculation of visleafs for our compile AND the processing in-game. Meaning if you have a very large room, or a big open skybox, we can take some of the processing away from our compile (making it faster), and the real-time processing of clients playing our map (making it smoother).

Before I get started on placement of visclusters in a map, I feel it is important to do some 'proof of concept' and clarification about viscluster functionality. 

I'm going to load up the BSP of our second screenshot in-game, where we have already implemented visclusters.

[fullsize image]

By checking our leafvis with mat_leafvis 3, we can see a discrepancy between our leafvis in-game, and our portal file in hammer. This is because, again, visclusters don't actually remove our visleafs, they just tell all the visleafs in the same cluster not to calculate visibilty to each other.  

This is why it is still important to use func_detail and proper optimization along-side our visclusters. You could cover entire areas of your map in func_viscluster without using func_details, and visclusters would alleviate visibility processing; however, your computer still has to process that the visleafs are there. Meaning if you have 2,000 unnecessary visleafs in an area, though not individually 'cross-processing' them real-time, they are still being 'accounted for', which will cause unnecessary strain for us and our clients.

Now, to prove in-game that visclusters are actually calculating visleafs together, and not individually, I devised a little test.

First, let's look at how the visleafs work normally without using visclusters.
I placed hint/skip as seen here: 

To acheive the following in game : 

We see that my hint/skip is functioning and not rendering the other area of my map that we can no longer see.

Then, I went ahead and covered the entire room in a func_viscluster : 

This will prove, if it works as intended, that even though I cut visleafs using hint/skip, that the viscluster will override my changes and treat the entire room as one numportal, thus not calculating visibility between the visleafs I just cut. (Note: this is not an effect that I actually want in this scenario, but it makes for a good example of functionality) 

After compiling and loading it up in-game we can see that it's working as intended and treating the whole room as one numportal. 

With that out of the way. Let's talk about placement of visclusters in your map. This is where prior knowledge of visleafs come in, as I cannot give specifics for every possible scenario where visclusters are useful. 

Basically, we want to aim for the fewest numportals possible while retaining the optimization we have already done in the map. (IE : The hint/skip I showed in the first GIF is still an effect that I want) This is also why I would recommend using visclusters as a final step to optimization, as they should be used once you've already simplified visleafs as much as possible.

In order for our func_viscluster to work properly, it has to fully cover all of the visleafs inside of it. Visleafs that are only partially covered by a func_viscluster will not give us a desirable effect and can sometimes cause the whole viscluster not to function as intended, usually by merging both portals the visleaf is touching together.

Let's look at some of the places I've placed my visclusters.

Starting with something small and simple, we have a room that's being cut in half. 

Both visleafs can see the areaportal so no matter where you are in the room, the player will always render the other side. By covering this whole room with one func_viscluster, we go from 2 numportals to 1.

Here is a room with no changes to visleaf cutting.

I added some hint/skip to simplify the visleafs

And finally clustered the entire room together. No matter where you are within the room you can see it's entirety, and all visleafs can see the areaportal, so it's fine as one numportal.

 In my large room, in order to get the effect i wanted, I first added my hint/skip, areaportals, and func_detail. I still have some odd visleaf cutting due to the way the engine works.

So, I add 3 different func_visclusters, matching up with hint/skip, to create the 3 numportals within the room that I want.

[fullsize image]
Seen below, our portals (once we compile) still show us where the visleafs are touching, but they are not actually cutting into the numportals as they may appear.

Again, my map is very small at the moment, so I decompiled a larger map that I thought would make for some good examples. I'll be showing the spawn area of bhop_cw_journey  by user Roma

We can see the difference from 0 changes : 

[fullsize image]
  • 678 portalclusters
  • 1991 numportals
Improved func_detailing (not pefect, did a glance-over) :

[fullsize image]
  • 222
  • 684

And finally, improved hint/skip and adding visclustering :

[fullsize image]

  • 16 portal clusters
  • 31 numportals
This was a quick do-over and could be improved. But even with a few minutes of work I added a total of 8 visclusters to reduce our numbers from the thousands down to double-digits, and shaved a good 4-5 seconds off the compile as well. 

This is the power of visclusters and although they can merge portals if you're not careful, they are a very strong tool that I would recommend every mapper take the time to learn.



Share banner
Image URL:
HTML embed code:
BB embed code:
Markdown embed code:


Key Authors
Whimsy avatar
Whimsy username pic Joined 11y ago
2,608 points Ranked 1970th
13 medals 1 legendary 1 rare
  • 10 years a member Medal icon
  • 6 years a member Medal icon
  • Reached 1,000 Points Medal icon
  • 1 post awarded Exemplary Feedback Medal icon
  • One month a member Medal icon
  • 6 months a member Medal icon


Whimsy avatar
Whimsy username pic Joined 11y ago
2,608 points Ranked 1970th
13 medals 1 legendary 1 rare
  • 10 years a member Medal icon
  • 6 years a member Medal icon
  • Reached 1,000 Points Medal icon
  • 1 post awarded Exemplary Feedback Medal icon
  • One month a member Medal icon
  • 6 months a member Medal icon

Whimsy avatar

Sign up to access this!
Sign up to access this!
Sign up to access this!


Sign up to access this!



Difficulty Level



  • Share on Reddit
  • Share on Twitter
  • Share on Facebook
  • Share on Google+


  • 1 Posts
  • 2ySubmitted
  • 2yModified


80 bScore
9 Rating

1 voter

Sign up to access this!

More from Submitter

More Mapping Tutorials tracking pixel