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:
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.
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
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
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).
Me fez lembrar das aulas de computação gráfica na universidade.Bem escrito(como sempre) vini!
ViniGodoy, tá vivo cara? Faz tempo que não tenha notícias suas…
Abraço.
Sim, mas está tudo muito corrido.
Mas ainda não foi dessa vez que bati as botas. =D
A bom… Porque você está me devendo um artigo
Abraço.
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!!
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á.