Mapping y Hammer

Optimizar un mapa de GMod: más FPS gracias a la visibilidad

Optimizar un mapa de GMod: entiende los visleafs y el PVS, usa func_detail, hint/skip, areaportals, occluders y distancias de fade, y luego mide en el juego.

Un mapa de GMod va fluido cuando el motor tiene que dibujar lo menos posible en cada fotograma. Donde más puedes ganar es en la visibilidad: world brushes sencillos que tapen la vista, detalles como func_detail, areaportals en los pasos estrechos y distancias de fade para los props. Después mides en el juego en lugar de suponer.

Cómo decide el motor qué dibujar

Durante la compilación, VBSP divide el interior del mapa en visleafs, que son trozos convexos de espacio. Después, VVIS calcula para cada leaf qué otros leafs se podrían ver desde él. Esa lista se llama PVS (Potentially Visible Set).

En el juego, el motor determina en qué leaf está la cámara y solo dibuja lo que queda en los leafs de ese PVS y dentro del campo de visión. Importan dos consecuencias:

  • La visibilidad se aplica por leaf, no por posición. Si desde cualquier punto de un leaf se ve otro, todo el contenido de ese otro leaf cuenta como visible.
  • Solo los world brushes bloquean la visibilidad. Las brush entities, func_detail, los displacements y los props no lo hacen, aunque no puedas ver a través de ellos.

Por eso una buena optimización empieza por el layout: las salas, las esquinas y los pasos desalineados separan unas zonas de otras. Ninguna herramienta puede salvar después una única sala enorme.

func_detail: saca los detalles del cálculo de visibilidad

Cada world brush corta leafs. Muchos brushes pequeños crean muchos leafs y portales pequeños, lo que alarga la compilación y ensucia la visibilidad. Selecciona todo lo que no separe zonas y conviértelo en func_detail con Ctrl+T: pilares, escalones, marcos, molduras, muebles hechos con brushes.

Como regla general, las paredes, los suelos y los techos que cierran las salas siguen siendo world brushes. El resto pasa a ser detalle. Ten en cuenta que func_detail no sella el mapa. Una pared exterior hecha con brushes de detalle provoca un leak. Si tu compilación se queda atascada en VVIS, consulta VVIS tarda una eternidad.

Hint y skip: corta los leafs a propósito

A veces VBSP corta mal, por ejemplo en la esquina de un pasillo, de modo que un leaf dobla la esquina y ve demasiado. Con un hint brush defines tú mismo el plano de corte:

  1. Crea un brush y aplica tools/toolsskip a todas las caras.
  2. Aplica tools/toolshint justo a la cara por la que debe pasar el corte.
  3. Coloca el brush de forma que la cara hint atraviese la esquina, por ejemplo, en diagonal.

Usa los hints con moderación. Cada corte extra crea nuevos leafs y portales. Puedes comprobar si un hint ayuda en Hammer con Map > Load Portal File, que muestra los límites de los leafs en el editor.

Areaportals y occluders

Un func_areaportal es un brush fino con la textura tools/toolsareaportal que rellena por completo una abertura, como una puerta o una ventana. Actúa de dos formas:

  • Abierto: El motor solo dibuja la parte de la zona de detrás que realmente se ve a través de la abertura. Esto afecta también a los props y a otras entities.
  • Cerrado: La zona de detrás no se dibuja en absoluto. Puedes vincular el portal a una puerta para que se abra y se cierre con ella.

Los areaportals dividen el mapa en áreas. Todas las conexiones entre dos áreas tienen que estar cerradas con portales; de lo contrario, la compilación avisa de un leak en el areaportal. Para las ventanas por las que solo se mira de cerca existe func_areaportalwindow, que oculta la zona a partir de cierta distancia.

En terreno abierto, donde no hay paredes que separen nada, ayuda func_occluder. Oculta los modelos que quedan completamente detrás de él, pero no la geometría de brushes. Las caras que ocultan llevan tools/toolsoccluder, y todas las demás tools/toolsnodraw. Los occluders cuestan tiempo de cálculo por sí mismos y solo compensan cuando una superficie grande tapa muchos props.

Props, lightmaps y caras invisibles

  • Distancias de fade: Los props tienen las propiedades "Start Fade Dist" y "End Fade Dist" (en prop_static se llaman "Start Fade Dist/Pixels" y "End Fade Dist/Pixels"). Los objetos pequeños, como botellas o carteles, no hace falta dibujarlos desde lejos. Cuanto más pequeño es el prop, antes puede desaparecer.
  • El tipo de prop correcto: Todo lo que nunca se mueve pasa a ser un prop_static. Los props con físicas suponen una carga extra para las físicas y la red en un servidor lleno.
  • Escala del lightmap: El valor por defecto es 16. En superficies grandes e iluminadas de forma uniforme, valores como 32 o 64 ahorran memoria y tamaño de archivo. Usa valores más pequeños solo donde las sombras tengan que ser nítidas. Más sobre esto en la guía de iluminación de Source Engine.
  • Nodraw: Las caras que nadie va a ver nunca llevan tools/toolsnodraw. Esto vale para las caras traseras, las caras de debajo de los displacements y los puntos tapados por props. Las caras que dan al vacío fuera del mapa las elimina VBSP automáticamente.
  • Escenario lejano: El paisaje alejado va en una skybox 3D, no en el mapa como geometría real.

Medir en el juego en lugar de suponer

Prueba con una compilación completa. Con VVIS en modo rápido el motor dibuja más de lo necesario, así que las cifras dicen poco. En GMod, mat_wireframe, mat_leafvis, r_DrawPortals y r_lockpvs están protegidos por cheats y requieren sv_cheats 1; cl_showfps y +showbudget, no.

ComandoQué muestra
cl_showfps 1Tasa de fotogramas
+showbudgetCómo se reparte el tiempo por fotograma, por ejemplo entre mundo, props y físicas. -showbudget vuelve a ocultar el panel
mat_wireframe 1Todo lo que se dibuja, en modo alambre, incluso detrás de las paredes. Así ves lo que el motor renderiza a pesar de una pared
mat_leafvis 1Contorno del visleaf en el que está la cámara
r_DrawPortals 1Contornos de los areaportals
r_lockpvs 1Congela la visibilidad para que puedas moverte y comprobar qué se dibujaba desde la posición anterior

Trabaja de forma sistemática: primero localiza los puntos con la tasa de fotogramas más baja, míralos con mat_wireframe 1 para ver qué se dibuja sin necesidad, y solo entonces coloca hints, areaportals o distancias de fade con un objetivo concreto. Si por el camino el compile log muestra advertencias que no sabes interpretar, el Map Scanner sugiere causas y soluciones para los mensajes conocidos.

Preguntas frecuentes

¿De verdad func_detail da más FPS?

De forma directa, func_detail sobre todo acorta la compilación. En el juego la ganancia es menor: el mapa queda con menos leafs y las caras de los world brushes se cortan en menos trozos. Eso sí, pasarse con el detalle perjudica: todo lo que está marcado como func_detail deja de bloquear la visibilidad.

¿Por qué mi mapa va lento aunque VVIS se haya ejecutado?

Muchas veces el layout es demasiado abierto, de modo que casi todo se ve desde casi cualquier sitio. Otras causas son muchísimos props sin distancias de fade, agua costosa o luces dinámicas. +showbudget muestra qué categoría se come el tiempo.

¿Los displacements bloquean la visibilidad?

No. Los displacements ni sellan el mapa ni bloquean la visibilidad. Pon world brushes sencillos con tools/toolsnodraw debajo de las colinas y detrás de las paredes de roca cuando detrás empiece otra zona.

¿Dónde tienen sentido los areaportals?

En los pasos estrechos entre zonas con mucho contenido, es decir, puertas, ventanas y pasadizos. En un espacio amplio y abierto sirven de poco, porque de todos modos casi todo se ve a través de la abertura.