10.3 Filtragem

Na amostragem de texturas, raramente temos um mapeamento \(1:1\) entre texels e pixels. Geralmente, cada pixel corresponde a vários texels, ou um mesmo texel pode ser mapeado a vários pixels.

Tanto o problema de minificação (mais de um texel mapeado para um único pixel) quanto de magnificação (mais de um pixel mapeado para um mesmo texel) exigem o uso de filtros de interpolação para calcular a cor correspondente a uma posição \((u,v)\) no espaço da textura. No OpenGL, o funcionamento desses filtros pode ser configurado de forma independente usando os identificadores GL_TEXTURE_MAG_FILTER e GL_TEXTURE_MIN_FILTER com a função glTexParameteri.

Magnificação

Os filtros de magnificação (GL_TEXTURE_MAG_FILTER) são dois:

  • Interpolação por vizinho mais próximo (GL_NEAREST): consiste em usar o valor do texel que está mais próximo da posição \((u,v)\) de amostragem, considerando a menor distância Manhattan entre os quatro texels mais próximos. Assim, os texels da textura aumentada têm um aspecto pixelado. Esse modo pode ser habilitado com

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  • Interpolação bilinear (GL_LINEAR): consiste em realizar uma média entre os quatro texels mais próximos da posição \((u, v)\) de amostragem. Isso é feito calculando a interpolação linear entre dois pares de texels em uma direção (por exemplo, direção \(u\)), e calculando em seguida a interpolação linear dos dois valores resultantes na outra direção (por exemplo, direção \(v\)). Essa é a filtragem padrão do OpenGL. A interpolação bilinear é ativada com

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

A figura 10.15 mostra a comparação entre os dois filtros em um mesmo detalhe ampliado de textura.

Exemplo de uso de filtros de magnificação do OpenGL.

Figura 10.15: Exemplo de uso de filtros de magnificação do OpenGL.

Minificação

Os filtros de minificação do OpenGL (GL_TEXTURE_MIN_FILTER) também incluem os filtros de interpolação por vizinho mais próximo (GL_NEAREST) e interpolação bilinear (GL_LINEAR), e podem ser ativados respectivamente com

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

e

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Entretanto, na minificação, é possível que mais do que quatro texels sejam mapeados para um mesmo pixel. Em tais casos, a filtragem bilinear usando somente os quatro vizinhos mais próximos não é suficiente, e erros de aliasing podem ser introduzidos. Uma forma eficiente de reduzir esse problema é através da técnica de mipmapping.

Mipmapping

Um mipmap é uma sequência ordenada de texturas repetidas, cada uma com metade da resolução da textura anterior. O nível base ou nível 0 do mipmap é a textura em sua resolução original. A textura do nível seguinte contém metade da resolução da textura do nível anterior. No último nível do mipmap, a textura tem tamanho \(1 \times 1\). A figura 10.16 mostra todos os níveis de um mipmap para uma textura de resolução \(256 \times 256\).

Níveis de mipmap.

Figura 10.16: Níveis de mipmap.

Se a textura é quadrada e a resolução é uma potência de dois, um texel de um nível do mipmap é definido de tal forma que seu valor é exatamente a média entre quatro texels do nível anterior. Isso pode ser visto na figura 10.17, que mostra o detalhe ampliado dos três últimos níveis do mipmap da figura 10.16. Observe, no nível 8, que a cor do único texel resultante é cinza. Essa cor cinza é a média de todos os texels do nível anterior (nível 7), que é o mesmo que a média de todos os texels da textura. De forma semelhante, no nível 7, o texel mais escuro (canto inferior esquerdo) é a média dos texels de \((0,0)\) até \((0.5, 0.5)\) dos níveis anteriores.

Detalhe ampliado dos três últimos níveis de um mipmap.

Figura 10.17: Detalhe ampliado dos três últimos níveis de um mipmap.

A figura 10.18 mostra uma comparação da qualidade de renderização de um padrão de xadrez sobre um plano, sem e com mipmapping. A renderização sem mapping introduz artefatos de aliasing espacial resultantes da subamostragem.

Comparação de renderização sem mipmapping (esquerda) e com mipmapping (direita) ([fonte](https://commons.wikimedia.org/wiki/File:Mipmap_Aliasing_Comparison.png)).

Figura 10.18: Comparação de renderização sem mipmapping (esquerda) e com mipmapping (direita) (fonte).

No OpenGL, um mipmap pode ser gerado facilmente com a função glGenerateMipmap. Quando a função é chamada, o mipmap é gerado para a textura atualmente ligada com glBindTexture. Por exemplo,

glBindTexture(GL_TEXTURE_2D, textureID);
glGenerateMipmap(GL_TEXTURE_2D);

gera o mipmap para a textura com identificador textureID.

Mipmapping é a técnica de filtrar texels usando mipmaps. Quando uma textura com mipmap é amostrada, o amostrador primeiro determina qual nível do mipmap será utilizado. Isso é calculado com base na estimativa do número de texels mapeados para o pixel. Por exemplo, se a área do texel projetado no espaço da janela é tal que todos os texels da textura cabem em um único pixel, então a textura amostrada é a textura do último nível (textura \(1 \times 1\)), pois o texel dessa textura contém a média de todos os texels.

No OpenGL, há diferentes modos de filtragem usando mipmapping (válido apenas para GL_TEXTURE_MIN_FILTER):

  • GL_NEAREST_MIPMAP_NEAREST: escolhe o nível de mipmap que mais se aproxima do tamanho do pixel que está sendo texturizado, e então amostra tal nível usando a interpolação por vizinho mais próximo.
  • GL_LINEAR_MIPMAP_NEAREST: escolhe o nível de mipmap que mais se aproxima do tamanho do pixel que está sendo texturizado, e então amostra tal nível usando a interpolação bilinear (média dos quatro texels mais próximos).
  • GL_NEAREST_MIPMAP_LINEAR: escolhe os dois níveis de mipmap que mais se aproximam do tamanho do pixel que está sendo texturizado, e então amostra os dois níveis usando a interpolação por vizinho mais próximo. O valor final é então calculado como a média entre os dois valores amostrados, ponderada de acordo com a proximidade dos níveis de mipmap ao tamanho do pixel. Esse é o modo padrão de filtro de minificação.
  • GL_LINEAR_MIPMAP_LINEAR: escolhe os dois níveis de mipmap que mais se aproximam do tamanho do pixel que está sendo texturizado, e então amostra os dois níveis usando interpolação bilinear. O valor final é então calculado como a média entre os dois valores amostrados, ponderada de acordo com a proximidade dos níveis de mipmap ao tamanho do pixel.

O modo GL_LINEAR_MIPMAP_LINEAR também é chamado de interpolação trilinear, pois faz uma interpolação linear sobre dois valores obtidos com interpolação bilinear. Esse é o modo de filtragem que produz resultados com menos artefatos de aliasing, mas também é o mais custoso.