Ponto V!

Home OpenGL Texturas – Parte 2
Vinícius Godoy de Mendonça
Texturas – Parte 2Imprimir
Escrito por Vinícius Godoy de Mendonça

No artigo passado, vimos o que são texturas e como mapeá-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. A 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 à OpenGL uma série de parâmetros que dizem a ela 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 à OpenGL sobre que modo de textura deve ser aplicada. 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:

Exemplo de filtros

Por padrão a 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 à 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.


Comentários (14)
  • Irving  - Problema
    avatar

    Ola , cara estou com um problema bem chato aqui.

    Tem certas imagens que se eu passar a largura e altura verdadeira da imagem na funcao glTexImage2d() da um erro que retorna 3.
    Porém se eu passo para glTexImage2d() valores de largura e altura menores do que o real , o programa até funciona porém a textura fica toda deformada.
    :(

    Você tem alguma ideia do que possa ser??
    desde já agradeço

    Esperando ansiosamente um novo artigo de um novo artigo :)

  • Bruno Crivelari Sanches
    avatar

    Quais são as dimensões?

  • Vinícius Godoy de Mendonça
    avatar

    Observe que no artigo 1 sobre texturas explico que:
    muito importante saber que até a OpenGL 2.0 esses valores tinham, obrigatoriamente, que ser potências de 2 (2,4,8,16,32,64,128,256, …). Não era necessário que a textura tivesse os dois lados iguais"

    Essa regra está sendo respeitada? Boa parte das placas, mesmo em versões posteriores da OpenGL ainda irão exigir essa regra, caso não sejam usadas funções específicas.

  • Irving  - Problema
    avatar

    Bom eu só uso dimensões que são potência de dois . Como você deixou bem claro no artigo.

    Por exemplo eu estou utilizando a figura 1.png que vem junto com a source code do outro capitulo de textura. Ela tem 512 pixel de largura e 512 pixel de altura. Bom se eu utilizo diretamente as dimesões guardadas na SDL_Surface na função glTexDraw2d() , acontece um erro e retorna 3.
    Porém seu coloco por exemplo 512 por 256 , não há erro . Mas a figura fica muito estranha.

    O que vem me deixando mais encucado . É que quando eu utilizo uma outra figura PNG com 128 por 128 e passo as dimensões da SDL_SURFACE para a glTexDraw2d() , dá certo.Ou seja certas figuras dão certo outras não.

    Alguma ideia ??

    abração


  • Vinícius Godoy de Mendonça
    avatar

    Muito estranho. Qual placa de vídeo você tem?

  • Irving  - problema
    avatar

    Minha placa de video a Intel gma 4500M.

  • irving
    avatar

    Olha eu de novo aqui para encher teu saco

    Para tentar resolver esse problema eu comecei a converter a imagem 1.png para outros tipos de imagens.

    A unica que deu certo foi a do tipo TIF.
    O restante das outras imagens convertidas ou ficaram com uma cor verde ou simplesmente não abriram.

    Bom não sei realmente o porquê disso. Acho também muito estranho que certas imagens em png rodem e outras não.

    abração

  • Bruno Crivelari Sanches
    avatar

    Bom, agora acredito que esteja errado o código que esta enviando as texturas para o OpenGL, tem como postar esse trecho?

  • Irving
    avatar

    Aqui está o código que cria a textura

    void Texture::createTexture(char * file,GLuint d){
    SDL_Surface * img = IMG_Load(file);

    if(img == NULL)
    exit(9);

    setId(d);
    setWidth(img->w);
    setHeight(img->h);


    glGenTextures(1,&d);

    glBindTexture(GL_TEXTURE_2D,id);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER , GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    GLint format ;
    if( img->format->BitsPerPixel == 3)
    format = GL_RGB;
    else
    format = GL_RGBA;

    glTexImage2D(GL_TEXTURE_2D,0,format,getWidth(),getHeight(),0,format,GL _UNSIGNED_BYTE , img->pixels);

    SDL_FreeSurface( img);


    GLenum err = glGetError ();
    if (GL_NO_ERROR != err)
    throw std::runtime_error("Error when creating texture!";);

    }

  • Bruno Crivelari Sanches
    avatar

    Ok,
    vamos lá:
    nem toda imagem é RGB ou RGBA, pode ser BGRA, tem que checar isso na hora de determinar os parâmetros, que nem é comentado no artigo.

    >>if(img->format->BitsPerPixel == 3)

    Aha! BitsPerPixel? O certo seria BytesPerPixel. Sem falar que o else ali deveria checar se são 4 bytes per pixel, porque podem ser menos.

    T+

  • Irving
    avatar

    Valews deu certo!!
    :D

    So foi trocar os bits por bytes e pronto. Iniciante é foda hem!!

    Brigadão realmente pela ajuda e desculpa ae por qualquer coisa.

    Abração

  • Joaozinho  - Problema com transparência
    avatar

    Estou tentando usar a SDL 2.0 com a opengl 2.1, meu pc ta meio velho e não da suporte pra nada mais novo do que isso, mas li em algum lugar que os conceitos principais estão na opengl desde o começo, indo direto ao ponto: eu carrego umas imagens .jpg com o fundo transparente, crio as texturas, na hora de desenhar não existe transparência, os locais que deveriam ser transparentes ficam brancos(ou a última cor definida com glColor). Poderia me explicar como solucionar esse problema?

    Agora uma nota: os artigos estão com uma explicação excelente, acho que seria bom dar continuidade e introduzir novos conceitos, estou entrando no mundo da opengl por agora e já vi muitas coisas como shaders, pipeline programável, sinceramente que vou levar muito tempo pra ler sobre tudo isso, testar e aprender, ainda mais agora que estou na faculdade, se tivesse aqui no blog uma série sobre esses temas, e tão bem explicados como os atuais acho que seria uma ótima forma de facilitar o aprendizado de todos os interessados, mas entendo que como professor você deve estar sempre ocupado.

  • Fernando Souza  - Vídeo como textura
    avatar

    Gostaria de saber se existe algum modo de usar um vídeo como textura, ou se tem como apenas carregar um vídeo usando openGL. Obrigado

Escrever um comentário
Your Contact Details:
Gravatar enabled
Comentário:
[b] [i] [u] [url] [quote] [code] [img]   
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):S:!::?::idea::arrow:
Security
Por favor coloque o código anti-spam que você lê na imagem.
LAST_UPDATED2  

Busca

Linguagens

Twitter