17. Multitexturas |
![]() |
![]() |
Videojuegos - Curso de Programación de juegos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Escrito por Vicengetorix | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() Veremos las multitexturas, multiples texturas aplicadas a la misma superficie, y para ello usaremos GLee tal y como vimos en el capitulo anterior. No sera un capitulo complicado si se ha llegado hasta este punto del curso pero sera un ejercicio liberador al dejar la vieja version 1.1 y abrirnos un mundo de capacidades graficas en nuestra tarjeta. Lo primero que quiero comentar es que lo visto hasta ahora, aunque alguien lo pueda considerar desfasado como he visto en algun comentario por ahi, yo creo que es necesario para llegar hasta donde estamos del curso. Creo que si alguien que empieza se va a lo ultimo sin conocer nada de las bases, no entendera nada por listo que sea. Dicho esto, al tema. Lo primero es lo primero, en este caso explicar el concepto de multitextura. Imaginemos que no estamos con un PC delante y lo que vemos, en vez de un modelo tridimensional en pantalla, es una miniatura de plastico encima de la mesa que nos disponemos a pintar con nuestros botecitos de pintura y un pincel. Le podriamos aplicar una primera capa de pintura como base. Eso seria en el PC aplicarle una textura. Luego podriamos aplicarle otra capa de pintura con los colores. En la version PC aplicarle una segunda textura. Por fin le aplicariamos otra capa de un color oscuro, pero muy diluido en disolvente para simular suciedad pero sin tapar totalmente la capa anterior. En la version PC del tema seria aplicarle una tercera textura. La idea es esa. Anteriormente podiamos aplicar una textura a los objetos de nuestro programa, que cargabamos desde disco. A partir de ahora podremos aplicar mas de una textura a cada superficie. Alguien, llegado a este punto, se podria preguntar ¿para que hacer eso? Pues para temas avanzados como sombras, o para añadir suciedad a los modelos, o para otros mil efectos que se nos ocurran. Mas facil es verlo con nuestros propios ojos. Dadas dos texturas como estas: ![]() ![]() Conseguriamos esto al aplicarlas a la misma superficie, primero la primera y luego la segunda de forma que se mezcle con la anterior: ![]() Creo que con esto el concepto no admite dudas.
El numero de texturas maximo que se puede aplicar depende de la implementacion de OpenGL, de la tarjeta grafica que tengamos. Con una llamada a la funcion glGetIntegerv(...) podremos saber cual es el maximo de nuestra tarjeta. Lo veremos. En mi caso, con una tarjeta Intel de hace unos años, el maximo es 8 texturas (de la 0 a la 7). Antes de pasar al codigo debemos incluir el fichero GLee.c en nuestro proyecto, tal como se vio en el capitulo anterior. Ahora empezaremos con el codigo, modificando el programa que teniamos en el capitulo 15 sobre carga de modelos y uso de Vertex Array. Concretamente con el codigo en que se cargaba un modelo de rinoceronte (al que daremos algo de color). Partiendo de este codigo tenemos la posibilidad de ver como implementar multitexturas con Vertex Arrays y sin ellos. Como siempre no pongo aqui todo el codigo si no solo el nuevo o el que cambia. Empezamos con las definiciones globales que cambien en el codigo. Lo primero es incluir el fichero de cabecera de GLee. Como internamente incluye gl.h, este ultimo ya no lo tenemos que incluir.
Añado una variable int mas para guardar el identificativo de una textura mas que voy a cargar, la de colores que voy a superponer al cartel y al rinoceronte.
Cambio valores de los materiales que no me gustaban en capitulos anteriores (creo que me equivoque al ponerlos). Obviamente, esto no es importante para el tema que nos ocupa.
Nos vamos a la funcion IniciaGL(), que aunque esta al final del codigo se ejecuta pronto. Aqui verificaremos si la version de OpenGL es la que soporta multitexturas o si soporta la extension. En el codigo he simplificado y compruebo las dos cosas independientemente pero con una que se diera podriamos usar multitexturas. Si la version es 1.3 o superior, la extension tambien estara soportada aunque las funciones y definiciones formen parte del nucleo (en ingles core).
Las multitexturas fueron incluidas en el nucleo de OpenGL de la version 1.3. Antes se soportaban a traves de la extension ARB_multitexture, en las tarjetas que lo soportaran. Si trabajamos con version 1.3 o superior no sera necesario poner "ARB" o "_ARB" detras de las funciones o definiciones (por ejemplo glActiveTextureARB o GL_TEXTURE0_ARB), bastara con poner solo la funcion o la definicion solo (glActiveTexture o GL_TEXTURE0) ya que estan funciones forman parte del nucleo de OpenGL 1.3 y superiores. Si por el contrario trabajamos con la extension por ser una version de OpenGL inferior a la 1.3 (1.1 o 1.2) deberemos añadir el sufijo correspondiente "ARB" o "_ARB" detras. La libreria GLee, ademas de permitirnos comprobar la version o si esta soportada una extension facilmente, en caso de respuesta positiva dejara preparadas para el el uso en nuestro programa las funciones correspondientes y las definiciones necesarias. Esto quiere decir que si intentamos usar una extension que sabemos que nuestra tarjeta soporta, antes de comprobar en el codigo si la soporta, el programa no reconocera las funciones y definiciones de esa extension. Solo podremos usarla despues de preguntar si la soporta. Esto es aplicable a las versiones. Es la forma de funcionar de GLee. En todo caso, tras el codigo para comprobar si podemos usar multitextura, ya estamos en disposicion de usar las nuevas opciones. Cargamos una textura nueva que sera la que superpongamos al cartel y a la piel del rinoceronte.
Tambien he añadido otro punto de luz para ver mejor (me ha dado por ahi). Ni que decir tiene que esto no es necesario si no se quiere.
En la funcion CargaTextura(...) he cambiado una cosa que estaba antes equivocada (mil perdones)
Con esta rectificacion vereis que ahora si cambia la cosa de GL_MODULATE a GL_DECAL u otro parametro. Vamos a la funcion PintaModelo() donde habra que cambiar el codigo para especificar con que textura trabajamos ya que ahora disponemos de mas de una para cada superficie que podemos usar o no. Al trabajar con multitexturas, la antigua unica textura se convierte en la textura 0. Eso quiere decir que por defecto la textura 0 es la que modificamos si no especificamos nada (como antes de trabajar con multitexturas. En cada unidad de textura (la 0, 1, 2, 3,...) se puede habilitar textura - glEnable(GL_TEXTURE_2D) - o desabilitar, se puede hacer bind de la textura que queramos y tengamos cargada; y se puede modificar la forma en que se aplicara sobre la anterior independientemente. Todo con las mismas funciones de siempre. Solo habra que especificar antes con que "texture unit" vamos a trabajar (la 0, 1, 2, 3,...). Por defecto todas estan desabilitadas asi que despues de usarlas habra que tener cuidado de dejarlas como estaban, desabilitadas. En caso de usar solo una textura, una sola unidad de textura, se debe usar la 0, la que siempre habiamos usado antes sin saberlo. Si usamos mas seran siempre correlativas a la 0 sin dejar unidades de textura sin usar entre medias. En realidad puede ser que se pueda hacer especificando mas parametros de cada textura pero yo lo hago como os digo y no me complico mas. Si quereis investigar adelante. Veremos la funcion glActiveTexture(...) que es la que usaremos para decir a OpenGL a que unidad de textura afectaran las proximas funciones sobre texturas de nuestro codigo. La textura se especifica con las definiciones GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2,... y asi hasta la ultima que nos permita nuestra tarjeta. La funcion glClientActiveTexture(...) indica a que unidad de textura afectara la proxima funcion glEnableClientState(GL_TEXTURE_COORD_ARRAY) y glTexCoordPointer(...) cuando estemos usando Vertex Arrays. La primera funcion glDisable(GL_TEXTURE_2D) se cambia por esto...
... con lo que aclaramos que la textura que desabilitamos es solo la 0 y a partir de este punto de la funcion las lineas de codigo sobre textura seran sobre la textura 0. Parece que al ser la textura por defecto la 0 no seria necesario especificarlo pero en realidad no sabemos si la funcion PintaModelo() ha sido llamada con la textura 0 como la activa. De hecho veremos en la funcion Pinta() que no va ha ser asi porque vamos a modificar la textura 1. En la funcion Pinta() modificaremos la textura 1 para superponerla al modelo primero y al cartel despues. Antes de pintar el modelo preparamos la textura 1, luego pintamos el modelo y luego dejamos la textura 0 como la de trabajo, no sin antes desabilitar la 1. El codigo esta explicado, como siempre.
Dentro de la funcion PintaModelo() se preparaba la textura 0 para pintar la textura que trae el modelo con lo que a la hora de pintar el modelo tendremos la textura 0 habilitada con la imagen de la piel del rinoceronte y la textura 1 con la imagen de colores que vamos a superponer. El siguiente codigo modificado sera el de pintar el cartel. Para este no se usan Vertex Arrays, con lo que no usaremos ahora la funcion glClientActiveTexture(...), no hara falta. El resto es parecido. Solo cambia la especificacion de las coordenadas de textura, para lo que usaremos una nueva funcion, glMultiTexCoord2f(...), con la que especificaremos a que textura se aplicaran las coordenadas y las propias coordenadas. Antes de pintar y despues de preparar la textura de siempre de la manera de siempre (la textura 0) preparamos la textura 1.
Un poco despues, cuando pintamos los vertices especificamos las coordenadas de la textura 1 con la nueva funcion glMultiTexCoord2f(...).
Observad como las coordenadas de la textura 0 se indican como siempre, con glTexCoord2f(...). Se podria hacer tambien con la nueva funcion glMultiTexCoord2f(...) indicando como primer parametro GL_TEXTURE0, seria lo mismo. Para terminar, como siempre, dejamos las cosas en su sitio.
Ya tenemos el cartel con colorines por encima. Para terminar los cambios en la funcion Pinta() vamos a preguntar a nuestra tarjeta grafica cuantas capas de pintura acepta, cuantas texturas se pueden aplicar a la vez a la misma superficie.
Por ultimo, en la funcion ProcesaMensajes(...), en el punto en que borro las texturas cargadas debo añadir el borrado de la textura de colorines nueva que he cargado en este capitulo, la de tex3.
Al ejecutar el programa se veria algo asi: ¡Sólo los usuarios registrados pueden escribir comentarios!
3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved." |