Aula Prática: Mapeamento de Textura em OpenGL
Disciplina: Computação Gráfica
Professora: Isabel Harb Manssour
 

O objetivo desta aula é aprender como trabalhar com mapeamento de textura em OpenGL. Nos exemplos e exercícios serão utilizadas as bibliotecas OpenGL, GLU, GLUT e GLAUX e o ambiente de programação Dev-C++. Inicialmente, faça o download das imagens e dos arquivos da GLAUX necessários para fazer o trabalho de hoje. Descompacte estes arquivos e coloque tudo numa mesma pasta no drive H. Depois, você deve criar um projeto para compilar e executar os programas (selecionar Menu Arquivo-Novo-Projeto; na janela aberta selecionar a "aba" Multimidia e depois o ícone da GLUT). Também será necessário incluir a biblioteca GLAUX neste projeto (selecionar Menu Projeto-Opções do Projeto e a "aba" parâmetros; clicar em adicionar e selecionar o arquivo GLAUX.LIB). Outra alternativa, seria pegar o projeto da aula prática de imagens e apenas trocar o arquivo fonte.

A primeira tarefa, consiste em compilar e executar o programa apresentado a seguir que exemplifica a utilização de mapeamento de textura. Certifique-se que as imagens estão na mesma pasta na qual o programa será executado.

 
// Textura.cpp - Isabel H. Manssour
// Um programa OpenGL que exemplifica a visualização 
// de objetos 3D com mapeamento de textura.
// Este código está baseado nos exemplos disponíveis no livro 
// "OpenGL SuperBible", 2nd Edition, de Richard S. e Wright Jr.

#include <gl/glut.h> 
#include <stdio.h>  
#include "glaux.h" 
                                                                        
//Função para Carregar uma imagem .BMP
AUX_RGBImageRec *LoadBMP(char *Filename){
	FILE *File=NULL;
	if (!Filename) {
		return NULL;         
	}
	File=fopen(Filename,"r");	
	if (File)	// Se o arquivo existe
	{
		fclose(File);			        
		return auxDIBImageLoad(Filename);//Retorna a imagem
	}
	return NULL;			
}

// Variáveis globais
GLfloat angle, fAspect, rotX, rotY, obsZ;
GLuint idTextura;
AUX_RGBImageRec *imagemTextura;           
       
// Função responsável pela especificação dos parâmetros de iluminação
void DefineIluminacao (void)
{
	GLfloat luzAmbiente[4]={0.2,0.2,0.2,1.0}; 
	GLfloat luzDifusa[4]={0.7,0.7,0.7,1.0};	   // "cor" 
	GLfloat luzEspecular[4]={1.0, 1.0, 1.0, 1.0};// "brilho" 
	GLfloat posicaoLuz[4]={0.0, -40.0, 0.0, 1.0};

	// Capacidade de brilho do material
	GLfloat especularidade[4]={1.0,1.0,1.0,1.0}; 
	GLint especMaterial = 60;

	// Define a refletância do material 
	glMaterialfv(GL_FRONT,GL_SPECULAR, especularidade);
	// Define a concentração do brilho
	glMateriali(GL_FRONT,GL_SHININESS,especMaterial);

	// Ativa o uso da luz ambiente 
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luzAmbiente);

	// Define os parâmetros da luz de número 0
	glLightfv(GL_LIGHT0, GL_AMBIENT, luzAmbiente); 
	glLightfv(GL_LIGHT0, GL_DIFFUSE, luzDifusa );
	glLightfv(GL_LIGHT0, GL_SPECULAR, luzEspecular );
	glLightfv(GL_LIGHT0, GL_POSITION, posicaoLuz );  
	
	// Habilita o modelo de colorização de Gouraud
	glShadeModel(GL_SMOOTH);
}
            
// Função callback chamada para fazer o desenho
void Desenha(void)
{
	// Limpa a janela e o depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Desenha um cubo no qual a textura é aplicada
	glBegin ( GL_QUADS );
		// Face frontal
		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);
		// Face posterior
		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);
		// Face superior
		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);
		// Face inferior
		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);
		// Face lateral direita
		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);
		// Face lateral esquerda
		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();

	glutSwapBuffers();
}

// Função usada para especificar a posição do observador virtual
void PosicionaObservador(void)
{
	// Especifica sistema de coordenadas do modelo
	glMatrixMode(GL_MODELVIEW);
	// Inicializa sistema de coordenadas do modelo
	glLoadIdentity();
	DefineIluminacao();
	// Especifica posição do observador e do alvo
	glTranslatef(0,0,-obsZ);
	glRotatef(rotX,1,0,0);
	glRotatef(rotY,0,1,0);
}

// Inicializa parâmetros de rendering
void Inicializa (void)
{ 
	// Define a cor de fundo da janela de visualização como preta
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
         
	// Habilita a definição da cor do material a partir da cor corrente
	glEnable(GL_COLOR_MATERIAL);
	//Habilita o uso de iluminação
	glEnable(GL_LIGHTING);  
	// Habilita a luz de número 0
	glEnable(GL_LIGHT0);
	// Habilita o depth-buffering
	glEnable(GL_DEPTH_TEST);

	// Inicializa a variável que especifica o ângulo da projeção
	// perspectiva
	angle=50;
    
	// Inicializa as variáveis usadas para alterar a posição do 
	// observador virtual
	rotX = 30;
	rotY = 0;
	obsZ = 10; 
    
	// Comandos de inicialização para textura
	imagemTextura = LoadBMP("imagem.bmp");
	glGenTextures(1, &idTextura);
	glBindTexture(GL_TEXTURE_2D, idTextura);
	glTexImage2D(GL_TEXTURE_2D, 0, 3, imagemTextura->sizeX, 
			imagemTextura->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
			imagemTextura->data);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glEnable(GL_TEXTURE_2D);    
}

// Função usada para especificar o volume de visualização
void EspecificaParametrosVisualizacao(void)
{
	// Especifica sistema de coordenadas de projeção
	glMatrixMode(GL_PROJECTION);
	// Inicializa sistema de coordenadas de projeção
	glLoadIdentity();

	// Especifica a projeção perspectiva(angulo,aspecto,zMin,zMax)
	gluPerspective(angle,fAspect,0.5,500);

	PosicionaObservador();
}

// Função callback chamada quando o tamanho da janela é alterado 
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
	// Para previnir uma divisão por zero
	if ( h == 0 ) h = 1;

	// Especifica as dimensões da viewport
	glViewport(0, 0, w, h);
 
	// Calcula a correção de aspecto
	fAspect = (GLfloat)w/(GLfloat)h;

	EspecificaParametrosVisualizacao();
}

// Função callback chamada para gerenciar eventos do mouse
void GerenciaMouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON)
		if (state == GLUT_DOWN) {  // Zoom-in
			if (angle >= 10) angle -= 5;
		}
	if (button == GLUT_RIGHT_BUTTON)
		if (state == GLUT_DOWN) {  // Zoom-out
			if (angle <= 130) angle += 5;
		}
	EspecificaParametrosVisualizacao();
	glutPostRedisplay();
}

// Callback para gerenciar eventos do teclado para teclas especiais 
void TeclasEspeciais(int key, int x, int y)
{
	switch (key)
	{
		case GLUT_KEY_LEFT:rotY--;
				break;
		case GLUT_KEY_RIGHT:rotY++;
				break;
		case GLUT_KEY_UP:rotX++;
				break;
		case GLUT_KEY_DOWN:rotX--;
				break;
		case GLUT_KEY_HOME:obsZ++;
				break;
		case GLUT_KEY_END:obsZ--;
				break;
		case GLUT_KEY_F10:// "camera reset"
				rotX=30;
				rotY=0;
				obsZ=10;
				angle=50;
				EspecificaParametrosVisualizacao();
				break;
	}
	PosicionaObservador();
	glutPostRedisplay();
}

// Programa Principal
int main(void)
{
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(400,350);
	glutCreateWindow("Visualizacao 3D com Mapeamento de Textura");
	glutDisplayFunc(Desenha);
	glutReshapeFunc(AlteraTamanhoJanela);
	glutMouseFunc(GerenciaMouse);
	glutSpecialFunc(TeclasEspeciais);
	Inicializa();
	glutMainLoop();
}

Após entender o funcionamento deste exemplo, faça as seguintes alterações no programa:

  1. Altere os filtros GL_LINEAR por GL_NEAREST e, utilizando zoom, verifique se há diferença de resolução.
  2. Acrescente o comando
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    antes de glEnable(GL_TEXTURE_2D) e acrescente o comando
    glColor3f(0.0f, 1.0f, 1.0f);
    antes de glBegin(GL_QUADS); compile e execute para verificar o resultado; experimente trocar o parâmetro GL_MODULATE por GL_DECAL e GL_BLEND e verifique o que acontece.
  3. Inclua os comandos
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);

    antes da chamada para a função glTexEnvi e altere as coordenadas de textura da face frontal da seguinte maneira:
    glTexCoord2f(-1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, -1.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
    glTexCoord2f(-1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

    Após executar o programa, altere o parâmetro GL_CLAMP para GL_REPEAT e execute-o novamente.
  4. Finalmente, altere o código acima para permitir trocar a imagem de textura; assim, quando o usuário pressionar F1 "imagem.bmp" deverá ser mapeada para o cubo, e quando o usuário pressionar F2 "leao.bmp" deverá ser mapeada.

 ../../Imagens/EMBAN15.GIF (1469 bytes)

../../Imagens/E-MAIL.JPG (3237 bytes) Comentários, dúvidas, sugestões, envie um mail para [email protected]

../../Imagens/EMBAN15.GIF (1469 bytes)

[Homepage CG]  [Homepage CG-SI]

Última alteração em 25 de outubro de 2006.