Anuncios Google

Lecciones 25-29 y Practicas 11-15

Tutoriales de Programaciones

25.- Las Coordenadas de Textura:

Hemos visto antes como podemos pintar los objetos usando colores o materiales. Pero si queremos dibujar una pared llena de ladrillos ¿qué hacemos?. Si dibujamos cada ladrillo con sus imperfecciones tendremos un modelo en altísima poligonización y un bonito juego más lento que el caballo del malo. La solución más barata consiste en pegar una imagen llena de ladrillos en un cuadrado que simulará la pared.

 

 

Y desde el mismo momento que decidimos pegar una imagen a un objeto surge la necesidad de indicar a OpenGL cómo queremos que la pegue: la escala, si se repite o no, la dirección, si solo una parte o toda la imagen, etc...

 

 

Para este fin OpenGL define las coordenadas de textura llamadas "s" para la anchura y "t" para la altura de la textura. La posición (0,0) corresponde a la parte inferior izquierda de la imagen y la posición (1,1) a la parte superior derecha. Estas coordenadas pueden ser superiores a 1 e inferiores a 0, consiguiendo con esto escalar o invertir la textura. La función encargada de definir las coordenadas de textura es "glTexCoord2f( GLfloat s, GLfloat t );" y debe especificarse antes que el vértice afectado. Por supuesto que si utilizamos Arrays para dibujar sería la función "glNormalPointer( GLenum tipo, GLsizei stride, GLvoid *puntero );".

 

En este ejemplo podemos ver como también se puede especificar con las coordenadas de textura, que sólo se aplique parte de la imagen cuadrada a un objeto triangular. Esto es muy importante, dado que las imágenes siempre son cuadradas o rectangulares y los objetos pueden tener cualquier forma, una incorrecta texturización producirá aberraciones en el resultado final.

Abajo veremos unos ejemplos prácticos de texturización de un cuadrado. Aún no os preocupéis de la carga de imágenes que será tratada en el siguiente capítulo.

  • Ejemplo con coordenadas de textura normal:

glBegin( GL_QUADS );
  glNormal3f( 0.0f, 0.0f, 1.0f );
  glTexCoord2f( 0.0f, 1.0f ); glVertex3i(-1, 1, 0 );
  glTexCoord2f( 0.0f, 0.0f ); glVertex3i(-1,-1, 0 );
  glTexCoord2f( 1.0f, 0.0f ); glVertex3i( 1,-1, 0 );
  glTexCoord2f( 1.0f, 1.0f ); glVertex3i( 1, 1, 0 );
glEnd();

  • Ejemplo con coordenadas de textura al doble:

glBegin( GL_QUADS );
  glNormal3f( 0.0f, 0.0f, 1.0f );
  glTexCoord2f( 0.0f, 2.0f ); glVertex3i(-1, 1, 0 );
  glTexCoord2f( 0.0f, 0.0f ); glVertex3i(-1,-1, 0 );
  glTexCoord2f( 2.0f, 0.0f ); glVertex3i( 1,-1, 0 );
  glTexCoord2f( 2.0f, 2.0f ); glVertex3i( 1, 1, 0 );
glEnd();

  • Ejemplo con coordenadas de textura a la mitad:

glBegin( GL_QUADS );
  glNormal3f( 0.0f, 0.0f, 1.0f );
  glTexCoord2f( 0.0f, 0.5f ); glVertex3i(-1, 1, 0 );
  glTexCoord2f( 0.0f, 0.0f ); glVertex3i(-1,-1, 0 );
  glTexCoord2f( 0.5f, 0.0f ); glVertex3i( 1,-1, 0 );
  glTexCoord2f( 0.5f, 0.5f ); glVertex3i( 1, 1, 0 );
glEnd();

Y para terminar abajo veréis un modelo de nave espacial de las Guerras de las Galaxias sin texturizar, la imagen y finalmente texturizado.


26.- Carga de Texturas 2D con SDL:

Como dije en el capítulo "2 ¿Qué no hace OpenGL?", este no se preocupa del marrón de cargar los diferentes tipos de formatos que puede tener un archivo de imagen "BMP, GIF, PNG, JPG, TGA, etc...". Así que vamos ha dejarle la gestión del asunto a la librería auxiliar "SDL_image.h" que complementa la carga de imágenes para SDL.

Lo primero que tenemos que tener en cuenta de la imagen es averiguar que formato de "Bytes por Pixel" se calza, por simpleza nos limitaremos solo a los dos formatos más comunes RGB y RGBA. Y lo segundo es que no se porqué OpenGL y SDL tienen invertido entre sí las imágenes en vertical. Tanto para importar imágenes a OpenGL como para exportarlas a SDL tenemos que invertirlas en vertical con la función "MirrorSurfaceX();" incluida en #include "Mirror.h".

 // -- INCLUDES REQUERIDOS --
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "Mirror.h"
// -- CARGA DE LA IMAGEN CON #include < SDL/SDL_image.h> --
SDL_Surface *Temp = IMG_Load( const char *nombre_archivo );
if ( Temp == NULL ) { cerr << "Falla IMG_Load." << endl; return false; }
// -- COMPROBACIÓN DE BYTES POR PIXEL --
GLint format;
if      ( Temp->format->BytesPerPixel == 3 ) format = GL_RGB;
else if ( Temp->format->BytesPerPixel == 4 ) format = GL_RGBA;
else {
  cerr << "Falla Bytes por Pixel IMG_Load." << endl;
  SDL_FreeSurface( Temp ); Temp = NULL; return false;
}
// -- INVERTIR LA IMAGEN EN EJE X CON #include "Mirror.h" --
Temp = MirrorSurfaceX( Temp );
// -- CREACION DE LA TEXTURA [ FALTA CÓDIGO ] --
// -- LIBERACION DE LA IMAGEN --
SDL_FreeSurface( Temp ); Temp = NULL; 

Antes de poder continuar más sobre las texturas hay que explicar el concepto de "MIPMAP". Estos son los mapas de imagen medios y son muy útiles para acelerar la texturización de objetos lejanos. Es evidente que cuando un objeto está muy cerca de la cámara la textura debe tener alta definición para verse bien, pero cuando está lejos es una pérdida de tiempo calcular una texturización a alta definición, siendo más eficiente tener copias de la imagen a diferentes definiciones según la distancia a la cámara.

Por desgracia esto tiene varios costes, el más evidente es que ocupáremos más memoria, pero es más grave el echo de que las imágenes tienen que ser cuadradas y potencias de (2^n) como "1x1, 2x2, ..., 32x32, 64x64, ..., 512x512, 1024x1024, etc..." y encima tenemos que crear varias imágenes de la misma textura con diferente resolución cargarlas y asignarlas a OpenGL con la función "glTexImage2D();"

glTexImage2D( GL_TEXTURE_2D, GLint level, GLint format, GLsizei w, GLsizei h, GLint border, GLenum format, GLenum type, GLvoid *pixels );
  level: 0,1,2.. nivel la textura MIPMAP. Si sólo hay una textura nivel=0
  format: 3 - 4 - El número de componentes de Color GL_RBG = 3 | GL_RGBA = 4
  w: SDL_imagen->w - El ancho de la imagen en pixels.
  h: SDL_imagen->h - El alto de la imagen en pixels.
  border: 0 - Sin borde, 1 - Con borde.
  format: GL_RBG | GL_RGBA
  type: GL_UNSIGNED_BYTE | GL_BYTE | GL_BITMAP | GL_SHORT | GL_INT | GL_FLOAT
  pixel: SDL_imagen->pixels 

ejemplo:
glTexImage2D( GL_TEXTURE_2D, 0, format, Temp->w, Temp->h, 0, format, GL_UNSIGNED_BYTE, Temp->pixels ); 

Hemos visto las limitaciones que tiene la función "glTexImage2D();", pero la he querido explicar puesto que tiene su utilidad en los casos en que no queramos usar texturas MIPMAP, más adelante veremos como es útil para escribir textos en pantalla usado una imagen cuadrada que contenga todos los caracteres ASCII.

Pero !qué maravillosa es la librería GLU!, casi siempre está ahí para ayudarnos. En ella esta la función "gluBuild2DMipmaps();" que nos librará de un plumazo de la tiránica limitación de usar imágenes cuadradas (2^n) y generará automáticamente los MIPMAP por nosotros. Así da gusto verdad...

gluBuild2DMipmaps(GL_TEXTURE_2D, GLint format, GLsizei w, GLsizei h, GLenum format, GLenum type, GLvoid *pixels );
  format: 3 - 4 - El número de componentes de Color GL_RBG = 3 | GL_RGBA = 4
  w: SDL_imagen->w - El ancho de la imagen en pixels.
  h: SDL_imagen->h - El alto de la imagen en pixels.
  format: GL_RBG | GL_RGBA
  type: GL_UNSIGNED_BYTE | GL_BYTE | GL_BITMAP | GL_SHORT | GL_INT | GL_FLOAT
  pixel: SDL_imagen->pixels 

ejemplo:
gluBuild2DMipmaps( GL_TEXTURE_2D, format, Temp->w, Temp->h, format, GL_UNSIGNED_BYTE, Temp->pixels ); 

Cuanta teoría y cuantas funciones verdad, pues lamentablemente aún tengo que explicaros algunas mas, paciencia. La función "glTexParameteri();" sirve para definir si aplicar y como aplicar los MIPMAP, también define si una textura se repite o no:

GL_TEXTURE_MIN_FILTER: Cuando la textura está muy lejos de la cámara.
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_enum Parametros );
 Parámetros:
 - GL_NEAREST Usa el pixel de la imágen más cercano.
 - GL_LINEAR Realiza la media de color de los cuatro píxeles de la imagen mas cercanos.
 - GL_NEAREST_MIPMAP_NEAREST Usa el píxel más cercano de la imagen MIPMAP correspondiente al tamaño del píxel.
 - GL_LINEAR_MIPMAP_NEAREST Realiza la media de color de los cuatro píxeles de la imagen MIPMAP correspondiente al tamaño del píxel.
 - GL_NEAREST_MIPMAP_LINEAR Realiza la media de los dos píxeles más cercanos de las dos imágenes MIPMAP correspondientes al tamaño del píxel.
 - GL_LINEAR_MIPMAP_LINEAR Realiza la media de los cuatro píxeles más cercanos de cada una de las dos imágenes MIPMAP correspondientes al tamaño del píxel.
 
GL_TEXTURE_MAG_FILTER: Cuando la textura está muy cerca de la cámara.
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_enum parametros );
 parámetros:
 - GL_NEAREST Usa el píxel de la imagen más cercano.
 - GL_LINEAR Realiza la media de color de los cuatro píxeles de la imagen más cercanos.
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_enum Parametros );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_enum Parametros );
 parámetros:
 - GL_CLAMP: Recorta la textura una vez esta supera las coordenadas 1.0 en (S,T)
 - GL_REPEAT: Repita la textura después de 1.0 bien sea en S y/o T. 

Bueno, con el ejemplo de abajo terminamos este capítulo tan intenso. Recordad que aún no he explicado como aplicar la textura, todo este código es solo para cargar imágenes y convertirlas en texturas.

 // -- INCLUDES REQUERIDOS --
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "Mirror.h"
// -- CARGA DE LA IMAGEN CON #include < SDL/SDL_image.h> --
SDL_Surface *Temp = IMG_Load( const char *nombre_archivo );
if ( Temp == NULL ) { cerr << "Falla IMG_Load." << endl; return false; }
// -- COMPROBACIÓN DE BYTES POR PIXEL --
GLint format;
if      ( Temp->format->BytesPerPixel == 3 ) format = GL_RGB;
else if ( Temp->format->BytesPerPixel == 4 ) format = GL_RGBA;
else {
  cerr << "Falla Bytes por Pixel IMG_Load." << endl;
  SDL_FreeSurface( Temp ); Temp = NULL; return false;
}
// -- INVERTIR LA IMAGEN EN EJE X CON #include "Mirror.h" --
Temp = MirrorSurfaceX( Temp );
// -- CREACION DE LA TEXTURA  --
GLuint textura[1];               // -- DEFINE EL NOMBRE DE LA TEXTURA/S --
glGenTextures( 1, &textura[0] ); // -- ASIGNA ESPACIO A LA/S TEXTURA/S  --
glBindTexture( GL_TEXTURE_2D, textura[0] ); // -- SELECCIONA UNA TEXTURA --
 
GLint param1, param2, efecto = 0; // - efecto de 0 a 3 --
switch( efecto ){
  case 0:  param2 = GL_NEAREST; param1 = GL_NEAREST; break;
  case 1:  param2 = GL_LINEAR;  param1 = GL_LINEAR; break;
  case 2:  param2 = GL_LINEAR;  param1 = GL_NEAREST_MIPMAP_NEAREST; break;
  case 3:  param2 = GL_LINEAR;  param1 = GL_LINEAR_MIPMAP_LINEAR; break;
  default: param2 = GL_NEAREST; param1 = GL_NEAREST; break;
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param2 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
 
gluBuild2DMipmaps( GL_TEXTURE_2D, format, Temp->w, Temp->h, format, GL_UNSIGNED_BYTE, Temp->pixels );
// -- LIBERACION DE LA IMAGEN --
SDL_FreeSurface( Temp ); Temp = NULL;
// -- USAR LA TEXTURA [ FALTA CÓDIGO ] --
// -- LIBERACION DE LA TEXTURA CUANDO YA NO SEA NECESARIA --
glDeleteTextures( 1, &textura[0] );   // -- BORRA LA TEXTURA/S -- 


27.- Aplicar Texturas 2D:

Ahora que tenemos cargada la textura en OpenGL, es necesario especificar el modo de aplicarla, lo normal es que los colores de los píxeles de la textura se combinen con los píxeles de los colores del objeto. Esta forma se denomina "GL_MODULATE", pero claro, puede que en un momento dado nos interese otras formar de aplicar la textura. El modo más radical es "GL_DECAL" que no tiene en cuenta nada y machaca todos los colores de los píxeles del objeto. Si queremos respetar las transparencias podemos usar el modo "GL_REPLACE" y si queremos usar un color específico a mezclar con los colores de los píxeles de la textura usaremos "GL_BLEND". Todos estos modos se definen con la función "glTexEnvi();" ver la tabla inferior:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_enum Parametros );
  Parámetros:
   - GL_DECAL    La textura reemplaza los colores previos no respeta los Alpha.
   - GL_REPLACE  La textura reemplaza los colores previos respeta los Alpha.
   - GL_MODULATE Combina el color del objeto con la textura.
   - GL_BLEND    Combina un color definido con la textura.
GLfloat color[4] = { 0.5f, 0.8f, 0.9f, 1.0f };
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND ); 

Por fin, ya hemos llegado al último paso. Solo nos falta seleccionar la textura que vamos a utilizar ( en el caso de tener varias ) y activar el modo "GL_TEXTURE_2D".

glBindTexture( GL_TEXTURE_2D, GLuint textura );
glEnable( GL_TEXTURE_2D );
  // -- DIBUJAR EL OBJETO CON COORDENADAS DE TEXTURA --
glDisable( GL_TEXTURE_2D ); 

Ejemplo práctico final:

// -- INCLUDES REQUERIDOS --
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "../Includes/Mirror.h"
// -- CARGA DE LA IMAGEN CON #include < SDL/SDL_image.h> --
char *nombre_archivo = "Textura.png";
SDL_Surface *Temp = IMG_Load( nombre_archivo );
if ( Temp == NULL ) { cerr << "Falla IMG_Load." << endl; return false; }
// -- COMPROBACIÓN DE BYTES POR PIXEL --
GLint format;
if ( Temp->format->BytesPerPixel == 3 ) format = GL_RGB;
else if ( Temp->format->BytesPerPixel == 4 ) format = GL_RGBA;
else {
  cerr << "Falla Bytes por Pixel IMG_Load." << endl;
  SDL_FreeSurface( Temp ); Temp = NULL; return false;
}
// -- INVERTIR LA IMAGEN EN EJE X CON #include "Mirror.h" --
Temp = MirrorSurfaceX( Temp );
// -- CREACION DE LA TEXTURA --
GLuint textura[1]; // -- DEFINE EL NOMBRE DE LA TEXTURA/S --
glGenTextures( 1, &textura[0] ); // -- ASIGNA ESPACIO A LA/S TEXTURA/S --
glBindTexture( GL_TEXTURE_2D, textura[0] ); // -- SELECCIONA UNA TEXTURA --
GLint param1, param2, efecto = 3; // - efecto de 0 a 3 --
switch( efecto ){
  case 0: param2 = GL_NEAREST; param1 = GL_NEAREST; break;
  case 1: param2 = GL_LINEAR; param1 = GL_LINEAR; break;
  case 2: param2 = GL_LINEAR; param1 = GL_NEAREST_MIPMAP_NEAREST; break;
  case 3: param2 = GL_LINEAR; param1 = GL_LINEAR_MIPMAP_LINEAR; break;
  default: param2 = GL_NEAREST; param1 = GL_NEAREST; break;
}
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param1 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param2 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
gluBuild2DMipmaps( GL_TEXTURE_2D, format, Temp->w, Temp->h, format, GL_UNSIGNED_BYTE, Temp->pixels );
// -- LIBERACION DE LA IMAGEN --
SDL_FreeSurface( Temp ); Temp = NULL;
// -- USAR LA TEXTURA --
glBindTexture( GL_TEXTURE_2D, textura[0] );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glEnable( GL_TEXTURE_2D );
  glBegin( GL_QUADS );
    glNormal3f( 0.0f, 0.0f, 1.0f );
    glTexCoord2f( 0.0f, 1.0f ); glColor3ub( 250, 0, 0 ); glVertex3i(-1, 1, 0 );
    glTexCoord2f( 0.0f, 0.0f ); glColor3ub( 0, 255, 0 ); glVertex3i(-1,-1, 0 );
    glTexCoord2f( 1.0f, 0.0f ); glColor3ub( 0, 0, 255 ); glVertex3i( 1,-1, 0 );
    glTexCoord2f( 1.0f, 1.0f ); glColor3ub( 250,255,0 ); glVertex3i( 1, 1, 0 );
  glEnd();
glDisable( GL_TEXTURE_2D );
// -- LIBERACION DE LA TEXTURA CUANDO YA NO SEA NECESARIA --
glDeleteTextures( 1, &textura[0] ); // -- BORRA LA TEXTURA/S --


28.- Generar Coordenadas de Textura ST:

En lecciones anteriores hemos visto como aplicar las coordenadas de textura a los objetos, pero también se puede dejar este trabajo a que lo haga OpenGL, aunque esto tiene sus limitaciones. OpenGL permite tres tipos de auto generar las coordenadas de texturas de un objeto a través de la función "glTexGeni();" :

  • GL_EYE_LINEAR: En el primer caso las coordenadas de textura se alinean según la perspectiva del observador, por eso la textura se mueve al mover el objeto u la cámara.
  • GL_OBJECT_LINEAR: El segundo caso la alineación es respecto al objeto, se puede definir un plano S y otro T para texturizar el objeto con cierta precisión. La textura permanece fija aunque se mueva el objeto u la cámara. Este sería el método adecuado para aplicar las coordenadas de textura de un objeto que no las tenga.
  • GL_SPHERE_MAP: El último caso es interesante para simular reflejos, la textura envuelve esféricamente al objeto y cuando hay movimiento del objeto u de la cámara la textura se mueve.

glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, parametro );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, parametro );
  parámetro:
    - GL_EYE_LINEAR
    - GL_OBJECT_LINEAR
    - GL_SPHERE_MAP
 
glEnable(GL_TEXTURE_GEN_S);  // Activa la generación de coordenadas.
glEnable(GL_TEXTURE_GEN_T);
  // -- DIBUJAR OBJETO --
glDisable(GL_TEXTURE_GEN_S); // Desactiva las coordenadas.
glDisable(GL_TEXTURE_GEN_T); 

Para la generación de coordenadas de textura "GL_EYE_LINEAR" y "GL_OBJECT_LINEAR" se pueden definir vectores S y T adicionales para modificar el proceso de generación. Si los vectores son del tipo "GLint" se usa "glTexGeniv();", si fuesen "GLfloat" pues "glTexGenfv();" según los estándares Opengl. Ver tabla inferior:

static GLint s_vector[4] = { 2, 0, 0, 0 };
static GLint t_vector[4] = { 0, 0, 2, 0 };
glTexGeniv( GL_S, parametro, GLint *vector );
glTexGeniv( GL_T, parametro, GLint *vector );
  parametro:
    - GL_EYE_PLANE
    - GL_OBJECT_PLANE 


29.- A veces veo Transparencias:

A lo largo de este tutorial hemos visto bastantes veces la palabra "Alpha" en colores, materiales e imágenes para textura. Ya va siendo hora de apechugar con el asunto. Según la documentación de OpenGL antes de usar las transparencias es necesario definir el tipo de mezcla con la función "glBlendFunc();" y después activar el interruptor "glEnable(GL_BLEND);". Ver tabla inferior :

 FUNCIONES DE MEZCLA DE COLOR:
glBlendFunc( GLenum origen, GLenum destino );
 
  origen:
  - GL_ZERO Color fuente=0,0,0,0.
  - GL_ONE Usos Color fuente.
  - GL_DST_COLOR El color origen se multiplica por el color del píxel de destino
  - GL_SRC_ALPHA El color origen se multiplica por el valor alfa de origen.
  - GL_DST_ALPHA El color origen se multiplica por el valor alfa de destino.
  - GL_ONE_MINUS_DST_COLOR Origen se multiplica por (1,1,1,1; color de destino).
  - GL_ONE_MINUS_SRC_ALPHA Origen se multiplica por (1, valor alfa de origen).
  - GL_ONE_MINUS_DST_ALPHA Origen se multiplica por (1, valor alfa de destino).
  - GL_SRC_ALPHA_SATURATE Origen se multiplica por el mínimo delos valores alfa de origen y (1, valor de destino).
 
  destino:
  - GL_ZERO Color destino=0,0,0,0.
  - GL_ONE Usos Color destino.
  - GL_DST_COLOR Color de destino se multiplica por el color del píxel de origen
  - GL_SRC_ALPHA Color de destino se multiplica por el valor alfa de de origen.
  - GL_DST_ALPHA Color de destino se multiplica por el valor alfa de destino.
  - GL_ONE_MINUS_DST_COLOR Destino se multiplica por (1,1,1,1; color de origen).
  - GL_ONE_MINUS_SRC_ALPHA Destino se multiplica por (1, valor alfa de origen ).
  - GL_ONE_MINUS_DST_ALPHA Destino se multiplica por (1, valor alfa de destino).
  - GL_SRC_ALPHA_SATURATE Destino se multiplica por el mínimo de los valores alfa de origen y (1, valor de destino).
glEnable(GL_BLEND); // Activa las transparencias.
glDisable(GL_BLEND); // Desactiva las transparencias. 

En el caso de usar texturas hechas con imágenes con canal Alpha, también se puede activar el Alpha Test para usar transparencias más sutiles como agujeros en las texturas o degradados de transparencia:

glAlphaFunc( GLenum funcion, GLclampf referencia );
 funcion:
   - GL_NEVER    Nunca pasa.
   - GL_LESS     Pasa si alpha < referencia.
   - GL_EQUAL    Pasa si alpha = referencia.
   - GL_LEQUAL   Pasa si alpha <= referencia.
   - GL_GREATER  Pasa si alpha >= referencia.
   - GL_NOTEQUAL Pasa si alpha != referencia.
   - GL_GEQUAL   Pasa si alpha >= referencia.
   - GL_ALWAYS   Siempre pasa.
referencia: de 0.0f a 1.0f;
glEnable( GL_ALPHA_TEST );  // Activa el Test Alpha
glDisable( GL_ALPHA_TEST ); // Desactiva el Test Alpha 


Práctica Nº 11 - Carga de Texturas 2D

En esta práctica vamos a estudiar la clase "c_textura_2D" incluida en el archivo "Texturas_2D.h".

Hay dos modos de carga:

  • c_textura_2D::carga_2D( const char *nombre_archivo, int efecto );
  • c_textura_2D::carga_2DMipmaps( const char *nombre_archivo, int efecto );

El primero solo soporta imágenes RGB, RGBA y de resolución (2^n), como por ejemplo 32x32, 64x64, 128x128, etc. El segundo soporta todo tipo de resoluciones y además crea automáticamente diferentes niveles de resolución de la textura. El parámetro entero "efecto" es el tipo de filtrado de la imagen y puede ser desde 0 (mínimo nivel) hasta 3 (máximo nivel).

¿Por qué usar dos modos de carga? A veces no necesitamos que la textura tenga diferentes niveles de resolución simplemente porque no tendremos en cuenta el eje "Z" de coordenadas, por ejemplo para el fondo o para escribir textos en primer plano. En estos casos ocuparemos menos memoria usando el primer modo de carga. Al contrario para los objetos que se muevan por el eje "Z" necesitaremos acelerar el proceso usando texturas de baja resolución cuando estén lejos de la cámara y alta resolución para los primeros planos.

Ahora hay cuatro tipos de aplicar la textura sobre un objeto:

  • GL_MODULATE
  • GL_DECAL
  • GL_REPLACE
  • GL_BLEND

La textura lógica es GL_MODULATE puesto que se integra con el color del material del objeto y su iluminación. GL_DECAL no tiene en cuenta los materiales ni la iluminación por lo cual es útil para pintar fondos o para escribir textos, GL_REPLACE solo respeta las transparencias. GL_BLEND se comporta como GL_MODULATE pero además mezcla con un color definido la textura y el material, esto puede ser útil para cambiar el color del objeto por ejemplo de rojo si está ardiendo, de negro si se ha quemado, de amarillo si es un objeto seleccionado, etc...

Para poder aplicar una textura a un polígono hay que definir las coordenadas de textura con "glTexCoord2f();" antes de definir el vértice "glVertex3f();". La parte inferior izquierda de la Textura corresponde con los valores (0, 0), y la parte superior derecha con (1,1). Además hay que activar primero la textura, luego dibujar el objeto y por último desactivar la textura. En algunos casos podemos querer que la textura se repita varias veces, pues es tan simple como activar la repetición y usar coordenadas de textura mayores a la unidad, ejemplo (2,2) repetiría dos veces la textura.

Las imágenes las cargamos usando "SDL_Image.h", es necesario invertir la imagen en el eje X, para eso se usa la librería "Mirror.h". De no invertir la las coordenadas son las siguientes: Parte superior izquierda ( 0, 0 ), y la parte inferior derecha ( 1, 1 ). Esto es útil saber cuando cargamos las texturas manualmente sin usar la librería "Texturas_2D.h".

Descargar Practica nº11 (Solo usuarios registrados)


Práctica Nº 12 - Coordenadas de Textura

Bueno, ahora que sabemos algo de texturas ya estoy aburrido de ver siempre un fondo monocolor y soso. Para crear un fondo bonito del entorno vamos ha utilizar seis imágenes de un decorado, las pegaremos dentro de un cubo y lo pintaremos de tal manera que no le afecte la iluminación ni el movimiento.

Todo esto y más lo tememos en el archivo "Entorno.h", si le damos el directorio donde estén las seis imágenes de nuestro decorado este se encarga de cargarlas, pegarlas en un cubo y pintarlo. También gestiona las texturas Cube_Map que las veremos más adelante.

Ahora vamos ha centrarnos en aprender a texturizar correctamente los diferentes objetos que tenemos en nuestra librería "Figuras.h", en el caso del cubo tenemos tres posibilidades, y dos en el de la pirámide. Un caso aparte es el de los objetos cuadráticos que generan ellos mismos sus coordenadas de texturas, en ellos las texturas se muestran invertidas en el plano horizontal.

Esto se puede solucionar invirtiendo en horizontal la imagen con cualquier editor que lo permita.

Descargar Practica nº12 (Solo usuarios registrados)


Práctica Nº 13 - Coordenadas de Textura ST

En la práctica anterior hemos visto como hacer las coordenadas de textura de varios objetos. Pero también se puede dejar este trabajo a que lo haga OpenGL, aunque esto tiene sus limitaciones. OpenGL permite tres tipos de auto generar las coordenadas de texturas de un objeto:

  • GL_EYE_LINEAR
  • GL_OBJECT_LINEAR
  • GL_SPHERE_MAP

En el primer caso las coordenadas de textura se alinean según la perspectiva del observador, por eso la textura se mueve al mover el objeto u la cámara. No le veo mucha utilidad la verdad.

El segundo caso la alineación es respecto al objeto, se puede definir un plano S y otro T para texturizar el objeto con cierta precisión. La textura permanece fija aunque se mueva el objeto u la cámara. Este sería el método adecuado para aplicar las coordenadas de textura de un objeto que no las tenga.

El último caso es interesante para simular reflejos, la textura envuelve esféricamente al objeto y cuando hay movimiento del objeto u de la cámara la textura se mueve.

Descargar Practica nº13 (Solo usuarios registrados)


Práctica Nº 14 - Texturas Blend y Alpha

Tanto el material como la textura pueden ser opacos o transparentes, esto da unas cuantas formas de pintar objetos:

La primera es la normal, tanto el material como la textura son opacos.

En el segundo ejemplo la textura es opaca pero el material no, esto nos muestra la textura uniformemente transparente.

El tercer ejemplo es al revés, la textura es transparente y el material no. A diferencia de los materiales, las texturas pueden tener zonas transparentes y zonas opacas. De esta manera aunque el cubo es sólido al usar una textura de barrotes con canal Alpha lo hemos convertido en una jaula.

El cuarto ejemplo riza el rizo de las texturas con canal Alpha, a parte de tener zonas opacas y transparentes, estas últimas lo son en degradado abarcando todos los posibles valores de transparencias. Pero solo son mostrados los pixels que tengan un nivel de transparencia inferior al 50%, o lo que es lo mismo Alpha > 0.5f > 128.

En el quinto ejemplo hemos usado una nueva forma de activar texturas que sea compatible con texturas con canal alpha en degradado. Ahora se muestran todos los pixels de la textura con su correcto nivel de transparencia. Ha sido necesario usar la función "textura[n].activa_Alpha_Blend();"

El sexto ejemplo es el más complejo de todos, tanto la textura como el material son transparentes y para colmo con degradado alpha. Al igual que en el ejemplo anterior es necesario usar función "textura[n].activa_Alpha_Blend();"

El séptimo ejemplo es como el tercero pero con un material transparente, siempre que ambos (material y textura) sean transparentes hay que utilizar la función "textura_2D[n].activa_Alpha_Blend();"

En el octavo hemos creado un arbol usando tres cuadrados texturizados con el dibujo de un arbol con canal Alpha sin degradado.

Y por último un cubo con material transparente con textura sin canal alpha y en modo "BLEND" en color rojo.

Sobre los objetos transparentes hay que decir que son un pequeño problema, si os fijáis bien se puede observar que si dibujamos primero un objeto transparente y luego uno opaco, el resultado no es el adecuado. También es un problema las caras internas de los objetos transparentes si no son dibujadas de atrás hacia adelante.

Descargar Practica nº14 (Solo usuarios registrados)


Práctica Nº 15 - Matriz de Coordenadas de Textura

En los dos primeros ejemplos trasladamos la matriz de textura, con esto conseguimos mover las coordenadas de textura que se aplican al cubo y a la esfera.

El tercer ejemplo es similar pero cambiando la escala de la matriz, la textura del cilindro aumenta y decrece usando una función senoidal.

En el cuarto ejemplo operamos directamente sobre un array que contiene las coordenadas de textura. En el quinto, el array tiene una segunda dimensión con 16 valores posibles de las coordenadas de textura, con esto conseguimos una animación de una explosión.

El último ejemplo traslada la matriz de textura para conseguir el mismo efecto de animación de una explosión, de esta forma ocupamos menos memoria.

Descargar Practica nº15 (Solo usuarios registrados)

4.55
Tu voto: Ninguno Votos totales: 4.6 (40 votos)

Anuncios Google

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de koldo52

Muy buen tutorial! Gracias a

Muy buen tutorial! Gracias a ti he solucionado un problema que tenia con el alpha de las texturas.

 

+3 scenebitos

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.