Texturas – Parte 2

27 08 2008

No artigo passado, vimos o que são texturas e como mapea-las em nossos polígonos. Neste artigo, veremos as principais configurações do ambiente e dos parâmetros que afetam o desenho das texturas.

Parâmetros de texturas

Aplicar texturas não se resume simplesmente a recortar uma imagem na área de nossa geometria, seguindo as diretrizes do mapeamento. O OpenGL muitas vezes precisa distorcer a imagem, esticá-la, rotacioná-la e misturar parte de seus pixels, para criar um efeito mais realista.

Podemos dar ao OpenGL uma série de parâmetros que dizem a ele como ele deve fazer esse trabalho. Isso inclui que tipo de algoritmos ele deve usar para redimensionar a textura, se a imagem deve ou não ser repetida, ou mesmo, o que acontece nas bordas (entre duas texturas).

Os parâmetros são definidos através das funções glTexParameter[fi](GLenum target, GLenum pname, GLfloat param); e glTexParameter[fi]v(GLenum target, GLenum pname, GLfloat* params);. O primeiro argumento indica ao OpenGL sobre que modo de textura deve ser aplicado. Como no artigo anterior, o valor desse parâmetro pode ser GL_TEXTURE_1D, GL_TEXTURE_2D ou GL_TEXTURE_3D. O segundo, indica qual parâmetro está sendo alterado e, finalmente, o terceiro, indica o novo valor do parâmetro.

É importante ressaltar que os parâmetros são definidos por textura. Isso significa que antes de executar esses comandos, devemos necessariamente ter dado o bind na textura desejada, da mesma forma que fizemos no artigo anterior.

Filtragem

Se o polígono for desenhado num tamanho maior que o da textura, cada pixel da textura (texel) corresponderá a um grupo de vários pixels nesse polígono, ou seja, a textura sofrerá ampliação (magnification). 

Por outro lado, se a textura for maior que o polígono, cada pixel na tela corresponderá a vários texels e, portanto, a textura terá que sofrer miniaturização (minification). O processo de cálculo dos fragmentos de cor de uma imagem esticada ou reduzida é chamado filtragem. Filtros para esses dois processos podem ser parametrizados através das constantes GL_TEXTURE_MAG_FILTER e GL_TEXTURE_MIN_FILTER.

O processo mais simples e rápido de filtragem é chamado “vizinho mais próximo” (Nearest neighboor) e corresponde ao valor GL_NEAREST. Neste processo, simplesmente calcula-se onde o pixel estaria situado na textura através de uma divisão simples e, a cor do pixel correspondente na textura é pintada na imagem. Esse tipo de textura é caracterizado por pixels largos e quadrados, quando a textura é muito esticada.

O segundo tipo de filtro é chamado interpolação bilinear, e é definido através da constante GL_LINEAR. Esse processo de filtragem calcula a média entre até quatro pixels de textura desde que correspondam a um determinado pixel da tela. O cálculo é ponderado de acordo com a distância. Isso evita uma mudança brusca de cor nos cantos e dá um efeito muito melhor durante a ampliação. Esse processo tem um custo praticamente desprezível para as placas de vídeo atuais, embora certamente seja mais custoso que a filtragem do vizinho mais próximo. Ele também gera uma imagem “embaçada”, mas com aparência muito mais realista do que os quadrados do filtro anterior.

Compare o resultado da ampliação de uma textura em quatro vezes usando os dois processos:

Por padrão o OpenGL ainda suporta outros tipos de filtragem, mas somente usadas em conjunto com mipmaps. Veremos esse assunto no próximo artigo.

Texture wrap

Wrap é uma palavra inglesa que significa “embalar, recobrir”. Normalmente, mapeamos as coordenadas de textura com coordenadas entre 0.0 e 1.0. A política de wrapping diz ao OpenGL o que fazer se as coordenadas de textura estiverem fora desses valores.

Vocë pode definir o parâmetro individualmente para as coordenadas de textura r, s ou t. Para isso, use as constantes GL_TEXTURE_WRAP_R, GL_TEXTURE_WRAP_S ou GL_TEXTURE_WRAP_T. Existem quatro modos de wrapping disponíveis, são eles:

  • GL_REPEAT: Faz com que a textura se repita a cada adição de 1 na coordenada máxima da textura. É bastante útil para desenhar uma parede ou gramado, onde uma pequena textura pode ser repetida lado-a-lado para formar um padrão maior, evitando assim incorrer em custos de memória. Por exemplo, para repetir a textura 5 vezes na vertical, deveríamos mapear os vértices da direita do polígono com glTexCoord2f(5.0f, y);
  • GL_CLAMP: Todas área que cair fora do intervalo de 0 até 1 ficará com a cor da borda, definida no parâmetro GL_TEXTURE_BORDER_COLOR, que é definido através da função glTexParameterf.
  • GL_CLAMP_TO_EDGE: Força com que área fora do intervalo tenha exatamente as mesmas cores dos texels mais próximos do canto . Esse é o modo ideal para quando você quiser esconder totalmente as bordas de seu polígono.
  • GL_CLAMP_TO_BORDER: Similar ao GL_CLAMP, mas usará pixels da borda da textura, que será carregada de forma especial. A borda será definida por uma linha e uma coluna a mais, ao redor da textura. Note que, se a imagem estiver dentro do intervalo correto, a borda náo aparecerá, do contrário do que ocorreria no caso do GL_CLAMP_TO_EDGE.

Parâmetros do ambiente

Além dos parâmetros individuais de cada textura, também podemos configurar qual é o ambiente em que as texturas serão aplicadas. Esse ambiente afeta todas as texturas do ponto onde foi declarado em diante e define como as cores da imagem são combinadas com a textura. Os parâmetros do ambiente podem ser alterados usando as funções:

glTexEnv[fi](GLenum target, GLenum pName, GLfloat param);
glTexEnv[fi]v(GLenum target, GLenum pName, GLfloat* param);

O primeiro parâmetro deve sempre ter o valor GL_TEXTURE_ENV. No segundo parâmetro indicamos se queremos modificar o ambiente, através da constante GL_TEXTURE_ENV_MODE ou se estamos modificando a cor, com GL_TEXTURE_ENV_COLOR. Finalmente, usamos o terceiro parâmetro para indicar o novo valor desejado.

Por exemplo, podemos definir o ambiente para GL_MODULATE através do comando:
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Esse modo multiplica os valores dos pixels da textura pela cor da geometria, depois de todos os cálculos de iluminação terem sido feitos. Assim, é possível alterar a cor da textura só mudando a cor da geometria. Por exemplo, você poderia ter uma textura de pêlo branca e preta, e criar animais coloridos só variando a cor da geometria.

Similarmente, você pode definir o ambiente para GL_ADD. Assim, ao invés de multiplicar as cores das texturas pela cor do objeto, você somará. Isso cria um efeito de brilho sobre as áreas claras da textura, enquanto o que for colocado em preto na textura permanecerá inalterado.

O ambiente GL_REPLACE pode ser usado para descartar a cor da geometria e simplesmente substitui-la pela cor da textura. Assim, qualquer efeito de iluminação será descartado. Se a textura tiver áreas transparentes, o polígono ficará transparente naquelas áreas. Uma substituição pura e simples.

O GL_DECAL comporta-se de maneira muitíssimo parecida com o GL_REPLACE. A diferença está unicamente nas áreas com transparência. Nesse caso, a transparência será aplicada sobre a cor original do polígono, como se a textura fosse simplesmente “decalcada” sobre ele.

As texturas também podem ser transparentes de acordo com uma cor de transparência constante. Isso é bastante útil para texturas sem o canal alfa. Nesse caso, define-se a variável o ambiente como GL_BLEND e é necessário definir a cor que será usada para isso. O exemplo abaixo mostra essa situação:

//Define rosa-choque como cor de transparência
//Essa é uma opção muito comum.
GLfloat blendColor = {1.0f, 0.0f, 1.0f, 0.0f};
//Dizemos que o ambiente é blend
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
//Definimos a cor de transparência
glTextEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,blendColor);

Estudaremos transparência em detalhes em um artigo futuro.

Concluindo

Nesse artigo, vimos vários parâmetros que afetam como a textura é desenhada sobre a tela. Entender esses conceitos é importante pois afeta diretamente a qualidade da cena final. No próximo artigo, veremos a técnica de mipmaping e mais opções de filtros que podem ser utilizados em conjunto com essa técnica.


Ações

Informações

9 respostas

3 09 2008
marcos

opa!
estou usando o glGenTextures(), mas a aplicação não consegue gerar a textura.. passo glGenTextures(1,&id), antes de chamar o glGenTextures coloco id=10 e depois do glGenTextures id continua com valor 10.
tentei usar o glGetError, mas não tem nenhum erro.

eu também peguei o tutorial o nehe, lesson 6, e coloquei os parametros de inicialização do gl e do sdl nele e ele funciona.. mas quando coloco no meu código a forma como ele carrega a textura e a exibição daí naum funciona…

você tem alguma idéia de pq na minha aplicação o gl naum aloca o espaço para a textura, e nos exemplos no nehe funcina certo…

valeu

14 10 2008
João Godoy

Olá Vinicus

Muito bom o blog, as informações são muito uteis, espero que continuem as postagens

No inicio do blog você indica o CodeBloc, mais prefiro muito mais o DevC++, depois de configurado não fica tao horrivel, XD, mais gosto é gosto

Fiz um package para ser instalado no DevC++, bem simples, so os includes, bibliotecas, DLL e um arquivo fonte de exemplo, que alias é foi tirado do seu blog, dai coloquei o endereço deste blog nos comentarios do codigo fonte

Vou distribuir para uns amigos, se quiser dar uma olhada posso mandar por email

22 10 2008
vinigodoy

Cara, eu desaconselho totalmente o DevCpp e não é só por uma questão de gosto. A IDE tem a inconveniente mania de não mostrar todas as mensagens de erro corretamente.

Como é muito antiga, a integração com o depurador fica seriamente comprometida, o que é uma perda significativa de funcionalidade (eu não me imagino programando sem um debugger decente).

Aliás, são poucos os programadores que atualizam o MinGW pré-histórico, que vem na distribuição básica do Dev. E com isso, não tem acesso aos últimos recursos de templates usados na boost, ou as atualizações da STL.

Fora que é um produto abandonado. Não há a menor possibilidade desses bugs serem corrigidos no futuro. Por essas e outras, recomendo uma IDE que esteja em manutenção, seja ela o Code::Blocks (opção multi-plataforma) ou o Visual C++ (Windows).

7 11 2008
Ironlynx

Me fez lembrar das aulas de computação gráfica na universidade.Bem escrito(como sempre) vini!

4 12 2008
Andre Brito

ViniGodoy, tá vivo cara? Faz tempo que não tenha notícias suas…
Abraço.

4 12 2008
vinigodoy

Sim, mas está tudo muito corrido.
Mas ainda não foi dessa vez que bati as botas. =D

5 12 2008
andrejammer

A bom… Porque você está me devendo um artigo :)
Abraço.

25 08 2009
Thiago

E ae Vini, acho muito bom seu site cara!
Que aconteceu que você sumiu?!?!
Faz tempo que não atualiza o seu blog…!

Abraços!!

26 08 2009
vinigodoy

Pois é, passei por uns problemas pessoais, troquei de emprego e aí complicou para eu escrever o blog. Depois, quando quis voltar, já tinha meio que perdido o fio da meada.
Estou pensando em reformular geral, provavelmente num domínio próprio.

E, claro, migrar os textos do blog para lá.

Deixe um comentário