Reducción de polígonos en pantalla

De LiTHiUM

Técnicas de Optimización #1 (GoldSrc)
Requisitos: Se supone un manejo fluido del WorldCraft/Hammer en general y mucha paciencia... ;)

Tabla de contenidos

Introducción

A continuación voy a explicar varios sistemas sencillos para poder evitar uno de los problemas más típicos de todo diseñador de mapas: la cantidad de polígonos visibles. En este tutorial se supone que el lector ya sabe manejar bien el WordCraft y domina la creación de mapas.

Todos los sistemas y métodos que incluyo en este texto no son invento ni descubrimiento mío, sino que han sido extraídos de multitud de páginas web y foros, y yo sólo me limito a recopilarlos y transmitirlos para que sirva de ayuda a otros... ;)

Es común que tras realizar nuestro mapa, el espectador vea zonas que se oscurecen, se relentize el juego o desaparezcan objetos según mira a un lado o a otro. Esto sucede porque el motor 3D del Half-Life no puede representar la gran cantidad de polígonos texturizados, luces y entidades que requiere el espectador.

Para entender como podemos evitar estos problemas, es necesario que conozcamos cómo funciona el motor gráfico del Half-Life y qué pasa al compilar y al procesar. Antes de continuar me gustaría aclarar que la mejor manera de mejorar nuestros mapas es usar las últimas versiones de los programas de compilación (hlbsp, hlvis, hlrad...), y para ello aconsejo que os descarguéis las ZHLT de la zona de Herramientas. Para poder ver todo lo que a continuación se dirá y poder seguir las explicaciones debéis arrancar el Half-Life con los parámetros -dev -console

Esto nos permitirá activar la consola, enterarnos de lo que ve el ordenador...

El ordenador no ve el mapa como nosotros, al igual que en la película Matrix él sólo ve códigos, así su visión es más amplia que la nuestra, de modo que cuando nosotros sólo vemos un pasillo, él ve las paredes como caras cubiertas de texturas, las entidades y lo que hay tras ellas y es incluso capaz de rodear objetos y doblar un poco las esquinas (esto último lo determina el módulo hlvis). Así que para hacer buenos mapas debemos intetntar ver los códigos como el los ve. De modo que una puerta (que es una entidad) no bloquea la visión, y es igual que si no estuviera, todos los polígonos que hay detrás se suman a los que tenemos alrededor (vista periférica) para ser calculados y traducidos a nuestro modo de ver. Y cuanto más vea él, más lento irá el juego. Si es extremadamente lento, en teoría dejará de ver cosas, empezando por las entidades, luego el cielo y terminando con zonas de atrás hacia adelante y en los bordes.

A continuación vamos a ver varios métodos para que los polígonos en pantalla por segundo (polys/sec) no se disparen y nuestro mapas sea jugable...


Divisiones forzosas

Concepto

Cuando creamos un sólido simple y lo texturizamos (como un cubo para representar una caja de madera), nosotros podemos pensar que es un objeto simple de representar, con sólo seis caras, de las que como mucho veremos tres de ellas, sin embargo el ordenador no lo ve así. En el motor 3D del HL cada textura se divide siempre en 2 polígonos, ya que el único polígono que sabe representar el motor es el de 3 puntos (triángulo).

Si creamos un cubo (para representar una pared) y le aplicamos una textura de menor tamaño que él, esta se pega en mosaico, rellenando toda la superficie de cada cara. Así la cara es en realidad varias texturas pegadas. Entonces en el proceso de compilación, la cara del polígono original quedará dividida en tantos polígonos como texturas formen el mosaico multiplicado por 2...

Esto es, si creamos una pared de 256 (alto) x256 (ancho) x32 (profundo), y en cada cara de tamaño 256u aplicamos una textura de 128x128, para rellenar el muro se usarán 4 texturas, con lo que pasaremos de tener 2 polígonos (si fuera una textura de 256x256) a tener 8 ([128x128x2]x2=[256x256]). El tamaño que toman las divisiones por textura varía según el de la textura que apliquemos.

Ejemplo

Crea una superficie cualquiera y aplícale una textura (a ser posible que la textura sea mas pequeña que cada cara del sólido). Luego compila el mapa. Mientras lo juegas, baja la consola y teclea r_drawflat 1 para ver las divisiones creadas...

Recuerda que el comando r_drawflat solo puede ser usado en modo SP (single player) y con la tarjeta configurada para usar el modo OpenGL.

Lo que ves son las divisiones en polígonos de los objetos con sus texturas, cada una en un color plano. Recuerda que luego cada cuadrado/rectángulo se dividirá en 2 triángulos. Este es un buen sistema para ver dónde el número de divisiones es excesivo. En un segundo veremos el por qué y cómo solucionarlo...


Fíjate en las divisiones de colores... O_o
Aumentar
Fíjate en las divisiones de colores... O_o


Solución

De modo que una primera optimización sería aplicar texturas lo más grandes posibles. Esto lo conseguiremos con las casillas de "Escale" en el menú de aplicación de texturas. Por supuesto, no podemos hacer esto siempre pues empeoraría el aspecto de nuestro mapa, pero ayuda a veces usarlas a un tamaño lo mas grande posible. De esta manera mejoramos la velocidad en juego y aceleramos la compilación.

Recuerda que para sacar el símbolo de guión bajo ( _ ) en la consola, tienes que teclear Mayús+?


Cuidado con el "Carve"

Concepto

Las divisiones se forman de manera natural distribuyéndose ordenadamente en una cara plana, sin embargo las interrupciones y encuentros con otros sólidos van distorsionando la homogeneidad y la hacen compleja y enrevesada, hasta que la cantidad de divisiones para un muro aparentemente sencillo se convierte en una pesadilla para el compilador y finalmente para el procesador.

Ejemplo

Si a la pared que hemos creado le hacemos un hueco rectangular sencillo ya habremos distorsionado la distribución de las divisiones, forzándolas a coincidir con el hueco y a adaptarse a él. Así que además de tener más divisiones, vemos además las jambas del hueco (los bordes) y lo que hay detrás, de esta manera multiplicamos casi por tres lo que tiene que enseñarnos...


Al cortar una pared...
Aumentar
Al cortar una pared...


Solución

Si tienes que hacer una ventana o abrir un hueco tienes que intentar que:

  • El hueco sea sencillo, cuantas menos caras mejor. Mejor rectangular (4 caras) que pseudo-circular (8 o mas caras). Y si quieres hacer un hueco más complejo, mejor hazlo a mano, creando las menos divisiones posibles, creando ángulos normales (30, 45, 60, 90,...).
  • El tamaño del hueco concuerde con el de la textura de la pared. La pared se divide cada vez que una textura acaba, con lo que si la pared tiene texturas de 32pix, calcula para hacer que tu ventana de 32u esté a los 32, 64, 128u de la pared, o si no crearás 4 polys extras donde podría haber tan sólo 2.
  • Lo que veamos desde uno u otro lado, no sea un gran espacio lleno de caras y polígonos (ventanas en lo alto de edificios o dando a una gran extensión de mapa, o a sitios complejos como reactores en movimiento).
  • Los cristales son entidades, con lo que no bloquean la visión y se ve lo de detrás. Ademas los cálculos de la fractura de los cristales en trozos al dispararlos cargan un poco al procesador. No abuses de ellos.
  • Si lo que necesitas es sólo luz, haz ventanas altas a las que el jugador no pueda llegar para ver por ellas.
  • Si quieres reducir un poco las caras, haz que las jambas (caras que delimitan el hueco) sean abocinadas (abriéndose) hacia el lado más complejo, como las saeteras de los castillos. Así al menos no ves a éstas.
  • Puedes poner objetos delante de los huecos que oculten la visión (pilares, arboles, monolitos, burladeros, etc).


Escaleras

Concepto

También se altera la distribución de las divisiones allí donde los polígonos se tocan, casi como si el sólido excavara allí donde se unen.

Ejemplo

Crea una escalera sencilla pegada a una pared, compila y juega el mapa para ver las divisiones del mapa. Observa cómo las divisiones de la pared se dividen en franjas verticales, de anchura igual a la del escalón. El resultado es que estarás viendo una pared dividida en partes (tantas como escalones), las caras de los escalones (tres para cada uno) y el suelo también partido por la anchura de la escalera.


Observa las divisiones de la pared, producidas por la escalera...
Aumentar
Observa las divisiones de la pared, producidas por la escalera...


Solución

La solución más sencilla y rápida es crear una rampa en vez de una escalera, y aunque esto lo han aplicado incluso los autores del juego, para mi gusto le resta calidad al conjunto, disminuyendo el realismo y la vistosidad. Recuerda que la escalera es el alma de una casa... :)


Aumentar


La solución recomendada es sencilla y fácil, basta con separar un pelín (lo mínimo que permite la menor de las cuadrículas es 1 unidad) la escalera de la pared y así evitamos la intersección. Esto también lo han empleado los mejores creadores, basta con fijarse en la escalera que comunica la planta superior con el río en del genial mapa "de_aztec":


Separación entre la escalera y la pared...
Aumentar
Separación entre la escalera y la pared...


Además podemos añadir un pasamanos en el lado exterior, así conseguiremos ocultar todos los bordes de los escalones y las partes inferiores, así:


Aumentar


Columnas y tuberías

Concepto

Si los encuentros o intersecciones se producen con objetos más o menos curvos (más de seis lados), los resultados son devastadores. Esto suele pasar con los encuentros entre tuberías con muros o con pilares que van de suelo a techo, pasadizos abovedados y adornos circulares.

Ejemplo

Crea un pilar circular (entre 8 y 12 lados) que vaya de suelo a techo, prueba poniendo dos o tres iguales más o menos juntos. Compila y juegalo. Entonces observa las divisiones de piso y techo. Verás un resultado caótico en ambos. Es como una espiral de divisiones en los encuentros del pilar. Esto es porque las divisiones sólo pueden tener 3 o 4 lados, y esa es la única manera de resolver la intersección:


Observa los múltiples cortes en techo y suelo...
Aumentar
Observa los múltiples cortes en techo y suelo...


Solución

La más obvia es crear pilares cuadrados que no dan ningún problema. Si nos empeñamos en que sean pseudo-redondos podemos solucionar el problema del techo tal y como hicimos con la escalera, separándolo una cantidad de 1 unidad de éste. Es la mejor solución si los techos son altos, ya que es imposible apreciar la separación. Puedes ver un ejemplo de esto en la parte superior de las columnas de una de las zonas de bomba del maravilloso mapa "de_train".

No debemos repetir la operación con la base, ya que puede notarse, sobretodo con los efectos de luz. Lo mejor es crear una base que no cree interferencias con el suelo, esto se puede lograr con la siguiente operación:

  • Separa una poco el pilar del suelo.
  • Crea una base circular (igual que la columna o de unos cuantos lados más) para el pilar y colócala debajo, entre el pilar y el suelo, tocando a ambos.
  • Haz que la base pase a ser la entidad "func_wall", dejando los valores por defecto.

Cuando compiles y veas el mapa observarás que ya han desaparecido todas las intersecciones y los pilares quedan mucho mejor. Esto es por que ahora la base es una entidad, y no intersecciona con objetos sólidos. Esto también puedes usarlo para crear capiteles (en los encuentros techo-pilar), como transición entre dos polígonos circulares, e incluso para tapar el hueco que dejamos entre la escalera y la pared con otro pasamanos. Si no queremos basa podemos hacer una del mismo diámetro del pilar de modo que no se aprecie la diferencia entre ambos...


Vemos 3 tipos de basas...
Aumentar
Vemos 3 tipos de basas...


Ahora alguien se preguntará: ¿Por qué no hacemos todo el pilar una entidad "func_wall"?

Hay varias respuestas... una es que las entidades no proyectan sombra, con lo que quedaría poco realista. Otra es que, como ya dijimos antes, el ordenador ve a través de las entidades, de modo que ya no ocultan la vista. Otra pega es que si se ve muy apretado de memoria, lo primero que desaparecen son las entidades visibles. Como con todo lo bueno, conviene no abusar... ;)


Usar texturas inteligentemente

Concepto

Muchas veces habremos pensado en, por ejemplo, hacer un objeto detalladamente a base de polígonos, ya que no tenemos una textura que lo imite. ¿Por qué no usar sólidos para crear esos detalles que dan al mapa un aspecto precioso?... No, no, no... hay que tener mucho cuidado y evitar esto en la medida de lo posible.

Ejemplo

Imagina una canasta de baloncesto... ¿ya? ...Tienes el aro y luego el tablero con las líneas negras... Pues imagina que no tienes una textura para el tablero, y dices: "lo hago a mano con sólidos"... y te lias a hacer líneas negras, con lo que al final el resultado es este:


Tablero hecho con sólidos...¡argh!
Aumentar
Tablero hecho con sólidos...¡argh!


Solución

Para resolver esto necesitamos tan solo un par de cosas: el Photoshop (o el PaintShop Pro), el Wally... y un poco de imaginación y habilidad. Usaremos... por ejemplo el Photoshop para crear las texturas, y como siempre el Wally para crear a partir de esas texturas nuestro propio archivo WAD. Fíjate como queda el tablero con nuestra propia textura:


Tablero hecho con textura...¡yeah!
Aumentar
Tablero hecho con textura...¡yeah!


La diferencia puede ser de entre 20 y 100 polígonos lo que nos ahorramos en este caso, dependiendo del tamaño de las texturas y la complejidad del objeto... genial, ¿no?


Bloquear la visión

Concepto

Como nada es perfecto, el motor 3D de HL y de la mayoria de los juegos antiguos (del 98 o antes) tienen un pequeño problema a la hora de determinar que objetos vemos y cuales no: muchas veces el motor del juego dibuja cosas que se encuentran escondidas para nosotros, pero que según sus cálculos sí se procesan.

Para saber qué objetos representa el HL y cuales no, desde la actualización 1.1.0.4, podemos usar el comando gl_wireframe X, donde si X es 1 se representarán los poligonos que se ven en primer plano y si X es 2 se representaran todos los polígonos que el motor 3D del HL puede ver en ese preciso instante...

Al usar este comando veremos como aparece una línea blanca rodeando a cada polígono. Así podremos ver dónde se sobrecarga el mapa, y podremos optimizarlo...

El comando gl_wireframe solo puede ser usado en SP (single player) y con la tarjeta configurada para usar el modo OpenGL.

Ejemplo

Observa estas screenshots. Ambas son del mapa "cs_assault". La de la izquierda es la imagen del mapa bien diseñado con paredes cortando visión, la de la derecha es el mapa en el mismo punto sin ninguna pared cortando vision.



Como ves, en la imagen de la derecha se dibujan muchísimos mas poligonos de los que en realidad vemos en ese punto. Pasa exactamente lo mismo que en la imagen de la fase SP del HL de un poco mas arriba...

Solución

Este problema se puede solucionar de varias formas, por ejemplo:

  • La compilación final de tus mapas siempre ha de ser FULL VIS (tarda bastante mas, pero el mapa resultante está bastante optimizado).
  • Según los expertos, nunca se han de hacer los mapas a partir de un gran cubo. Primero haz tu diseño (edificios, calles, cloacas, etc.) y luego acopla el cielo pegado a las paredes mas altas. Además si quieres crear habitaciones dentro de una construcción, no uses "Carve", pues crearás multitud de divisiones innecesarias. Hazlo por partes: Cubo->Hollow->Unir pisos->Ver que caras se repiten->Desagrupar y Eliminar->Volver a agrupar.
  • No asignes un sólido a una entidad a no se que sea estrictamente necesario (puertas, para evitar intersecciones, etc.). Recuerda que el motor del HL ve a través de ellos.
  • Expertos (como DaveJ, autor del de_dust entre otros) recomiendan que no se abuse del "carve". Puede que el HL tenga problemas a la hora de representar algunas divisiones. Procura que coincidan los vértices del sólido con los puntos de la rejilla (grid).
  • Intenta que todas las construcciones lleguen al techo o cielo de tu mapa. Esto hará que los módulos VIS y RAD tarden bastante menos. Si es un mapa abierto o aparentemente abierto (fíjate el de_dust por ejemplo) haz que los tejados coincidan con el cielo, así:


Fíjate como el cielo (en verde) está pegado a las paredes...
Aumentar
Fíjate como el cielo (en verde) está pegado a las paredes...


Y ten en cuenta que el motor del HL es antiguo, asi que no te desesperes si aún siguiendo estos consejos siguen apareciendo mas poligonos de lo debido...


El rendimiento

Si quieres saber cuanto está viendo el ordenador exactamente bastará con que te fijes en el ángulo superior izquierdo. Al añadir los parámetros indicados al principio (-dev) para ejecutar un mapa ya va incluido el indicador que se activará cuando el número de caras exceda un mínimo.

Por encima de cierto número (según la CPU, en mi caso 1500) empieza a ocultar objetos...

r_speeds

También puedes saber de manera exacta la velocidad del proceso tecleando en la consola el famoso comando "r_speeds" y poniéndolo a 1. Te indicará la cantidad de polígonos totales, polígonos/segundo en pantalla y la velocidad de proceso en milisegundos. Fijate:


Números de una zona del nuevo de_dust3 de DaveJ...:o


  • El primer número son los fotogramas por segundo. Teóricamente el número mínimo para que el ojo humano no perciba saltos es 24. Normalmente este número ha de ser superado, ya que si nos da 24 en nuestro mapa vacío, cuando haya mas gente jugando (si es MP), o al poner los grunts y demas bichejos (si es SP), este número caerá seguramente. No debemos fiarnos demasiado de este parámetro, pues va un poco en función de la potencia de nuestro ordenador. Yo puedo obtener un valor pero alguien con un ordenador superior al mio puede obtener mas FPS...
  • El segundo es el número (en milisegundos) que el ordenador tarda en completar un ciclo del juego. Esta es la explicación de VALVe... No estoy muy seguro de este número, pero creo que debe ser el número en milisegundos que se tarda en preparar un fotograma. De todas maneras este número tampoco es muy relevante, pues también depende de la máquina de cada cual...
  • El tercer número es el importante. Es el número de sólidos (paredes, suelo, techo, etc.) que ves. Según VALVe no debe pasar de 450-500 en zonas donde pueda haber muchos tiros. Para el resto de las zonas podemos llegar hasta los 600. Si superamos los 700 el mapa se ralentizará un poco. Estos números son para que el mapa corra suave en la mayoría de los ordenadores. Piensa en que puede que tu tengas un Athlon1.2Ghz y una GeForce2Ultra, pero el resto de la gente seguramente NO... ;)
  • El cuarto número es el número de entidades que ves (entidades-poligono) como puertas, cristales, liquidos, trenes, plataformas, etc. Este número es mas o menos informativo.


Ahora vamos a ver la diferencia entre un buen mapa y otro que falla en una zona en la que se ve demasiado...

  • MAPA INJUGABLE: Aquí podemos ver como el número de poligonos que podemos ver es demasiado alto. En mi ordenador da una cifra de FPS demasiado baja. El mapa da tirones. Es prácticamente injugable:


Números de una zona de un mapa prácticamente injugable...:(


  • MAPA JUGABLE: Aquí podemos ver una cifra tomada de una zona del nuevo mapa de_dust3. Sin comentarios... :)


Números de una zona del nuevo de_dust3 de DaveJ...:)


Estos 4 números los da en modo OpenGL. En modo software da otros diferentes.


r_draworder

Otro comando con el que también podemos ver como actúa el motor del HL es este. Si lo tecleamos en la consola, veremos que en vez de dibujar la escena de atrás hacia delante lo hará al revés, con lo que veremos lo que realmente ve el ordenador (mas de lo que parece)... Fíjate:


Este comando sólo puede ser usado en modo SP (single player) y con la tarjeta configurada en modo software.


Uniones entre sólidos

Una buena forma de reducir los polígonos en pantalla es haciendo que las uniones entre los sólidos (esquinas, objetos con varias piezas, etc.) sean óptimas.

Para eso, antes de nada hay que ver cómo funciona realmente el módulo HLBSP. En el proceso de compilación, el HLBSP analiza cada sólido y lo divide en triángulos... ¿que por que?... :)

Los motores 3D y a las aceleradoras 3D están diseñados para mover triángulos, y cuando nos referimos a polígonos en el mundo de las 3D hablamos de triángulos, ya que es el polígono con menor número de vértices, y por esto es mas fácil y rápido de manejar.

Seguimos... el HLBSP coge nuestro mapa y lo desmenuza en triángulos. Si no hemos construído con cuidado el mapa dará un número de polígonos (triángulos) demasiado elevado y será injugable. Debemos de tener en cuenta las uniones entre sólidos, ademas de las texturas y su escalado, como vimos antes.

Entonces si hacemos en muestro mapa un pasillo normal, con las texturas a un tamaño normal, tenemos:


Construcción inicial...regular
Aumentar
Construcción inicial...regular


Al compilarlo y jugarlo vemos las divisiones (en polígonos de 4 lados):


Hay demasiados cortes en el suelo...:(
Aumentar
Hay demasiados cortes en el suelo...:(


Vemos como da multitud de divisiones. En este caso la mayoria de ellas se producen por haber aplicado a la textura del suelo un escalado de 0.5. Entonces ahora vamos a optimizar las uniones. Para esto podremos usar nuestras utilísimas herramientas de "Clipping Tool" (corte de polígonos) o "Vertex Manipulation" (manipulación de vértices), para dejar el pasillo con un aspecto como este:


Optimizando las uniones de las paredes...
Aumentar
Optimizando las uniones de las paredes...


Hemos conseguido que una intersección entre 3 vértices sea una de 2. Ahora al compilar y jugar el mapa (con el comando gl_wireframe 2 para ver las divisiones). En este segundo caso hemos dejado la textura del suelo en su tamaño original. Mira el resultado:


Mucho mejor...:D
Aumentar
Mucho mejor...:D


También podemos pensar... ¿por que no hacerlo a el suelo y techo también?...


Demasiados cortes...:(
Aumentar
Demasiados cortes...:(


La respuesta es no, ya que las divisiones, además de por polígonos se hacen por textura, y las texturas son cuadradas siempre con lo que cortará en cuadrado al acabar la textura y dejará un triángulo suelto extra...


Hacer esto en todo el mapa es una tarea laboriosa. Tenemos la opción de ir haciéndolo desde el principio (en las paredes de las zonas por las que vayamos a pasar, no en las que no vemos), o podemos hacerlo sólamente en las zonas que veamos que el mapa se ralentiza (zonas de gran actividad o mas abiertas). La elección es tuya... ;)


Despedida...

Como habrás visto, algunos comandos de control de poligonos necesitan que el mapa se juegue en modo SP. Esto lo hacen para evitar que la gente haga trampas en los juegos MP tipo Counter-Strike o TFC.

Entonces la solución es hacer nuestro mapa sin ninguna entidad especial del CS hasta el final, hasta que sepamos que nuestro mapa va fino. Así podremos probarlos mientras como mapas SP normales para el HL.

De momento nada mas... nosotros seguimos buscando nuevas técnicas de optimización...  ;)

Ciao!



Puntos 2º, 3º, 4º, 5º y 8º originales e imágenes Odin, finales de septiembre de 2000.
Añadido el 7º punto por [doomy]
Revisión general y ampliación, puntos 6º y 9º, e imágenes por vEK.
Gracias a Juancho por la idea del 6º punto
Herramientas personales