Rendering de Mapas de Quake 2 – Lightmaps

Este fin de semana estuve trabajando de a ratitos en el soporte para Lightmaps para el renderer de mapas de Quake 2. Afortunadamente implementar los lightmaps no fue tan costoso como el soporte para el mapeo de texturas.


Cuarto escondido en base1.bsp, renderizado con Lightmaps.

Cuarto escondido en base1.bsp, renderizado con Lightmaps.



Quake 2 permite acelerar mucho el rendering de polígonos precalculando la iluminación que afecta a cada uno en la etapa de compilación del Árbol BSP. Estos cálculos son almacenados en la forma de una textura de iluminación (Lightmap) que luego puede multiplicarse por la textura del polígono para obtener un efecto de tener sombreado y sombras en la escena, sin deber realizar el cálculo en tiempo real.

Quienes jugaron Quake 2 recordarán la psicodelia típica de los mapas, lo cual distingue mucho la apariencia visual del Quake 2 de la del Quake original. Esto se debe a que los Lightmaps de Quake 2 son imágenes RGB de 24 bits por pixel, permitiendo mapear no solo sombras y sombreado, sino también colores sobre los polígonos. Esto se utiliza mucho en los cuartos de exteriores, donde se quiere expresar la hostilidad de la atmósfera del planeta Strogg, y para implementar luces cromáticas.


Cuarto exterior en base1.bsp renderizado con sus Lightmaps.


A nivel de implementación el Lightmap es simplemente otra textura que debe mapearse sobre los polígonos junto con la proveniente del archivo WAL. Para combinar ambas texturas utilicé multitexturing y escribí un Shader que multiplica los texel provenientes de cada una de las dos imágenes en tiempo de ejecución.

Prefusionar el Lightmap con la textura difusa hubiese sido más rápido, sin embargo, esto no fue una opción dado que cada polígono tiene su propio Lightmap asociado, a diferencia de las texturas difusas, las cuales son compartidas entre varios polígonos.

La dificultad más grande que enfrenté para esta tarea fue calcular las coordenadas de textura del polígono en el Lightmap (las cuales son distintas de las coordenadas utilizadas para la textura difusa). Tras bastante ensayo y error, terminé encontrando la fórmula correcta en los foros de GameDev.net, aquí. Mil gracias al autor del post, realmente esta fórmula no se encuentra por ningún lado y buscarla en el código fuente del Quake 2 es una tarea muy tediosa.

Finalmente, a modo de comentario, los Lightmaps agregan muchísimo realismo al renderer, sin embargo, tienen un costo asociado. En particular, al existir un Lightmap por polígono, para un mapa de aproximadamente 9.500 polígonos (como base1.bsp), esto implica que tendremos 9.500 texturas más, aumentando un poco el consumo de memoria de video, pero -más importante- obligándonos a realizar más llamadas a glBindTexture en cada cuadro, realmente perjudicando el framerate. Existen varias estrategias para intentar resolver este problema, alguna de las cuales intentaré tras terminar de mejorar el aspecto visual de los mapas.

A continuación dejo algunas capturas realizadas con el renderer. Nótese el realismo agregado a la escena, sobre todo comparando con el post anterior, en el cual solo mapeábamos texturas. Para generar estas imágenes, modifiqué la proyección perspectiva a una más “suave”. Creo que la matriz actual es más parecida a la utilizada por el Quake 2.

Finalmente, notarás que el cielo sigue roto, afortunadamente tengo alguna idea para desarrollar un Shader especial para el cielo que permita renderizarlo como en el Motor original de Quake 2.

Hasta la próxima!


Cuarto Final de base1.bsp, con el ascensor a la Installation (base2).

Cuarto Final de base1.bsp, con el ascensor a la Installation (base2).

Cuarto de inicio en base1.bsp. Notar que el cielo no se renderiza bien debido a que no dispone (aún) de su propio shader.


This entry was posted in C++, Computación Gráfica, Programacion, Quake. Bookmark the permalink.