Académique Documents
Professionnel Documents
Culture Documents
Laboratorio 08
Objetivo: El objetivo de esta práctica, es que el alumno conozca y sepa cómo se lleva a cabo el proceso
de mapeado de Texturas, además de conocer las principales funciones de manejo de Texturas con
OpenGL.
El conocimiento requerido para realizar esta práctica es de haber asimilado los conceptos básicos
de C/C++ y OpenGL.
1. Mapeado de Texturas
2. Mapa de Bits basado en máscaras
3. Programa ejemplo
4. Texturas basadas en ficheros gráficos
5. Programa ejemplo
6. Ejercicios propuestos
7. Referencias
8. Anexo 1
9. Anexo 2
1. MAPEADO DE TEXTURAS
Obtener un buen realismo de nuestras escenas implica un decorado exhaustivo de ellas, para esto
haremos uso de los mapas de bits (definidas por el usuario) y las funciones involucradas pertenecientes
a OpenGL para un manejo adecuado de estas. En una primera instancia estas son usadas para diseñar
caracteres y en otras para rellenar polígonos. También puede emplearse imágenes definidas en
ficheros gráficos y opcionalmente algún algoritmo procedural para minimizar costos computacionales.
2. MAPA DE BITS
Un mapa de bits o bitmap es un arreglo rectangular de 0 y 1 que sirve para representar imagen,
también se le denomina de máscara (de bits), esta permite dibujar (o rellenar) una porción rectangular
o ventana.
• glRasterPos{23}{if}{v}{x,y,y}: especifica la posición actual del raster, las cuales vienen dadas
por (x,y) en el caso glraster2i(x,y). Generalmente sirve para posicionar o desplazar el raster a
una nueva posición.
alto
(origenX,origenY)
(0,0) (disX,disY)
(12,0)
raster ancho
máscara
3. PROGRAMA EJEMPLO
Para esto, guíese del cuadro adjunto para describir la máscara (de bits) necesaria en hexadecimal.
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Glint aw,ah;
// arreglo de bits para el caracter F
GLubyte rasters[24] = {
0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xff, 0x00, 0xff, 0x00, 0xc0, 0x00,
0xc0, 0x00, 0xc0, 0x00, 0xff, 0xc0, 0xff, 0xc0};
void myinit(void)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.0, 0.0, 0.0, 0.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glRasterPos2i (20.5, 20.5);
glBitmap(10, 12, 0.0, 0.0, 12.0, 0.0, rasters);
void myReshape(intw,int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, 0, h, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
int main(intargc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (0,0);
glutCreateWindow ("teste");
myinit ();
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
//glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Modificaciones (sugerencia)
El siguiente mapa de bits ha sido tomado de “OpenGL Superbible”, que consiste en dibujar caritas
felices de forma aleatoria:
Int aw,ah;
GLubyte caritas[] = {
0x03, 0xc0, 0, 0,
0x0f, 0xf0, 0, 0,
0x1e, 0x78, 0, 0,
0x39, 0x9c, 0, 0,
0x77, 0xee, 0, 0,
0x6f, 0xf6, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0xff, 0xff, 0, 0,
0x73, 0xce, 0, 0,
0x73, 0xce, 0, 0,
0x3f, 0xfe, 0, 0,
0x1f, 0xf8, 0, 0, Figura No. 2. Mascaras de bits en
0x0f, 0xf0, 0, 0, posiciones aleatorias
0x03, 0xc0, 0, 0, };
for(int i=0;i<100;i++)
{glRasterPos2i(rand()%aw,rand()%ah);
glBitmap(16,16,8.0,8.0,0.0,0.0,caritas);
}
y en la función reshape:
aw=w;
ah=h;
¿Qué es una textura?, Imagine un lienzo o una alfombra muy decorada a su gusto, tómela y péguela
a la pared, o mejor aún, cubra toda la pared de su cuarto (ya sea extendiéndola o en mosaico); bien, lo
que ha hecho es justamente un mapeado de texturas, y su lienzo ha sido la textura empleada.
Ignoraremos el hecho usual de que este tipo de operaciones suelen ser muy costosas y lentas en el
renderizado de la respectiva escena, salvo este detalle trataremos de mostrar algunos resultados que
luego pueden ser extendidos a escenas más complicadas.
Para un éxito razonable del uso de texturas comentaremos acerca de las funciones necesarias que
OpenGL proporciona para este efecto:
• GL_UNSIGNED_BYTE
• GL_BYTE
• GL_BITMAP
• GL_UNSIGNED_SHORT
• GL_SHORT
• GL_UNSIGNED_INT
• GL_INT
• GL_FLOAT
• pixels es un puntero al mapa de valores de los píxeles. Recuerde que esta deberá ser
generada por cualquier método de lectura para ficheros gráficos.
• void glTexCoord2f(GLfloat x, GLfloat y):las coordenadas (x,y) indican las posiciones sobre
la textura, el cual se hace antes de indicar las coordenadas de vértice para el polígono
involucrado, por ejemplo:
Observe que nuestra textura está limitada por 0 y 1, piense en un escalamiento por defecto.
void glEnable(GL_TEXTURE_2D)
5. PROGRAMA EJEMPLO
Ahora si desea usar exclusivamente glut y no otra librería auxiliar como glaux, entonces disponemos
de un método (ANEXO 2) no muy complicado propuesto por Raquel Viaña (raquel.viana@uah.es) de
la Universidad de Alcalá, el cuál puede verse en http://www2.uah.es/rviana/texturasCuadrado.cpp.
De igual manera R. Wright & M. Sweet (OpenGL Superbible) proponen un algoritmo más eficiente,
el cual se deja al alumno para que lo revise e implemente.
6. EJERCICIOS PROPUESTOS
Ejercicio 01:
Implemente un programa en el que se vea un cubo con diferentes texturas en cada cara. Haga las
implementaciones necesarias para que una de estas caras involucre un mapeado con patrones.
Ejercicio 02:
Ejercicio 03:
En función del anterior taller, implemente el código necesario para mostrar un gris como base del
terreno y sobre el insertar objetos arqueológicos como pirámides u obeliscos de tal forma que podamos
incorporar texturas de forma apropiada, finamente activarlas o desactivarlas.
7. REFERENCIAS
1. Foley J. D., A.van Dam, S.K.Feiner and J.F. Hughes Computer Graphics. Principles and
Practice (Second Edition). Addison-Wesley. 1990
2. OpenGL Superbible. R. Wright and M. Sweet. Waite Group, Inc 1996
3. The OpenGL Utility Toolkit (GLUT) Programming Interface (API Version 3). Mark J. Kilgard,
Silicon Graphics, Inc 1996
4. The OpenGL Graphics System: A Specification (Version 1.2). Mark segal& Kurt Akeley.
Silicon Graphics, Inc 1998
5. Ramiro Alcocer , enlace: www.geocities.com/valcoey/index.html
8. ANEXO 1
/* texture3D.cpp
Rotación de un Cubo, con la aplicación de Textura
Autor : Ramiro Alcocer
WWW : www.geocities.com/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
GLfloatxrot=0.0;
GLfloatyrot=0.0;
GLfloatzrot=0.0;
GLuint texture[1];
// unsigned
//parametros de la fuente de luz
GLfloatLightAmbient[]={ 0.5f, 0.5f, 0.5f, 1.0f };
GLfloatLightDiffuse[]={ 1.0f, 1.0f, 1.0f, 1.0f };
GLfloatLightPosition[]={ 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
}
intLoadGLTextures() // 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("foto.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
}
voidinit(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+=1.0f;
yrot+=1.0f;
zrot+=0.0f;
display();
}
int main(intargc, 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;
}
9. ANEXO 2
Código:
/* Método extraído de
http://www2.uah.es/rviana/texturasCuadrado.cpp
E-mail: raquel.viana@uah.es
*/
int num_texture=-1;
num_texture++; // The counter of the current texture is increased
if( (l_file = fopen(filename, "rb"))==NULL) return (-1); // Open the file for reading
// Now we need to allocate the memory for our image (width * height * color deep)
l_texture = (byte *) malloc(infoheader.biWidth * infoheader.biHeight * 4);
// And fill it with zeros
memset(l_texture, 0, infoheader.biWidth * infoheader.biHeight * 4);
// And store it
l_texture[j+0] = rgb.rgbtRed; // Red component
l_texture[j+1] = rgb.rgbtGreen; // Green component
l_texture[j+2] = rgb.rgbtBlue; // Blue component
l_texture[j+3] = 255; // Alpha value
j += 4; // Go to the next position
}