Mapping & Hammer

func_detail vs World Brush: What Goes Where in Hammer

func_detail or world brush? Clear rules with measurements from a test compile: what seals, what cuts visleafs and which mistakes lead to leaks.

A brush stays a world brush when it seals the map against the outside or blocks the view between two areas: outer walls, floors, ceilings and dividing walls. The rest of the solid brushwork becomes func_detail, meaning pillars, steps, frames, trims and furniture. The reason is the visibility calculation: only world brushes cut the space into visleafs and portals. In a test room with 64 pillars VVIS reported 180 portals. With the same pillars as func_detail it reported 4.

What world brushes do for visibility

VBSP builds a BSP tree from the world brushes. Every plane that a brush face lies on can divide the space. What remains are convex pieces of space, the visleafs, and between neighbouring leafs the portals. Two more things come from the same tree:

  • Sealing: VBSP floods the tree starting from the entities. If the flood reaches the void, it reports **** leaked ****.
  • Faces: Visible faces are split along the cuts, so many cuts also mean many small faces.

The VBSP source code Valve published with the Source SDK 2013 is unambiguous about the order: tree, portals and leak test are created exclusively from brushes without the detail flag. The detail brushes are only added afterwards.

What func_detail changes about that

func_detail is not an entity that exists in game. While loading, VBSP moves its brushes into the world, flags them as detail and discards the entity. What follows from that:

  • No influence on visibility. Detail brushes create no visleafs and no portals, but they do not block the view either.
  • No sealing. They are absent from the leak test.
  • Still solid. In the BSP they keep the flag for solid geometry. Players and props collide with them like with any wall.
  • No name, no inputs. Apart from the DirectX levels, the FGD defines no keyvalues, and func_detail cannot be moved or hidden in game.
  • World faces stay whole. According to the FGD, a wall is not cut up when a detail sits on it.

In the compile log you recognise detail brushes by three additional VBSP lines:

Chop Details...done (0)
Find Visible Detail Sides...done (0)
Merging details...done (0)

The test: 64 pillars as world brushes and as func_detail

For this article, a room of 2048 by 2048 units and 256 units in height was compiled with GMod's compilers: once empty, once with a grid of 64 pillars (32 by 32 units, floor to ceiling) as world brushes and once with the same pillars as func_detail.

MeasurementEmpty roomPillars as world brushesPillars as func_detail
portalclusters (VVIS)41004
numportals (VVIS)41804
Faces in the BSP96560352
of which floor faces3614036
Brushes in the BSP67070

For VVIS, the room with detail pillars is identical to the empty room. The number of brushes stays the same, so func_detail does not relieve the brush limit from Source engine map limits. The world pillars also split the floor into many small faces, while under detail pillars it stays in the same 36 pieces as in the empty room.

The 180 portals achieve nothing here: VVIS reported an average of 92 out of 100 clusters as visible, because narrow pillars hide almost nothing.

Both variants compile in under a second. So the test shows the mechanism, not the waiting time. Across a whole map the effect adds up to the compile times from the article on VVIS taking forever.

Rules: what becomes detail and what never does

ElementTypeReason
Outer walls, floor and ceiling of the hullWorld brushseal the map
Dividing walls and floor slabs between roomsWorld brushblock the view
Pillars, beams, crates, furniture made of brushesfunc_detailhide almost nothing, create many cuts
Steps, railings, window and door frames, trimsfunc_detailpure decoration
Arches, cylinders, rotated and angled shapesfunc_detailcut the space at unfavourable angles

The test question for every brush is: would the map leak, or could you see into another area, if this brush were missing? If yes, it stays a world brush. If no, select it and turn it into detail with Ctrl+T (Tie to Entity).

Typical mistakes

The most common mistake is a detail brush as part of the outer hull. In the test, one of the four walls was turned into func_detail. VBSP reported the leak and wrote no portal file. The third line comes from VVIS, which then aborted (path shortened):

**** leaked ****
Entity info_player_start (256.00 256.00 1.00) leaked!
LoadPortals: couldn't read ...\d_wall_detail.prt

The fix: select the brush and move it back to the world with Ctrl+Shift+W (Move to World). Finding the spot is covered in fixing the map leak error. More mistakes with the same cause:

  • A hole that only a detail closes. A window frame or a pillar in a corner fills a gap in the hull. It looks sealed in the editor, but for VBSP there is a hole.
  • Areaportal in a detail frame. VBSP also determines the areas for areaportals before it adds the detail brushes, so the opening a func_areaportal sits in has to be enclosed by world brushes. More on that in Areaportals, hints and occluders.
  • Everything is detail. Then no view blockers are left, and the engine draws rooms that lie behind walls. The connection is explained in optimizing GMod map performance.

func_brush, props and displacements compared

TypeCuts visleafsSealsAddressable in game
World brushyesyes, unless its material is translucentno
func_detailnonono
func_brushnonoyes
prop_staticnonono
Displacementnonono

Use func_brush when a brush has to do something in game: it has a name, can be switched with the inputs Enable and Disable, and can be made non-solid through the keyvalue "Solidity". In return it is a real entity and occupies a slot at runtime, see the edict limit and "no free edicts". According to the FGD it only casts lightmap shadows when you set "Shadows" to "Yes".

Finely shaped or frequently repeated objects are better off as a model, see prop_static, prop_dynamic and prop_physics. Terrain is built as a displacement with a simple world brush underneath. In the test, an outer wall with a displacement face led to a leak just like the detail wall.

Making the effect visible

The most important check is at the start of the VVIS output. In the test with the world pillars it looked like this:

 100 portalclusters
 180 numportals

Note numportals before and after a change. These tools help as well:

  • Load the portal file. Map > Load Portal File shows the portals of the last compile in the editor. VBSP writes the .prt file next to the VMF, but only if the map has no leak.
  • Hide the details. In the visgroup list there is an entry "World Details" under "Auto". Without the tick the detail brushes disappear. The world brushes that remain are the hull VBSP works with.
  • Compile without details. According to its help text, the VBSP parameter -nodetail removes all detail geometry. What is left determines visibility.
  • Have the log checked. The Map Scanner detects root causes, follow-up errors and matching fixes in VBSP, VVIS and VRAD logs.

FAQ

Does it matter whether I combine several brushes into one func_detail?

Not for the result. VBSP moves all detail brushes into the world and discards the entity. How you group them only matters for keeping the editor tidy.

How do I build a round outer wall?

In two layers: on the outside a simple, straight hull of world brushes that seals, and in front of it the round shape as func_detail. Apply tools/toolsnodraw to the sides of the hull that nobody sees.

Why does my empty room still have several visleafs?

Because VBSP additionally cuts along a fixed grid: every 1024 units on the X and Y axes, according to the SDK 2013 source. The empty test room of 2048 by 2048 units consisted of four visleafs, and all four portals lay on the lines at 1024 units.