Controlling Visibility With Areaportals and Occluders
(September 30, 2017)
Visibility control is the most important part of optimizing your map. Too much happening on-screen at once is guaranteed slowdown, so cutting the amount of detail being rendered is key. While the second compile process, VVIS, does a rather good job of this on its own, it's not perfect, and occasionally, it needs some help.
There's two types of brush entities you can use to control what's being rendered in an area: areaportals and occluders.
Why should I use areaportals?
The VVIS compile process determines which visleaves (empty spaces inside the game world split by brushes) can be seen from any one point, and normally, this is more than enough to control visibility in a level. If you're not at CT spawn on de_dust
, why would the game render it? There are special cases where this isn't enough, however. Take the following sample scene.
The issue with it might not be immediately obvious, but switch on mat_wireframe
and it'll become apparent:
That's right, we're rendering a bunch of props and NPCs that aren't actually on-screen. Because of the way these areas are set up, both rooms and everything inside them will get rendered, no matter where the player is in either. What's the solution? VVIS won't help in this instance; the hallway visleaf touches both rooms, which means both rooms are in the potentially visible set at all times. Enter the areaportal.
What are areaportals and how do I use them?
The areaportal is a brush entity that tests for what the player can see through it at any given moment. To make one, make a brush with the tools/toolsareaportal
texture on all sides, tie it to a func_areaportal
entity, and put it at the mouth of a hallway.
The areaportal can either be open or closed. If open, the areaportal will prevent any entity not immediately in sight of the player's viewpoint (call it a view frustum to impress your friends) from being rendered.
If closed, the areaportal prevents anything from being rendered through it. You can also link an areaportal to a door entity through the "Name of Linked Door" keyvalue, and that areaportal will open and close with the door. Be sure to make the areaportal thinner than the door so it does not block the door itself from being rendered.
Care and feeding of your areaportals
Simple, right? Link an areaportal to every door and let it go.
Of course, it's not that simple. It takes valuable cycle time for that areaportal to function, and if there's too many on-screen, rendering the scene without them actually becomes faster. Like all optimization techniques, you'll have to test it in your specific scene and see what works best. For example, the spawn room has nothing in it, aside from the player. Thus, an areaportal facing the spawn room is nonsensical.
There's a few caveats to working with an areaportal. If your areaportal crosses the surface of a water brush, you'll need to split it at the water surface and make the split two separate areaportals or else the water brush won't display right. (They'll merge back together at runtime.) The other major caveat involves "leaking" areaportals and how they seal off areas.
Areaportal leak ! Brush 1269: areaportal brush doesn't touch two areas
By this point, you should be aware that a map with a leak is bad. VVIS won't run on a leaky map, and water and particle effects won't display right on a leaky map, either. Areaportals also need to be sealed, in the sense that any one side of the areaportal shouldn't be able to touch any other side of the same portal. If the compile tools can find any way to touch one side to another, it'll leak. This becomes the most tedious part of working with areaportals.
You can think of an areaportal as splitting areas of the map into smaller maps. The inside region of any one of the smaller maps shouldn't touch the inside region of another. Make sure that all sides of the areaportal touch solid world geometry; func_wall
and func_detail
will not stop an areaportal leak. If it's not touching all four sides of the hallway, you'll know because your pointfile will be rather short.
If your areaportal leaks and you're sure it's not because it was constructed wrong, use the pointfile to find the leak and plug it up with another areaportal. Keep doing this until it stops leaking. Remember, if you have too many in one area, it'll be faster to render without them.
Occluders
Occluders work in a similar way to areaportals, but are more niche in use. Occluders will block any props behind them from being rendered. Occluders don't block world geometry, split visleaves, or cause leaks. In fact, an occluder can be completely free-standing, with no ill effects. To make an occluder, create a brush, texture all of its sides with tools/toolsoccluder
, and tie the brush to func_occluder
.
Note the white box (that is, the occluder surface) and how only the barrel peeking out from the side is rendered. Occluders have their own render cost, so use them sparingly.
The downside to areaportals and occluders is that, because of their effectiveness versus their cost, their use is rather limited. Trying to fit areaportals into large, open areas of your map can be done, but it's best to just reduce detail and use open areas sparingly. Areaportals are a helpful tool, but they don't work miracles.