viernes, 26 de septiembre de 2014

Túnel wormhole: Shaders en Unity

Aunque para realizar los diferentes efectos del túnel utilicé mezcla de cosas, jugando con geometría, efectos de partículas, efectos de post-proceso... lo que hay en común en todas y era la primera vez que utilizaba eran shaders en Unity

Shaders en Unity3D
Unity añade una capa de abstracción bastante grande a los Shaders, que en realidad supone control sobre el renderizado completo. Tiene varios tipos de shaders (que son más que shaders), pero me he restringido a los que son un reflejo de lo que se entiende por shader fuera de Unity. Dentro de cada shader de Unity, además de poder especificar una serie de shaders de vértices o fragmentos, podemos configurar las pasadas, opciones de transparencia, niebla, modos de filtrado de las texturas, realizar renderizados multipasada con varios shaders en cada pasada... por lo que supone al configuración del render completo y puede ser complejo encajar todas las piezas: propiedades que se darán al shader en el editor, uniforms, atributos de entrada, pasadas...



Ayuda bastante la documentación y cantidad de dudas en los foros, tutoriales... para tomar contacto con esta forma de trabajar los shaders. En general, Unity3D es un motor bastante agradecido con los novatos por la cantidad de información que hay de él en Internet. Así que una vez que me acostumbré, comencé a hacer mis propios pequeños ejemplos para ver si las cosas funcionaban como yo creía, y poco a poco fui haciendo efectos más complejos para intentar llegar a mis metas gráficas, los efectos del túnel. Sin embargo me encontré algunas piedras en el camino, entre ellas están:

Unity no deja declarar arrays globales en los shaders. Para poner colores proceduralmente quería usar el mismo sistema que utilicé en la práctica de Rendering Avanzado de la montaña rusa, declarando un array global con los colores y mediante la altura (en este caso profundidad del túnel), hacer una función que elija colores del array y los interpole. Pero Unity transforma las variables globales a uniforms automáticamente, y el perfil para el que compilo los shaders no soporta arrays como uniform. Intenté declararlo de varias formas, todo junto, en varias sentencias, local dentro de una función... pero por más que estuve varias horas no le conseguí dar solución. Viendo que no avanzaba por este problema, opté por una solución que no me gusta nada, tener una función llena de ifs que te devuelve un color a partir de un índice. Como este efecto no creo que lo use en tiempo real sobre un dispositivo móvil, sino que se usa para la intro, que será un vídeo, si no ocupa mucho, pues no creo que cambie esa chapuza que no formará parte del código final del juego.

Otro problema fue que unity tampoco deja declarar estructuras while y for si no es capaz de desenrollar los bucles. Esto no me permitió probar algunas cosas que tenía en mente para los shaders, aunque seguramente desde el punto de vista del rendimiento no fueran buenas ideas. Y conste que probé a cambiar el modelo para el que se compilaban los shaders, intentando que fuera para máquinas más modernas en las que no debería tener este problema, pero no conseguí que me dejase de ninguna manera.

También tuve problemas al cambiar la resolución. Estaba probando en 3:2 durante el desarrollo y cambié a 16:9 para grabar la demo, y entonces hubo efectos que no funcionaban bien. Al verse más lateral y ser diferente la proporción se notaban más los empalmes del túnel y tuve que reajustar el
ancho de los empalmes para que se notase menos, y el efecto de ojo de pez hacía que todo el efecto de Odisea2001 quedase mal, así que tuve que reajustar los parámetros para el vídeo. No he tenido tiempo, pues ha sido ya sobre el deathline, pero estaría bien ajustar estos parámetros según el ancho
de pantalla para que los efectos se adapten automáticamente.

Aún con estos problemas, conseguí un par de efectos que si me gustaron y otro del que no estoy orgulloso, en próximas entradas os cuento cómo.

No hay comentarios :

Publicar un comentario