Mapping et Hammer

Areaportals, hints et occluders : quel outil résout quel problème

Areaportals, brushes hint/skip et occluders comparés : fonctionnement de chaque outil, coût, quand le placer et comment vérifier le résultat en jeu.

Les hint brushes, les areaportals et les occluders résolvent trois problèmes de visibilité différents. Un hint modifie le découpage des visleafs à la compilation et ne coûte rien en jeu. À l’exécution, un areaportal restreint la vue à une ouverture ou coupe entièrement la zone située derrière. À l’exécution également, un occluder ne masque que les modèles situés entièrement derrière une surface.

Trois outils, deux moments

VBSP découpe l’intérieur en visleafs, et VVIS calcule pour chaque leaf quels autres leafs pourraient être visibles depuis celui-ci (le PVS). Les bases sont expliquées dans optimiser les performances d’une map GMod et VBSP, VVIS et VRAD expliqués. Les trois outils interviennent à des endroits différents :

  • Hint et skip agissent pendant la compilation. Tu décides où VBSP découpe les leafs, ce qui change le résultat de VVIS.
  • Les areaportals divisent la map en areas pendant la compilation, mais ne décident qu’en jeu de ce qui est dessiné.
  • Les occluders travaillent exclusivement en jeu.

VVIS ne tient pas compte des areaportals : dans notre map de test, deux pièces se trouvaient toujours dans le PVS l’une de l’autre malgré des portals correctement placés. En jeu, le moteur prend donc d’abord le PVS, le rogne au niveau des areaportals et teste enfin les modèles contre les occluders.

Hint et skip : contrôler le découpage des leafs

Un hint brush est un world brush dont la face de coupe porte tools/toolshint et toutes les autres faces tools/toolsskip. VBSP choisit ses plans de coupe parmi les faces des brushes. Dans le code de VBSP du Source SDK 2013, les faces skip ne sont jamais choisies, et un plan qui traverserait une face hint est évité, sauf si ce plan est lui-même un hint.

L’exemple classique est un couloir qui tourne à angle droit :

  1. Sans hint, VBSP coupe le long de l’un des deux murs intérieurs. Il en résulte deux leafs qui partagent un portal. Depuis le bout d’un bras, le moteur dessine aussi le bout de l’autre.
  2. Place un brush en forme de coin dans l’angle. Sa face hint coupe l’angle extérieur : elle va à 45 degrés d’un mur extérieur à l’autre et touche exactement l’arête intérieure de l’angle.
  3. Le hint détache de l’angle un morceau triangulaire, et chaque bras garde son propre leaf. Les leafs des deux bras ne se touchent plus qu’à l’arête intérieure et ne partagent plus de portal.

Dans notre test avec les compilateurs de GMod, le nombre est ainsi passé de 2 leafs et 1 portal à 4 leafs et 3 portals, parce que VBSP a encore divisé le triangle de l’angle le long d’un mur intérieur. Les deux bouts de bras ne se trouvaient plus dans le PVS l’un de l’autre. Dans l’angle lui-même, tu vois toujours les deux bras.

Chaque coupe de hint crée des leafs et des portals que VVIS doit calculer. Plus d’infos dans VVIS prend une éternité.

Areaportals : rogner et fermer les ouvertures

Un func_areaportal est un brush unique en tools/toolsareaportal qui remplit entièrement une ouverture.

  • Ouvert : Le moteur resserre la vue sur la découpe de l’ouverture. Les leafs situés en dehors sont ignorés, et chaque entité de la zone située derrière est testée contre cette découpe à l’aide de sa bounding box.
  • Fermé : La zone située derrière n’est pas dessinée du tout, sauf si un autre portal ouvert y mène.

La règle la plus importante : les deux côtés d’un portal doivent se trouver dans des areas différentes. Toute liaison entre deux areas doit donc être fermée par un portal ou par des world brushes. func_detail, les displacements, les entités brush et les props n’assurent pas l’étanchéité. Plus d’infos dans func_detail ou world brush.

Pour les portes, saisis le nom de la porte sous « Name of Linked Door » dans le portal et règle « Initial State » selon l’état de départ de la porte. Dans le code du Source SDK 2013, func_door, func_door_rotating et prop_door_rotating ouvrent chaque func_areaportal qui les désigne comme porte liée dès que la porte commence à s’ouvrir, et ne le referment qu’une fois la porte complètement fermée. D’après le wiki de Valve, donne au brush du portal une épaisseur inférieure à celle de la porte, pour que la porte fermée soit encore dessinée.

func_areaportalwindow se ferme en fonction de la distance et non d’une porte. Entre « Fade Start Distance » (128 par défaut) et « Fade End Distance » (512 par défaut), il fait apparaître en fondu l’entité brush saisie sous « Rendered Window », puis coupe la zone. Il ne peut pas être lié à une porte : il n’a pas de champ pour cela, et le code des portes dans le SDK ne cherche que des func_areaportal.

Trouver un leak d’areaportal

Si un portal touche la même area des deux côtés, VBSP le signale ainsi :

Processing areas...Wrote mymap.lin
Areaportal leak ! File: mymap.lin
Brush 88: areaportal brush doesn't touch two areas

VBSP ne s’interrompt pas à cet endroit. Dans notre test avec les compilateurs de GMod, il a quand même écrit le BSP et le fichier de portals, et VVIS est allé jusqu’au bout sans erreur. Le BSP final ne contenait toutefois qu’une seule area et aucune donnée d’areaportal, les deux pièces se trouvaient donc dans la même area. Nous n’avons pas testé comment le jeu traite une telle map. Comme rien ne s’arrête, le message passe facilement inaperçu. Plus d’infos dans lire le compile log.

  1. Charge le fichier .lin dans Hammer via Map > Load Pointfile. Dans notre test, la ligne menait d’un côté du portal à l’autre en passant par la liaison ouverte.
  2. Si tu ne sais pas de quel portal il s’agit, saute à l’ID de brush indiqué dans le message avec View > Go to Brush Number.
  3. Suis la ligne et cherche le trou : un deuxième passage sans portal, un mur en func_detail ou en displacements, ou un brush de portal qui ne remplit pas entièrement l’ouverture.

func_occluder : masquer des modèles derrière une surface

Un func_occluder ne découpe aucun leaf, n’a rien à rendre étanche et peut se tenir librement dans l’espace. À chaque image, le moteur vérifie si la bounding box d’un modèle se trouve entièrement derrière la surface occultante et, si c’est le cas, ne le dessine pas. Seuls les modèles sont testés, c’est-à-dire les props, les NPC et les joueurs. Un occluder ne masque ni les world brushes ni les displacements, et le code client du Source SDK 2013 exclut les entités brush du test.

Tu le construis sous forme de brush à l’intérieur de quelque chose d’opaque, par exemple un mur en func_detail, une colline en displacements ou un bâtiment fait de props. Les faces occultantes reçoivent tools/toolsoccluder, toutes les autres tools/toolsnodraw. Il n’agit que depuis la direction d’où tu regardes une face d’occluder.

D’après le wiki de Valve, les occluders coûtent plus cher par objet que les areaportals ouverts. Ils ne valent donc le coup que lorsqu’une grande surface cache beaucoup de modèles.

Comparatif : quel outil pour quel usage

OutilMasque la géométrie du worldMasque les propsCoût à la compilationCoût à l’exécutionUsage typique
Hint et skipoui, des leafs entiersoui, avec le leafplus de leafs et de portals pour VVISaucunangles dans les couloirs et les passages
Areaportaloui, en dehors de la découpe, toute la zone quand il est ferméoui, un par un via la bounding boxfaible, un leaf supplémentaire par portalpour chaque portal ouvert visibleportes, fenêtres, entrées de bâtiments
Occludernonoui, s’ils sont entièrement cachésaucunpour chaque occluder et chaque modèle testéobstacles visuels isolés en terrain ouvert

Il en découle l’ordre à suivre : d’abord des world brushes pour bloquer la vue, puis des hints, puis des areaportals aux goulets d’étranglement avec beaucoup de contenu derrière, et des occluders uniquement là où aucun mur ne peut assurer l’étanchéité.

Vérifier en jeu

Teste avec un VVIS entièrement calculé. Les commandes suivantes existent dans le moteur de GMod. Les cinq premières y sont marquées comme cheats et nécessitent sv_cheats 1, r_occlusion non :

mat_wireframe 1
mat_leafvis 1
r_lockpvs 1
r_DrawPortals 1
r_portalsopenall 1
r_occlusion 0
  • mat_wireframe 1 dessine en fil de fer tout ce qui est rendu, même derrière les murs.
  • mat_leafvis 1 montre le leaf dans lequel se trouve la caméra, et r_lockpvs 1 fige le PVS pour que tu puisses te déplacer en volant. Sers-t’en pour contrôler les hints.
  • r_DrawPortals 1 trace le contour des areaportals, et r_portalsopenall 1 force l’ouverture de tous les portals. Si le fil de fer ne change pas quand tu actives et désactives la commande, le portal n’économise rien à cet endroit.
  • r_occlusion 0 désactive le système d’occlusion à titre de comparaison.

Tu peux coller le compile log dans le Map Scanner, qui détecte les causes racines et les erreurs en cascade dans les logs de VBSP, VVIS et VRAD.

Questions fréquentes

Puis-je contrôler un areaportal avec un trigger ?

Oui. func_areaportal possède les inputs Open, Close et Toggle. Mais le portal n’a qu’un seul état pour tous les joueurs. Pour le multijoueur, le wiki de Valve recommande avant tout des portals toujours ouverts, ensuite des portals sur les portes, et en dernier ceux contrôlés par trigger.

À partir de combien d’areaportals y en a-t-il trop ?

Il n’y a pas de nombre fixe. Chaque portal ouvert visible coûte du temps de calcul, et s’il masque trop peu, la scène est plus rapide sans le portal. Chaque areaportal est en outre une entité et compte dans la limite d’edicts.

Pourquoi la pièce derrière une porte ou une fenêtre disparaît-elle ?

C’est qu’un portal est fermé alors que tu peux voir à travers. Les causes typiques sont un portal dont « Initial State » est sur « Closed » et qu’aucune porte ni aucun input n’ouvre jamais, une porte liée dotée d’une vitre ou un func_areaportalwindow dont la « Fade End Distance » est trop courte.