Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
La utilización de texturas es determinante para dar una apariencia real al material del que estén constituidos los modelos de la escena. Una textura es una imagen que se pega a un modelo tridimensional de forma que parezca que forma parte del objeto.
En OpenGL, si queremos aplicar textura, tenemos que seguir los siguientes pasos:
Esto se hace ejecutando la siguiente instruccion:
glEnable(GL_TEXTURE_2D)
Para ello se utiliza la siguiente funcion:
void glTexImage2D( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels )
Ejemplo :
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data)
La imagen se puede obtener de dos formas. Una, generandola con codigo del propio programa. Esto es facil si la textura es sencilla, como puede ser un tablero de ajedrez. Si la imagen es mas complicada, hay que cargarla de un archivo. En el ejemplo que damos aqui, se muestra una función para cargar una textura a partir de un archivo BMP de
Windows.
OpenGL exige que las dimensiones de la imagen en unidades de pixel (ancho y alto)
, sean 2n x 2m. donde n y m son eneteros.
Cuando se esta dibujando el objeto, hay que indicar, para cada vertice de este, que posición
de la textura le corresponde. Esto se hace mediante la siguiente función :
void glTexCoord2f( GLfloat s, GLfloat t)
Donde (s,t) indica una posicíon sobre el mapa de la imagen.Lo que se hace es indicar la
coordenada de la textura antes de indicar el vertice del polígono. A continuación vemos
como se dibuja el poligono del frente, indicando las posicion de la textura :
// Frente glNormal3f( 0.0f, 0.0f, 1.0f) glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f) glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f) glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f) glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f)
Aqui hay varios puntos que indicar. El primero de ellos es indicar que ocurre con el tamaño de las texturas. Cuando uno referencia la coordenadas de las texturas, se indican valores entre 0 y 1, que dan los limites de las texturas. Cuando uno referencia un valor mayor que 1 o menor que 0, se esta fuera del mapa de la imagen. ¿Que hacer en estos casos?. Hay dos posibilidades. La primera es repetir los pixels de los bordes de la textura cuando se referencie fuera de ella, lo cual no parece que tenga mucha utilidad. La otra posibilidad es la de repetir la textura. Esto es, en lugar de tener un mapa con solo una imagen, se tiene un mapa donde la imagen de la textura esta repetida infinitas veces, unas contiguas a las otras.
Para indicar si se quiere repetir el borde de la textura, o se quiere repetir la textura
completa se utiliza la siguiente función :
void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
Ejemplo :
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
Otro de los parametros a tener en cuenta es el filtrado de las texturas. Cuando la camara
esta muy cerca de un objeto con texturas, debido al efecto del mapeado se pueden notar con
mucha claridad la diferencia entre los pixels contiguos de la textura, que se ven como unos
cuadrados mas grandes cuanto mas cerca se esta del objeto.
Un efecto desagradable aparece tambien cuando se esta lejos de las texturas. Si se tiene
objeto lejano con una textura del tipo de un tablero de ajedrez, debido a que solo se dibujan
algunos de los pixels de la textura, pueden aparecer formas muy extrañas en la textura.
Si se quiere evitar de forma parcial este efecto, existe la posibilidad de filtrar las
texturas. Esto se hace con la siguiente llamada :
void glTexParameterf( GLenum target, GLenum pname, GLfloat param )
donde:
Ejemplo :
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
![]() |
El Cubo 3D, con la textura aplicada. |
![]() |
Textura utilizada, en este caso es un archivo del tipo bmp (mapa de bits) y de 256x256 pixels. |
/* Rotación de un Cubo, con la aplicación de Textura Autor : Ramiro Alcocer WWW : www.oocities.org/valcoey/index.html Email : valcoey@hotmail.com */ #include <GL/glut.h> #include <gl/gl.h> #include <gl/glu.h> #include <gl/glaux.h> #include <stdio.h> //angulos de rotacion GLfloat xrot=0.0; GLfloat yrot=0.0; GLfloat zrot=0.0; GLint texture[1]; //parametros de la fuente de luz GLfloat LightAmbient[]={ 0.5f, 0.5f, 0.5f, 1.0f }; GLfloat LightDiffuse[]={ 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat LightPosition[]={ 1.0f, 1.0f, 1.0f, 0.0f }; AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image { FILE *File=NULL; // File Handle if (!Filename) // Make Sure A Filename Was Given { return NULL; // If Not Return NULL } File=fopen(Filename,"r"); // Check To See If The File Exists if (File) // Does The File Exist? { fclose(File); // Close The Handle return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer } return NULL; // If Load Failed Return NULL } int LoadGLTextures() // Load Bitmaps And Convert To Textures { int Status=FALSE; // Status Indicator AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit if (TextureImage[0]=LoadBMP("imagen.bmp")) { Status=TRUE; // Set The Status To TRUE glGenTextures(1, &texture[0]); // Create The Texture // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } if (TextureImage[0]) // If Texture Exists { if (TextureImage[0]->data) // If Texture Image Exists { free(TextureImage[0]->data); // Free The Texture Image Memory } free(TextureImage[0]); // Free The Image Structure } return Status; // Return The Status } void init(void) { //Carga la textura LoadGLTextures(); glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); //posicion de la fuente de luz glLightfv(GL_LIGHT1, GL_POSITION,LightPosition); //activa la luz glEnable(GL_LIGHT1); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-4.5f); //Rota el cubo glRotatef(xrot,1.0f,0.0f,0.0f); glRotatef(yrot,0.0f,1.0f,0.0f); glRotatef(zrot,0.0f,0.0f,1.0f); glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); // Frente glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // parte de Atras glNormal3f( 0.0f, 0.0f,-1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Arriba glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Abajo glNormal3f( 0.0f,-1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // lado Derecho glNormal3f( 1.0f, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Lado Izquierdo glNormal3f(-1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); glFlush (); glutSwapBuffers(); } void reshape (int width, int height) { if (height==0) { height=1; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); break; } } //Incremento los angulos de rotacion void Idle(void) { xrot+=5.0f; yrot+=6.0f; zrot+=7.0f; display(); } int main(int argc, char** argv) { //Inicializar el estado de GLUT glutInit(&argc, argv); //Seleccionar el tipo de modo de display Buffer doble y color RGBA glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //Poner el tamaño y posición de la ventana glutInitWindowSize (300, 300); glutInitWindowPosition (0, 0); glutCreateWindow ("Textura 3D"); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutIdleFunc(Idle); glutMainLoop(); return 0; } |
valcoey@hotmail.com
Ramiro Alcocer, 2001
Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links