Aula Prática: Mapeamento de Textura 2D em OpenGL
Disciplina: Computação Gráfica
Professora: Isabel Harb Manssour e Márcio S. Pinho
 

O objetivo desta aula é aprender a utilizar mapeamento de textura em OpenGL. Para isto, será utilizada a API JOGL e a linguagem de programação Java, tendo como resultado um programa que pode ser executado tanto no ambiente Windows como no ambiente Linux.

Para implementação de aplicações com JOGL na linguagem de programação Java é necessário configurar um projeto para linkar as bibliotecas. Na primeira aula prática já foi explicado como configurar o projeto para o ambiente Eclipse, portanto, basta criar um novo projeto no drive H, configurá-lo conforme explicado e incluir os programas fonte e imagens que serão usados nesta aula. Para facilitar, deixe as imagens na pasta do projeto junto com os programas fonte.

O mapeamento de textura 2D em OpenGL consiste em carregar uma imagem de um arquivo e "colar" esta imagem na superfície do(s) objeto(s). É importante salientar que a largura e a altura desta imagem devem ser potências de 2. A utilização de mapeamento de textura é um procedimento complexo em OpenGL, pois existem muitas variações e diversas funções de manipulação. Nesta aula prática, serão apresentados alguns exemplos e conceitos básicos da sua utilização.

A primeira tarefa, consiste em compilar e executar o programa que exemplifica a utilização de mapeamento de textura. A imagem abaixo deverá ser apresentada.

Observe como foram implementados os métodos loadImage, init e display, nesta ordem. Analisando os comentários do código fonte, observa-se que, de maneira simplificada, os passos para o mapeamento de textura são:
- Ler uma imagem e armazenar num objeto adequado;
- Criar um identificador para a textura;
- Definir a textura em OpenGL;
- Especificar como a textura será aplicada em cada pixel (filtros);
- Habilitar o mapeamento de textura;
- Desenhar os objetos fornecendo uma coordenada de textura para cada coordenada geométrica.

Os parâmetros passados para o método public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, Buffer pixels), que faz o envio da textura para OpenGL, são:
-target: GL_TEXTURE_2D;
-level: nível de detalhe da imagem de textura;
-internalFormat:número de valores de cor para cada pixel (RGB=3, RGBA=4);
-width e height: tamanho da imagem de textura (devem ser potências de 2);
-border: deve ser 0;
-format: tipo de valor de cor esperado (GL_ALPHA, GL_COLOR_INDEX, GL_BGR , GL_RGB, GL_RGBA, ...);
-type: indica o formato e tipo de dado (GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_BITMAP, ...);
-pixels: textura.

OpenGL tem três modos de textura:
-GL_MODULATE: Ajusta valores de cor e iluminação com a imagem de textura (mais usado);
-GL_DECAL: Usa apenas a imagem de textura (cor e iluminação não alteram a aparência da textura)
-GL_BLEND: Usado com um ou dois componentes de textura (imagem de textura é misturada com a cor de textura e com as informações de cor e iluminação). O método para especificação do modo de textura é: public void glTexEnvi(int target, int pname, int param). O primeiro parâmetro, neste caso, deve ser GL_TEXTURE_ENV, o segundo deve ser GL_TEXTURE_ENV_MODE e o terceiro pode ser GL_DECAL,GL_REPLACE, GL_MODULATE,GL_BLEND.

Para verificar como funcionam estes diferentes modos de textura, acrescente a chamada para o método abaixo como último comando do método init. Altere também a cor para magenta(1.0f, 0.0f, 1.0f) na chamada para gl.glColor3f que aparece logo acima de gl.glBegin(GL_QUADS) no método display.
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
Compile e execute a aplicação para verificar o resultado. Experimente trocar o parâmetro GL.GL_MODULATE por GL.GL_DECAL e GL.GL_BLEND e verifique o que acontece.

Filtros de textura são usados para interpolar pixels de textura. Dois tipos são fornecidos em OpenGL:
-GL_TEXTURE_MIN_FILTER para polígonos que são menores que a imagem de textura;
-GL_TEXTURE_MAG_FILTER para polígonos que são maiores que a imagem de textura.
O método usado para especificar estes filtros é glTexParameteri, e o seu último parâmetro corresponde ao filtro. Este último parâmetro pode ser GL.GL_NEAREST, GL.GL_LINEAR, GL.GL_NEAREST_MIPMAP_NEAREST, etc.

Agora altere os filtros GL.GL_LINEAR usados no método init por GL.GL_NEAREST e, utilizando zoom, verifique se há diferença de resolução. Experimente também usar as diferentes imagens fornecidas (ex. imagem1.jpg e imagem2.jpg) para ver o resultado.

As coordenadas de textura associam um ponto específico na imagem de textura com vértices de um polígono, conforme ilustra a figura abaixo. O método usado para especificar estas coordenadas é:
public void glTexCoord2f(float s, float t)
Os parâmetros s e t indicam as coordenadas para os eixos horizontais e verticais da imagem, respectivamente. Neste caso, por exemplo, t é 0.0 para o pixel mais abaixo na imagem de textura e 1.0 para o pixel mais acima.

Coordenadas de textura normalmente possuem valores entre 0.0 e 1.0. Para valores fora deste intervalo elas são:
-Clamped (GL.GL_CLAMP);
-Repeated (GL.GL_REPEAT).
O método para especificar como serão tratados os valores fora deste intervalo é glTexParameteri, mas, neste caso, o segundo parâmetro deve ser GL.GL_TEXTURE_WRAP_S ou GL.GL_TEXTURE_WRAP_T, e o terceiro parâmetro pode ser GL.GL_CLAMP ou GL.GL_REPEAT.

Para exemplificar como funciona o texture wrapping, acrescente as linhas de código abaixo no final do método init, mas antes da chamada para o método gl.glTexEnvi.
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);

Logo em seguida, altere as coordenadas de textura da face frontal da seguinte maneira:
gl.glTexCoord2f(-1.0f, -1.0f); gl.glVertex3f(-1.0f, -1.0f, 1.0f);
gl.glTexCoord2f(1.0f, -1.0f); gl.glVertex3f( 1.0f, -1.0f, 1.0f);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 1.0f);
gl.glTexCoord2f(-1.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 1.0f);

Após executar o programa, altere o parâmetro GL.GL_CLAMP para GL.GL_REPEAT e execute-o novamente.

Você deve estar se perguntando como seria possível aplicar o mapeamento de textura na esfera se não sabemos as coordenadas dos vértices para associar com as coordenadas de textura? Bom, neste caso é necessário fazer uma geração automática das coordenadas de textura. Para ver um exemplo, siga os passos listados a seguir:

1) Verifique no método init se estão sendo passados os parâmetros exibidos abaixo para cada chamada de método.
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR);

gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);

gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);


2) Acrescente os comandos abaixo antes de desenhar o cubo e logo após o comentário "// Desenha um cubo no qual a textura é aplicada".
gl.glDisable(GL.GL_TEXTURE_GEN_S);
gl.glDisable(GL.GL_TEXTURE_GEN_T);


3) Acrescente os comandos abaixo antes de desenhar a esfera e logo após o comentário "// Desenha uma esfera azul". Cuide para que o método glColor3f seja chamado apenas uma vez com a cor branca.
gl.glEnable(GL.GL_TEXTURE_2D);

float texgen_s[] = {0.5f, 0.0f, 0.0f, 0.5f};
float texgen_t[] = {0.0f, 0.5f, 0.0f, 0.5f};

gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);
gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);

gl.glTexGenfv(GL.GL_S, GL.GL_OBJECT_PLANE, texgen_s, 0);
gl.glTexGenfv(GL.GL_T, GL.GL_OBJECT_PLANE, texgen_t, 0);

gl.glEnable(GL.GL_TEXTURE_GEN_S); // Habilita a geração da textura
gl.glEnable(GL.GL_TEXTURE_GEN_T);

gl.glColor3f(1.0f, 1.0f, 1.0f);

Compile e execute a aplicação para ver o resultado.

Para finalizar a aula de hoje, experimente alterar o código desta aplicação para permitir aplicar uma textura diferente para cada objeto. Lembre-se que através da chamada ao método gl.glBindTexture é possível especificar qual é a "textura corrente" e que é necessário gerar um identificador para cada textura.

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

../../Imagens/E-MAIL.JPG (3237 bytes) Comentários, dúvidas, sugestões, envie um mail para seu(sua) professor(a)

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

Última alteração em 06 de junho de 2010.