Ads keep us online. Without them, we wouldn't exist. We don't have paywalls or sell mods - we never will. But every month we have large bills and running ads is our only way to cover them. Please consider unblocking us. Thank you from GameBanana <3

Visibility Optimization

A Tutorial for Goldsource Engine

No ads for members. Membership is 100% free. Sign up!

1. Requisites

2. Visleaves, worldleaves and portals

Maps are divided into areas called visleaves, which define a group of visible faces. Every single face in a map is part of a visleaf.

All world geometry is part of a brush model called worldspawn. Initially, VIS builds 8192 visleaves that only cover worldspawn, before building visleaves for other brush models. These initial 8192 visleaves are known as worldleaves.

Portals are the shared faces of adjacent visleaves. Only world geometry affects visleaf generation.

3. Potentially visible set

The potentially visible set (PVS) determines which visleaves are rendered from a given location. Visleaves that are in direct line of sight on any point on the visleaf the player is in are rendered, even if they are not in the direct line of sight of the player. If a visleaf is outside of the PVS, all faces inside of that visleaf are not rendered.


4. Loading portal files in J.A.C.K.

You can load portal files in J.A.C.K. to look at the visleaves; however, they can't be loaded unless some modifications are made. Here is an example of a .prt file after compilation.
7
8
1
1
1
1
1
1
1
4 1 6 (192.000000 -256.000000 160.000000) (112.000000 -256.000000 160.000000) (112.000000 -256.000000 64.000000) (192.000000 -256.000000 64.000000)
4 1 3 (-8.000000 -256.000000 64.000000) (-256.000000 -256.000000 64.000000) (-256.000000 8.000000 64.000000) (-8.000000 8.000000 64.000000)
4 1 2 (-256.000000 256.000000 64.000000) (256.000000 256.000000 64.000000) (256.000000 8.000000 64.000000) (-256.000000 8.000000 64.000000)
4 2 4 (-256.000000 256.000000 56.000000) (256.000000 256.000000 56.000000) (256.000000 8.000000 56.000000) (-256.000000 8.000000 56.000000)
4 2 3 (-256.000000 8.000000 64.000000) (-256.000000 8.000000 56.000000) (-8.000000 8.000000 56.000000) (-8.000000 8.000000 64.000000)
4 3 5 (-8.000000 -256.000000 56.000000) (-256.000000 -256.000000 56.000000) (-256.000000 0.000000 56.000000) (-8.000000 0.000000 56.000000)
4 3 4 (-256.000000 0.000000 56.000000) (-256.000000 8.000000 56.000000) (-8.000000 8.000000 56.000000) (-8.000000 0.000000 56.000000)
4 4 5 (-256.000000 0.000000 56.000000) (-256.000000 0.000000 0.000000) (-0.000000 0.000000 0.000000) (-0.000000 0.000000 56.000000)

The first line indicates the number of visleaves, and the second line indicates the number of portals. All lines between the first two and the lines with portal coordinates need to be removed.
7
8
4 1 6 (192.000000 -256.000000 160.000000) (112.000000 -256.000000 160.000000) (112.000000 -256.000000 64.000000) (192.000000 -256.000000 64.000000)
4 1 3 (-8.000000 -256.000000 64.000000) (-256.000000 -256.000000 64.000000) (-256.000000 8.000000 64.000000) (-8.000000 8.000000 64.000000)
4 1 2 (-256.000000 256.000000 64.000000) (256.000000 256.000000 64.000000) (256.000000 8.000000 64.000000) (-256.000000 8.000000 64.000000)
4 2 4 (-256.000000 256.000000 56.000000) (256.000000 256.000000 56.000000) (256.000000 8.000000 56.000000) (-256.000000 8.000000 56.000000)
4 2 3 (-256.000000 8.000000 64.000000) (-256.000000 8.000000 56.000000) (-8.000000 8.000000 56.000000) (-8.000000 8.000000 64.000000)
4 3 5 (-8.000000 -256.000000 56.000000) (-256.000000 -256.000000 56.000000) (-256.000000 0.000000 56.000000) (-8.000000 0.000000 56.000000)
4 3 4 (-256.000000 0.000000 56.000000) (-256.000000 8.000000 56.000000) (-8.000000 8.000000 56.000000) (-8.000000 0.000000 56.000000)
4 4 5 (-256.000000 0.000000 56.000000) (-256.000000 0.000000 0.000000) (-0.000000 0.000000 0.000000) (-0.000000 0.000000 56.000000)

Instead of manually editing the portal files every time you compile your map, you can use this useful tool to improve your workflow. It will automatically fix portal files if you add it into your J.A.C.K. advanced compile run commands.
Share banner

Afterward, you can then load the portal file with Map > Load portal file...


5. Checking map performance in-game

You can see the FPS, latency and number of world and entity faces being rendered with the r_speeds 1 console command. You can also use the gl_wireframe 2 console command to outline all faces currently being rendered.

Note that gl_wireframe 2 will not work if you create a server, so you must restart the game and launch your map in singleplayer mode with the map console command.




6. HINT and SKIP

Hint planes are used to split visleaves during compile time, allowing you to optimize what parts of the map are visible. Faces with the HINT texture will split visleaves. Faces with the SKIP texture are ignored by the compiler. Hint planes can intersect other geometry and do not have to be perfectly on the grid to work.


While optimizing your map, it is a good idea to hide func_detail entities since they do not cut visleaves. One of the ways to optimize a map would be to create diagonal hint planes.


Another way would be to create horizontal hint planes.



As you can see, we have successfully reduced the number of faces being rendered.




7. func_detail

func_detail can be used to increase performance and reduce VIS compile time. This is not a real entity as it is converted into worldspawn after compile. This gives func_detail an advantage over brush entities such as func_wall, as it does not count towards the edict limit of 1024.

Brushes tied to func_detail will not affect visleaf generation, but they still affect worldleaf generation. They cannot be used to seal the map; otherwise, you will get a leak error.

As a rule of thumb, all geometry with faces on non-axial planes should be func_detail.


Here's the VIS compile log with the use of func_detail around my map.
503 portalleafs
1258 numportals

BasePortalVis:
(0.09 seconds)
LeafThread:
(0.37 seconds)
average leafs visible: 68
g_visdatasize:29330 compressed from 31689
0.53 seconds elapsed

Here's the VIS compile log without the use of func_detail. The compile times have increased by 1160%.
1031 portalleafs
2966 numportals

BasePortalVis:
(0.27 seconds)
LeafThread:
(6.33 seconds)
average leafs visible: 111
g_visdatasize:46589 compressed from 132999
6.68 seconds elapsed

8. func_wall

This is an entity with its own brush model. It does not affect visleaf or worldleaf generation, so this entity is useful for complex geometry that may cause you to exceed the worldleaf limit.

Sign up to access this!

Embed

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

Credits

Key Authors
seedee avatar
seedee username pic Joined 2mo ago
Offline
334 points Ranked 52117th
10 medals 1 rare
  • Returned 1000 times Medal icon
  • Received thanks 5 times Medal icon
  • Returned 100 times Medal icon
  • 1 post awarded Exemplary Feedback Medal icon
  • Submitted 1 Tool Medal icon
  • Reached 10 subscribers Medal icon

Submitter

seedee avatar
seedee username pic Joined 2mo ago
Offλine
334 points Ranked 52117th
10 medals 1 rare
  • Returned 1000 times Medal icon
  • Received thanks 5 times Medal icon
  • Returned 100 times Medal icon
  • 1 post awarded Exemplary Feedback Medal icon
  • Submitted 1 Tool Medal icon
  • Reached 10 subscribers Medal icon
seedee avatar
seedee

Creator
  • Paypal Donate
Sign up to access this!
Sign up to access this!
Sign up to access this!

Game

Sign up to access this!

Category

Details

Difficulty Level
Advanced

Attributes

Genre
Mapping

Share

  • Share on Reddit
  • Share on Twitter
  • Share on Facebook
  • 5
  • 367
  • 6
  • 22d
  • 4d

More from Submitter

Tool Textures
Tool Textures folder Mapping Intermediate
Volumetric Lighting
Volumetric Lighting folder Mapping Beginner
func_vehicle
func_vehicle folder Mapping Intermediate
Embedding Custom Textures
Embedding Custom Textures folder Mapping Intermediate

WiPs by Submitter

More Mapping Tutorials