Computação Gráfica II

Trabalho Prático

Exercícios



Aula 4. Texturização

Os seguintes exercícios propõem prática e fixação do mapeamento de texturas usando OpenGL.


1. Especificando coordenandas de textura manualmente e usando múltiplas texturas.

Criem um objeto simples usando quads (para simplificar) ou triângulos em Opengl (não precisa usar a classe malha). Digamos, um cubo. Agora, usando 6 imagens de textura que vocês mesmos podem criar no Paint ou onde preferirem, transformem o cubo em um dado. Basicamente, será necessário passar as coordenadas dos vértices, um por um, e as coordenadas de textura, uma a uma. Será também necessário criar as 6 texturas a partir de 6 arquivos e fazer o binde de cada uma.



Fig. 1. Exemplo de resultado esperado

 

2. Combinando texturas

Agora, experimentem combinar duas ou mais texturas em um único objeto, sobrepondo-as.
Primeiro, criem um ambiente com mais de um objeto e mapeiem uma textura em cada. Têm total liberdade para escolher como modelar os objetos e como passar as coordenadas de textura. Para começar, eu sugiro usar os objetos que já usamos nas aulas anteriores e mesmo nesta.

Em seguida, experimentem mapear as duas texturas sobre o mesmo objeto. Como?

Usaremos uma extensão da OpenGL (ARB) que está definida no arquivo: #include <GL/glew.h>
Este arquivo permite fazer chamadas para a função:

glClientActiveTexture( id da textura ); // id da textura será GL_TEXTURE0 ou GL_TEXTURE1

Isso permite alterar parâmetros de cada textura separadamente. Assim, podemos usar o modo BLEND e MODULATE com o GL_TEXTURE_ENV_MODE para a segunda textura.

Baixem a glew a partir de: http://glew.sourceforge.net
Ajustem os includes e as libraries para o compilador e o ligador.

Usuários do Dev-C++:
O Dev-C++ não entende a estrutura do arquivo .lib da glew. Uma solução é usar a glew32.dll diretamente no ligador do Dev. Depois de baixar os binários Windows do site da GLEW, copiem o glew32.dll no diretório do seu projeto. No Dev-C++ façam:
> Project
> Project Options
> Parameters
> Add Library or Object
> Troque o Files Type para todos os arquivos (*.*)
> Selecione glew32.dll
> Clique OK

glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureObjects[0]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);


glActiveTexture(GL_TEXTURE1);
glEnable( GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,textureObjects[1]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Um detalhe que falta é que será preciso também enviar as coordenadas de textura separadamente para cada textura.

Com a abordagem clássica:

glBegin( GL_QUADS );
 
        glMultiTexCoord2f( GL_TEXTURE0_ARB, 0.0f, 0.0f );
        glMultiTexCoord2f( GL_TEXTURE1_ARB, 0.0f, 0.0f );
        glVertex3f( -1.0f, -1.0f, 0.0f );

        glMultiTexCoord2f( GL_TEXTURE0_ARB, 0.0f, 1.0f );
        glMultiTexCoord2f( GL_TEXTURE1_ARB, 0.0f, 1.0f );
        glVertex3f( -1.0f, 1.0f, 0.0f );

(...)

glEnd();

Com a abordagem mais moderna e rápida:

// na drawMesh ou função equivalente

  glVertexPointer(3,GL_FLOAT,0,m->verts); //passa os vértices

  glClientActiveTexture(GL_TEXTURE0);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer(2,GL_FLOAT,0,m->uvs);  // passa as coord de textura para a primeira textura

  glClientActiveTexture(GL_TEXTURE1);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer(2,GL_FLOAT,0,m->uvs); 
// passa as coord de textura para a segunda textura

  glDrawElements (GL_TRIANGLES,m->nbrTris*3,GL_UNSIGNED_INT,m->tris);

 

Obs. O mesmo efeito pode ser obtido carregando duas imagens, modulando as duas em uma terceira imagem e só então fazendo o bind dessa terceira imagem na textura. A modulação pode ser qualquer operação entre cada pixel. Se quiserem, experimentem intuitivamente várias possibilidades. Essa abordagem tem a desvantagem de ser processada via software na CPU, enquanto que a anterior é feita pelo hardware da GPU.

3. Textura de elevações

Estamos acostumados a usar texturas como imagens, carregando informação de cor. No entanto, existem diversas outra aplicações para a textura. Experimentem agora usar a informação da textura na modelagem de um terreno acidentado.

Carreguem dois arquivos de imagem: um em tons de cinza para as elevações; um colorido para a textura de cor do terreno.

O arquivo de elevações será usado em tempo de modelagem, dentro de uma função createMesh, que usará dois laços encadeados para gerar uma malha retangular de triângulos ou quads. Pensem em dar o número de triângulos ou quads e a altura máxima como parâmetro para a função. Dentro dela, para cada vértice gerado no plano (x, y), usem a imagem em cinza para produzir z. Por exemplo, se o valor (u, v) da imagem for preto, z será 0. Se for 1, z será a altura máxima. Outros tons de cinza gerarão alturas intermediárias.

Chamem a função na init() para gerar a malha. Exibam a malha gerada na display mapeando a textura de cor sobre ela. Experimentem usar cores que correspondem a altura. Por exemplo: altura 0 coloquem cor de água; altura acima de 3000 cor de neve.

4. Bump mapping e outros efeitos

Texturas também podem ser usadas para alterar o comprimento e a orientação dos vetores normais de uma malha para produzir efeitos de realismo, como relevo, sem alterar a geometria. Como as operações de rendering envolvendo as normais são executadas para cada pixel, em OpenGL padrão é bastante complicado aplicar bumps. Faremos bump e relieve mapping mais tarde quando estudarmos a programação de shaders. Aí, faremos implementações personalizadas do programa de shading de vértices e fragmentos para modular cores e normais.