Demystifying Source Engine Visleaves
IntroAnother fitting title for this article would have been “a beginners’ guide to source engine visleaves”; this is because I will be simplifying the definition of visleaves using layman’s terms and plain English in a way that even beginners can understand and grasp.
I won’t be using technical jargon or advanced lingo; just simple terms even absolute beginners can follow. It is very important to grasp the concept of visleaves, otherwise all optimization efforts will be useless and aimless. Once visleaves are understood, optimization becomes very easy; you can trust me on this one and you will see it unfold throughout this article.
Definition in plain EnglishBefore defining visleaves and giving tangible examples, let me give you a brief historical background about them.
Visleaves were first discovered by Adam and Eve as they used “leaves” to cover the “visibility” of their private parts. The guys at Id Software learned about this discovery and wanted to acquire the copyrights of these visleaves. Adam refused, so Id threatened to summon a powerful “Quake” that will bring “Doom” upon humanity. Adam had no choice but to relinquish visleaves to Id.
Now with this “accurate and very true” historical background out of the way, let us examine the modern definition of visleaves, in the frame of the Source engine (if you want an in-depth look at BSP and visleaves concept, please consult my paper Man Vs Engine, paragraph II).
In the simplest definition possible, a visleaf is just a polyhedron (polygon in 3D space), most likely a cube or rectangular cuboid, although other shapes are viable options too. Think of a visleaf as a room with 4 walls, a floor and a ceiling, only these are transparent and non-solid.
Any map in Source is basically a group of these “rooms” connected together where the player can freely travel from one to another (as long as they are on ground level); the player can only be in one “room” at any time.
The size and borders of these “rooms” are generally decided by the surrounding geometry (the world brushes) and by hints and areaportals. The creation and division of these “rooms” is done by vbsp during the map’s compiling.
Let us check some examples about these “rooms” or better revert to calling them visleaves, shall we. I will use my map cs_calm for the examples.
Can you see the blue lines going on the XYZ axes to form a rectangular cuboid? Good. This is the visleaf, plain and simple. I, the player, am standing right inside the visleaf.
Let me switch to third person view so you could have a better angle to check the visleaf.
Much better now?
You can clearly see that the player is within the borders of the visleaf. As I said earlier, the player can only be in 1 visleaf at any time.
From the top view, we can represent the flat visleaf as a rectangle. We will call this visleaf “A” for the remainder of this article.
Once these visleaves are created, vvis runs an algorithm to calculate visibility between these visleaves and to determine what we colloquially refer to as a visleaf “seeing” another visleaf.
In the simplest explanation of how “seeing” is determined, just imagine that vvis is Robin Hood with his bow and arrows; vvis, sorry Robin, will stand in the visleaf and fire his arrow towards another visleaf in a perfect straight line. If the arrow reaches the other visleaf unobstructed, then a direct line of sight (LOS) between these 2 visleaves is established, and we can say that the first visleaf can “see” the second visleaf. If the arrow has to cross a world brush/geometry, a skybox brush or travel in parabolic/hyperbolic trajectory to reach the second visleaf, then there is no LOS and these 2 visleaves cannot “see” each other.
In the screenshot above, visleaf B is adjacent to our visleaf A, therefore, a direct LOS can be established between them (white arrow). A and B can see each other.
The second visleaf does not need to be adjacent to be seen. A visleaf further away can still be directly seen by A.
In the screenshot above, the white arrow shoots straight from A to C which means A can see C (no pun intended)
In the screenshot above, a straight line cannot be established between visleaves A and X, therefore A cannot see X (the arrow can start anywhere inside the first visleaf and end anywhere inside the second visleaf).
Remember that one visleaf is not restricted to see only one other visleaf, it can see several visleaves that are surrounding it (just imagine you are in the bedroom with the door open and you can see the living room, the dining room, the second bedroom and possibly part of the kitchen). The number of other visleaves that can be seen from one visleaf is called the potentially visible set (PVS).
The PVS is dynamic by nature; it changes as soon as you move your position to another visleaf. If visleaf A can see visleaves B, C, and D, then the PVS when standing in A is (BCD). If you move to visleaf B and B can see A, C, D, E, and F, then the PVS when standing in B is (ACDEF).
An image would be better illustrating the PVS.
In the screenshot above, we still have our initial visleaf A and the 2 visleaves B and C which we established that they can be seen from A. In addition, I have painted in orange all the visleaves/areas that are seen from A (a direct LOS can be established).
This orange area in addition to B and C is basically the PVS, the collection of all visleaves that can be seen from visleaf A. Please note that these visleaves that I highlighted are for a well optimized map, otherwise the PVS would have been bigger.
Link between optimization and visleavesNow that we know what a visleaf is, how it is created, and how visibility and interaction with other visleaves is done, the big question looms in the horizon.
What does all this have to do with optimization? After all, I promised you earlier that once you understand visleaves, optimization becomes the easy part. I’m a man of my word and I will keep my promise.
As I said in the intro, I won’t be using technical definitions or go into in-depth analysis but I still need to briefly and very clearly explain the BSP concept so we can relate visleaves with optimization.
The BSP, or Binary Space Partition, is the method that the Source engine uses to compute visibility. We have already seen that during the compile phase, vbsp takes care of creating the visleaves in the map then vvis shoots its arrows and calculates the visibility between visleaves. All this info (visleaves’ locations, PVS, visibility matrix) are stored in the BSP tree (think of it as a big library shelf where each book is neatly labeled and indexed for easier retrieval at a later stage).
The BSP uses “visibility from a region” approach since the regions or visleaves are already created and the visibility matrix is calculated. What does that mean in plain English?
I, the player, am standing in visleaf A as we have seen earlier. The engine immediately knows that I can be in only one visleaf at a time and it is currently visleaf A. The engine goes quickly to the neatly indexed book shelf (the BSP tree) and checks visleaf A. The information retrieval is instantaneous and the engine swiftly recognizes what other visleaves can be directly seen from A (The PVS).
With all this info clearly available, the engine will proceed to render ALL the visleaves in the PVS of A; when the visleaves are rendered, ALL their content is rendered too. Let’s get back to the previous screenshot to better display this info.
The engine does not care where I am exactly standing in visleaf A; it does not matter if I am standing to the left or right, in the center, or on the edges. As long as I’m inside visleaf A, the engine renders all the PVS of A, the orange area in addition to B and C (that is why it is called visibility from a region method).
Other games might use the “visibility from a point” approach where the engine calculates and renders the world around you in real time relative to the exact position you are standing at. The Source engine doesn’t care about your exact location rather about the visleaf you are standing in, to determine what is rendered and what is not.
You can now clearly notice the quintessential role and importance of the visleaf in your optimization endeavor.
The immediate conclusion you can draw from all this explanation is that the smaller the PVS, the better fps you will have. A smaller PVS means fewer visleaves to draw and fewer visleaves’ content to render (brushes, textures, props, entities…).
There you go; I kept my promise :)
All you need to focus and concentrate on while optimizing a map in Source is to make sure any given visleaf in the map can see the minimum amount of visleaves around it.
In my paper Man Vs Engine, I summarized optimization in one sentence and I feel I should repeat it here to emphasize what I just said.
Your ultimate goal is to make a specific visleaf “see” the least amount of adjacent leaves thus preventing the engine from rendering the content of these “unseen” leaves which will reduce engine overhead and increase frame rate.
Now that you know the essence of optimization, the tools and techniques become easier. You will mostly use the layout itself, skybox brushes, func_detail, and hint brushes to delimit visleaves, cut large visleaves into smaller ones and make sure the visleaf in hand sees the utmost minimal amount of surrounding visleaves.
For visleaves’ content, and in addition to hints, you will likely use areaportals, occluders, props fade distance, and nodraw to keep visible render-able content at a minimum and prevent the engine from over-rendering which will inevitably lower your fps.
Let’s re-examine the PVS screenshot but this time assuming the map to be un-optimized properly.
You can note that, in addition to our original PVS (orange area + B + C), the PVS of the un-optimized map is bigger with the additional purple area added. Without proper optimization and control, the visleaves tend to be large, covering wide areas, and extending around corners and upwards. This only means that visleaf A will see a much larger number of surrounding visleaves; the PVS will be bigger. When you stand in visleaf A now, the engine will render practically twice the number of visleaves compared to the optimized map version (orange area). When your PVS doubles, your fps will decrease, and depending on the visleaves’ content and amount of brushes/models/entities, it could be as severe as plunging to half its original value.
ConclusionAs I promised you in the beginning and as we have seen throughout this article, optimization in itself is quite easy once you grasp the concept of visleaf.
Visleaves are the cornerstone of the Source engine since the whole visibility calculation and approach relies on them and their spatial order.
Once you realize how Source engine uses visleaves to compute visibility, optimization becomes intuitive; fewer visleaves visible at a time, higher fps and everyone is happy.