Mapping y Hammer

Areaportals, hints y occluders: qué problema resuelve cada uno

Areaportals, brushes hint/skip y occluders comparados: cómo funciona cada herramienta, qué cuesta, cuándo colocarla y cómo comprobar el resultado en el juego.

Los hint brushes, los areaportals y los occluders resuelven tres problemas de visibilidad distintos. Un hint cambia cómo se cortan los visleafs al compilar y no cuesta nada en el juego. Un areaportal recorta la vista a una abertura en tiempo de ejecución o cierra por completo la zona que hay detrás. Un occluder, en tiempo de ejecución, oculta solo los modelos que quedan completamente detrás de una superficie.

Tres herramientas, dos momentos

VBSP divide el interior en visleafs, y VVIS calcula qué otros leafs podrían verse desde cada uno (el PVS). Lo básico se explica en optimizar el rendimiento de un mapa de GMod y en VBSP, VVIS y VRAD explicados. Las tres herramientas intervienen en puntos distintos:

  • Hint y skip actúan durante la compilación. Tú decides dónde corta VBSP los leafs, y con ello cambias el resultado de VVIS.
  • Los areaportals dividen el mapa en áreas durante la compilación, pero no deciden hasta el juego qué se dibuja.
  • Los occluders trabajan exclusivamente en el juego.

VVIS no tiene en cuenta los areaportals: en nuestro mapa de prueba, dos salas seguían estando cada una en el PVS de la otra a pesar de tener los portales bien colocados. Así que, en el juego, el motor toma primero el PVS, lo recorta en los areaportals y por último comprueba los modelos contra los occluders.

Hint y skip: controlar los cortes de los leafs

Un hint brush es un world brush cuya cara de corte lleva tools/toolshint y todas las demás caras tools/toolsskip. VBSP elige sus planos de corte entre las caras de los brushes. En el código de VBSP del Source SDK 2013, las caras skip no se eligen nunca, y un plano que cortaría una cara hint se evita, salvo que ese plano sea a su vez un hint.

El ejemplo clásico es un pasillo que gira en ángulo recto:

  1. Sin hint, VBSP corta a lo largo de una de las dos paredes interiores. El resultado son dos leafs que comparten un portal. Desde el final de un tramo, el motor dibuja también el final del otro.
  2. Coloca un brush en forma de cuña en la esquina. Su cara hint recorta la esquina exterior: va a 45 grados de pared exterior a pared exterior y toca justo la arista interior de la esquina.
  3. El hint separa de la esquina un trozo triangular, y cada tramo conserva un leaf propio. Los leafs de los dos tramos solo se tocan en la arista interior y ya no comparten ningún portal.

En nuestra prueba con los compiladores de GMod, esto hizo que la cuenta subiera de 2 leafs y 1 portal a 4 leafs y 3 portales, porque VBSP volvió a dividir el triángulo de la esquina a lo largo de una pared interior. Los extremos de los dos tramos ya no estaban cada uno en el PVS del otro. Dentro de la propia esquina sigues viendo los dos tramos.

Cada corte de un hint crea leafs y portales que VVIS tiene que calcular. Más sobre esto en VVIS tarda una eternidad.

Areaportals: recortar y cerrar aberturas

Un func_areaportal es un único brush con tools/toolsareaportal que rellena por completo una abertura.

  • Abierto: El motor estrecha la vista al recorte de la abertura. Los leafs que quedan fuera se omiten, y cada entity de la zona de detrás se comprueba contra ese recorte mediante su bounding box.
  • Cerrado: La zona de detrás no se dibuja en absoluto, salvo que otro portal abierto lleve a ella.

La regla más importante: los dos lados de un portal tienen que estar en áreas distintas. Por eso, toda conexión entre dos áreas tiene que estar cerrada con un portal o con world brushes. func_detail, los displacements, las brush entities y los props no sellan. Más sobre esto en func_detail o world brush.

Para las puertas, escribe el nombre de la puerta en «Name of Linked Door» dentro del portal y ajusta «Initial State» según cómo empiece la puerta. En el código del Source SDK 2013, func_door, func_door_rotating y prop_door_rotating abren todo func_areaportal que las nombre como puerta vinculada en cuanto la puerta empieza a abrirse, y solo lo cierran cuando la puerta está cerrada del todo. Según la wiki de Valve, haz el brush del portal más fino que la puerta para que la puerta cerrada se siga dibujando.

func_areaportalwindow se cierra por distancia en lugar de por una puerta. Entre «Fade Start Distance» (128 por defecto) y «Fade End Distance» (512 por defecto) hace aparecer gradualmente la brush entity indicada en «Rendered Window» y después cierra la zona. No se puede vincular a una puerta: no tiene ningún campo para ello, y el código de las puertas del SDK solo busca func_areaportal.

Encontrar un leak de areaportal

Si un portal toca la misma área por ambos lados, VBSP lo avisa así:

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

VBSP no se detiene en este punto. En nuestra prueba con los compiladores de GMod escribió igualmente el BSP y el archivo de portales, y VVIS terminó sin errores. Sin embargo, el BSP final contenía una sola área y ningún dato de areaportals, de modo que las dos salas quedaban en la misma área. No hemos probado cómo trata el juego un mapa así. Como nada se detiene, es fácil pasar por alto el mensaje. Más sobre esto en leer el compile log.

  1. Carga el archivo .lin en Hammer con Map > Load Pointfile. En nuestra prueba, la línea iba de un lado del portal al otro pasando por la conexión abierta.
  2. Si no sabes a qué portal se refiere, salta al ID de brush del mensaje con View > Go to Brush Number.
  3. Sigue la línea y busca el hueco: un segundo paso sin portal, una pared hecha de func_detail o de displacements, o un brush de portal que no rellena la abertura por completo.

func_occluder: ocultar modelos detrás de una superficie

Un func_occluder no corta leafs, no tiene que sellar nada y puede estar suelto en el espacio. En cada fotograma, el motor comprueba si la bounding box de un modelo queda completamente detrás de la superficie que oculta y, si es así, no lo dibuja. Solo se comprueban modelos, es decir, props, NPC y jugadores. Un occluder no oculta world brushes ni displacements, y el código del cliente del Source SDK 2013 deja las brush entities fuera de la comprobación.

Lo construyes como un brush dentro de algo opaco, por ejemplo una pared hecha de func_detail, una colina de displacements o un edificio hecho de props. Las caras que ocultan llevan tools/toolsoccluder, y todas las demás tools/toolsnodraw. Solo funciona desde la dirección en la que miras hacia una cara de occluder.

Según la wiki de Valve, los occluders son más caros por objeto que los areaportals abiertos. Por eso solo compensan cuando una superficie grande tapa muchos modelos.

Comparación: qué herramienta para qué tarea

HerramientaOculta geometría del mundoOculta propsCoste de compilaciónCoste en ejecuciónUso típico
Hint y skipsí, leafs enterossí, junto con el leafmás leafs y portales para VVISningunoesquinas en pasillos y pasos
Areaportalsí, fuera del recorte; cerrado, toda la zonasí, uno a uno mediante la bounding boxbajo, un leaf adicional por portalpor cada portal abierto visiblepuertas, ventanas, entradas de edificios
Occludernosí, si quedan completamente tapadosningunopor cada occluder y cada modelo comprobadoelementos sueltos que tapan la vista en terreno abierto

De ahí sale el orden: primero world brushes que tapen la vista, después hints, después areaportals en los pasos estrechos con mucho contenido detrás, y occluders solo donde ninguna pared puede sellar.

Comprobar en el juego

Prueba con un VVIS calculado por completo. Los comandos siguientes existen en el motor de GMod. Los cinco primeros están ahí protegidos por cheats y necesitan sv_cheats 1; r_occlusion, no:

mat_wireframe 1
mat_leafvis 1
r_lockpvs 1
r_DrawPortals 1
r_portalsopenall 1
r_occlusion 0
  • mat_wireframe 1 dibuja en modo alambre todo lo que se renderiza, incluso detrás de las paredes.
  • mat_leafvis 1 muestra el leaf en el que está la cámara, y r_lockpvs 1 congela el PVS para que puedas moverte volando. Úsalos para comprobar los hints.
  • r_DrawPortals 1 marca el contorno de los areaportals, y r_portalsopenall 1 fuerza la apertura de todos los portales. Si el modo alambre no cambia al activarlo y desactivarlo, el portal no ahorra nada en ese punto.
  • r_occlusion 0 desactiva el sistema de oclusión para comparar.

Puedes pegar el compile log en el Map Scanner, que detecta causas raíz y errores derivados en los logs de VBSP, VVIS y VRAD.

Preguntas frecuentes

¿Puedo controlar un areaportal con un trigger?

Sí. func_areaportal tiene los inputs Open, Close y Toggle. Eso sí, el portal solo tiene un estado para todos los jugadores. Para multijugador, la wiki de Valve recomienda sobre todo portales siempre abiertos, después portales en puertas y, en último lugar, los controlados por trigger.

¿Cuántos areaportals son demasiados?

No hay un número fijo. Cada portal abierto visible cuesta tiempo de cálculo, y si oculta demasiado poco, la escena va más rápida sin el portal. Además, cada areaportal es una entity y cuenta para el límite de edicts.

¿Por qué desaparece la sala que hay detrás de una puerta o una ventana?

Entonces hay un portal cerrado aunque puedas ver a través de él. Las causas típicas son un portal con «Initial State» en «Closed» que ninguna puerta ni ningún input abre nunca, una puerta vinculada que tiene un cristal o un func_areaportalwindow con una «Fade End Distance» demasiado corta.