Mapeo de Texturas

Anuncio
Mapeo de Texturas
Mapeo de texturas
Texturas 1D
•
Para definir la textura:
void glTexImage1D (GLenum objetivo, GLint nivel,
GLint componentes, GLsizei ancho, GLint borde,
GLenum formato, GLenum tipo, const GLvoid *pixels)
donde:
– objetivo vale siempre GL_TEXTURE_1D
– nivel indica el nivel de detalle (0 para texturas individuales)
– componentes vale 1 (modo índice), 3 (RGB) ó 4 (RGBA)
– ancho indica el ancho en pixel del mapa de textura (debe ser potencia de 2)
– borde indica el número de pixels que forman el borde de la textura (0, 1 ó 2)
– formato indica el formato de los pixels: GL_RED, GL_RGB, GL_LUMINANCE
– tipo indica el tipo de dato de los pixels: GL_UNSIGNED_INT, GL_FLOAT
– pixels es un puntero a los pixels de la textura
Ejemplo
•
Para activar el mapeo de texturas 1D:
void glEnable (GL_TEXTURE_1D)
unsigned char ArcoIris[8][3] = {
{ 0x3f, 0x00, 0x3f },
// Violeta oscuro
{ 0x7f, 0x00, 0x7f },
// Violeta
{ 0xbf, 0x00, 0xbf },
// Malva
{ 0x00, 0x00, 0xff },
// Azul
{ 0x00, 0xff, 0x00 },
// Verde
{ 0xff, 0xff, 0x00 },
// Amarillo
{ 0xff, 0x7f, 0x00 },
// Naranja
{ 0xff, 0x00, 0x00 }
// Rojo
};
glTexImage1D (GL_TEXTURE_1D, 0, 3, 8, 0,
GL_RGB, GL_UNSIGNED_BYTE, ArcoIris);
Coordenadas de la textura
•
Para hacer corresponder las coordenadas de la textura con las de la
superficie:
void glTexCoord1f (GLfloat s)
S=0.0
S=1.0
glBegin(GL_QUADS);
glTexCoord1f (0.0);
glVertex3f (0, 0, 0);
glTexCoord1f (1.0);
glVertex3f (8, 0, 0);
(0,8) s=0.0
(8,8) s=1.0
(0,0) s=0.0
(8,0) s=1.0
// glTexCoord1f (1.0);
glVertex3f (8, 8, 0);
glTexCoord1f (0.0);
glVertex3f (0, 8, 0);
glEnd();
Variando las coordenadas
•
Virtualmente la textura se extiende para cualquier valor de s
S=-1.0
•
S=0.0
S=1.0
S=2.0
S=3.0
Podemos asignar a un vértice cualquier valor de s
s=1.0
s=1.0
s=0.0
s=2.0
s=-1.0
s=2.0
s=0.0
s=1.0
s=0.0
s=2.0
s=0.0
s=1.0
Filtrado
•
Al mapear la imagen de textura sobre una superficie, los texels no se
van a corresponder exactamente con los pixels
– Si la superficie es mayor que la textura, cada pixel se corresponderá con
un trozo pequeño de texel ---> Magnificación
– Si la superficie es menor que la textura, cada pixel se corresponderá con
una conjunto de texels contiguos ---> Minificación
Texels
Pixels
Pixels
Tipos de filtrado
void glTexParameteri (GL_TEXTURE_1D, GLenum filtro, GLint valor)
GL_NEAREST
GL_TEXTURE_MAG_FILTER
GL_TEXTURE_MIN_FILTER
GL_NEAREST
Textura
GL_LINEAR
GL_LINEAR
Ejemplo final con texturas 1D
unsigned char Arco[8][3] = {...}
// Habilitamos el mapeo de texturas
glEnable(GL_TEXTURE_1D);
// Indicamos el tipo de filtrado
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Creamos la textura
glTexImage1D(GL_TEXTURE_1D,0,3,8,0,GL_RGB,GL_UNSIGNED_BYTE,Arco);
// Indicamos el modo de mapeo
//(volcar el valor de los texels directamente sobre los pixels)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// dibujamos el objeto
glBegin(...);
glTexCoord1f (..);
glVertex3f (...);
...
glEnd();
Modos de mapeo
•
Para establecer el modo de mapeo:
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GLint valor)
donde valor puede tomar 3 valores:
– GL_DECAL: el valor del texel se copia directamente al pixel
– GL_MODULATE: el valor del texel se escala por el color del objeto
– GL_BLEND: el valor del texel se usa para interpolar entre el color del objeto y un
color constante definido para la textura, mediante la función
glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,GLfloat color[4])
ENV_COLOR
Texturas 2D
•
Para definir la textura:
void glTexImage2D (GLenum objetivo, GLint nivel,
GLint componentes, GLsizei ancho, GLsizei alto,
GLint borde, GLenum formato, GLenum tipo,
const GLvoid *pixels)
donde:
– objetivo vale siempre GL_TEXTURE_2D
– nivel indica el nivel de detalle (0 para texturas individuales)
– componentes vale 1 (modo índice o luminancia), 3 (RGB) ó 4 (RGBA)
– ancho indica el ancho en pixels del mapa de textura (debe ser potencia de 2)
– alto indica el alto en pixels del mapa de textura (debe ser potencia de 2)
– borde indica el número de pixels que forman el borde de la textura (0, 1 ó 2)
– formato indica el formato de los pixels: GL_RED, GL_RGB, GL_LUMINANCE
– tipo indica el tipo de dato de los pixels: GL_UNSIGNED_INT, GL_FLOAT
– pixels es un puntero a los pixels de la textura
Ejemplo
•
Para activar el mapeo de texturas 2D:
void glEnable (GL_TEXTURE_2D)
unsigned char Colores[4][4][3] = {
{{64,0,0}, {128,0,0},
{192,0,0},
{{0,64,0}, {0,128,0},
{0,192,0},
{{0,0,64}, {0,0,128},
{0,0,192},
{{64,64,0}, {128,128,0}, {192,192,0},
};
{255,0,0}},
{0,255,0}},
{0,0,255}},
{255,255,0}}
glTexImage2D (GL_TEXTURE_2D, 0, 3, 4, 4, 0,
GL_RGB, GL_UNSIGNED_BYTE, Colores);
//
//
//
//
Rojos
Verdes
Azules
Amarillos
Coordenadas de la textura
•
(s,t)=(0,0)
(s,t)=(1,0)
(s,t)=(0,1)
(s,t)=(1,1)
Para hacer corresponder las coordenadas de la
textura con las de la superficie:
void glTexCoord2f (GLfloat s, GLfloat t)
glBegin(GL_QUADS);
glTexCoord2f (0.0, 0.0);
glVertex3f (0, 0, 0);
(0,4) (s,t)=(0,0)
(4,4) (s,t)=(1,0)
(0,0) (s,t)=(0,1)
(4,0) (s,t)=(1,1)
glTexCoord2f (1.0, 1.0);
glVertex3f (4, 0, 0);
glTexCoord2f (1.0, 0.0);
glVertex3f (4, 4, 0);
glTexCoord2f (0.0, 0.0);
glVertex3f (0, 4, 0);
glEnd();
Variando las coordenadas
•
Virtualmente la textura se extiende para cualquier valor de s y de t
(s,t)=(-1,-1)
(s,t)=(1,-1)
(s,t)=(0,0)
(s,t)=(1,0)
(s,t)=(0,1)
(s,t)=(1,1)
(s,t)=(0.5,2)
•
Podemos asignar a un vértice cualquier valor de s y de t
Leyendo la textura de un fichero (C++ Builder)
Graphics::Tbitmap *bitmap;
// objeto donde leeremos la imagen
unsigned char *textura;
// vector donde se leerá la textura
TColor tcolor;
// variable donde se lee cada pixel
unsigned char *color = (unsigned char *) &tcolor;
int dimx, dimy, n=0;
bitmap = new Graphics::TBitmap;
// creamos el objeto bitmap
bitmap->LoadFromFile(”textura.bmp"); // volcamos la imagen en él
dimx = bitmap->Width;
dimy = bitmap->Height;
// potencias de 2
textura = (unsigned char *) malloc (dimx*dimy*3);
for (int j=0; j<dimy; j++)
for (int i=0; i<dimx; i++) {
// leemos el color pixel
tcolor = bitmap->Canvas->Pixels[i][j];
textura[n++] = color[0];
// leemos la componente roja
textura[n++] = color[1];
// leemos la componente verde
textura[n++] = color[2];
// leemos la componente azul
}
delete bitmap;
// borramos el objeto bitmap
glTexImage2D (GL_TEXTURE_2D, 0, 3, dimx, dimy, 0,
GL_RGB, GL_UNSIGNED_BYTE, textura);
Texturas sobre una malla de vértices
•
Al texturar un objeto hay que especificar la coordenada de textura para
cada vértice
glTexCoord2f (.., ..);
glVertex3f (.., .., ..);
glTexCoord2f (.., ..);
glVertex3f (.., .., ..);
glTexCoord2f (.., ..);
glVertex3f (.., .., ..);
glTexCoord2f (.., ..);
glVertex3f (.., .., ..);
Generación automática de coordenadas
•
Podemos decirle a OpenGL que genere automáticamente las
coordenadas de textura para cada vértice del objeto
void glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GLint param)
GL_OBJECT_LINEAR
GL_EYE_LINEAR
GL_SPHERE_MAP
•
Para cada vértice, la coordenada de textura vendrá dada por:
s = x*plano_s[0] + y*plano_s[1] + z*plano_s[2] + w*plano_s[3]
– donde (x,y,z,w) son las coordenadas homogéneas del vértice,
– y plano_s viene definido por la llamada a la función:
void glTexGenfv (GL_S, GL_OBJECT_PLANE, GLfloat plano_s[4])
Ejemplo con texturas 1D
GLfloat plano_s[4] = {1, 0, 0, 0};
// s=x
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenfv (GL_S, GL_OBJECT_PLANE, plano_s);
glEnable (GL_TEXTURE_GEN_S);
GL_DECAL
y
GL_BLEND
x
z
Ejemplo con texturas 2D
GLfloat plano_s[4] = {1, 0, 0, 0};
// s=x
GLfloat plano_t[4] = {0, 1, 0, 0};
// t=y
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenfv (GL_S, GL_OBJECT_PLANE, plano_s);
glEnable (GL_TEXTURE_GEN_S);
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenfv (GL_T, GL_OBJECT_PLANE, plano_t);
glEnable (GL_TEXTURE_GEN_T);
y
textura
x
z
GL_BLEND
GL_DECAL
Matrices de textura
•
Las coordenadas de textura también se pueden transformar a través de
la matriz de textura.
glMatrixMode (GL_TEXTURE)
•
Las coordenadas de textura se pueden trasladar, escalar y rotar.
•
Ejemplo: para simular la ondulación del agua podemos trasladar la
textura con un timer
Problemas con las texturas individuales
•
Cuando la proyección del objeto con textura ocupa pocos pixels en la
pantalla, no tiene sentido trabajar con un mapa de textura grande
8
256
256
64
y
256
z
x
Texturas multimapa (Mipmaps)
•
Se generan varias imágenes de la textura con distinta resolución
– las resoluciones son siempre potencias de dos
– hay que acabar en las imágenes 1x1
glTexImage2D (GL_TEXTURE_2D,0,3,2n,2n,0,GL_RGB,..,imagen_0);
glTexImage2D (GL_TEXTURE_2D,1,3,2n-1,2n-1,0,GL_RGB,..,imagen_1);
....
glTexImage2D (GL_TEXTURE_2D,n,3,1,1,0,GL_RGB,..,imagen_n);
2 1
•
2n-3
2n
2n-2
2n-1
OpenGL decide qué imagen
usar automáticamente, en
función del tamaño de la
proyección del objeto
Filtrado con mipmaps
•
Para decidir qué texels deben usarse para calcular el color de cada pixel:
glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER, GLint valor)
GL_NEAREST_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_LINEAR
Texels de
imagen i+1
Filtrado
Texels de
imagen i
Pixels
Generación automática de mipmaps
•
Si queremos que OpenGL calcule automáticamente las imágenes de
textura de menor resolución, a partir de la imagen original:
void gluBuild2DMipmaps(GL_TEXTURE_2D, GLint componentes,
GLsizei ancho, GLsizei alto, GLenum formato,
GLenum tipo, const GLvoid *pixels)
•
La anterior llamada es equivalente a
unsigned char imagen_0 [256][256][3] = {....}
unsigned char imagen_1 [128][128][3] = {....}
....
unsigned char imagen_8 [1][1][3] = {....}
glTexImage2D (GL_TEXTURE_2D, 0, 3, 256, 256, GL_RGB,
GL_UNSIGNED_BYTE, imagen_0)
glTexImage2D (GL_TEXTURE_2D, 1, 3, 128, 128, GL_RGB,
GL_UNSIGNED_BYTE, imagen_1)
....
glTexImage2D (GL_TEXTURE_2D, 8, 3, 1, 1, GL_RGB,
GL_UNSIGNED_BYTE, imagen_8)
Objetos de textura
•
Se usan para acelerar la carga de texturas en memoria.
•
Para reservar un número de objetos de textura:
void glGenTextures (GLsizei num, Gluint *nombres)
•
Para asociar una textura a cada índice reservado:
void glBindTexture (GLenum num, Gluint nombre)
– La primera vez que se llama a esta función, se carga la textura en memoria.
– Las demás veces, sólo selecciona la textura, por lo que no hace falta cargarla
de nuevo
•
Para liberar memoria, en caso de que dejemos de usar la textura:
void glDeleteTextures (GLsizei num, const Gluint *nombres)
Ejemplo
GLuint texturas[3];
void Init()
{
glGenTextures (3, texturas);
// textura del suelo
glBindTexture (GL_TEXTURE_2D, textura[0]);
glTexParameteri (…);
glTexImage2D (GL_TEXTURE_2D, …);
// textura de la pared
glBindTexture (GL_TEXTURE_2D, textura[1]);
glTexParameteri (…);
glTexImage2D (GL_TEXTURE_2D, …);
…
}
void Paint()
{
// pinto el suelo
glBindTexture (GL_TEXTURE_2D, textura[0]);
glBegin (…);
…
glEnd();
// pinto la pared
glBindTexture (GL_TEXTURE_2D, textura[1]);
glBegin (…);
…
glEnd();
}
Descargar