No meu jogo, há um terreno semelhante ao Minecraft feito de cubos. Gero um buffer de vértice a partir dos dados do voxel e uso um atlas de textura para aparências de diferentes blocos:
O problema é que a textura de cubos distantes interpola com peças adjacentes no atlas de textura. Isso resulta em linhas de cores erradas entre os cubos (talvez seja necessário visualizar a captura de tela abaixo em tamanho real para ver as falhas gráficas):
Por enquanto, uso essas configurações de interpolação, mas tentei todas as combinações e mesmo GL_NEAREST
sem o mipmapping não fornece melhores resultados.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Também tentei adicionar um deslocamento nas coordenadas da textura para escolher uma área um pouco menor do ladrilho, mas como o efeito indesejado depende da distância da câmera, isso não pode resolver o problema completamente. A longas distâncias, as faixas ocorrem de qualquer maneira.
Como posso resolver esse sangramento de textura? Como o uso de um atlas de textura é uma técnica popular, pode haver uma abordagem comum. Infelizmente, por alguns motivos explicados nos comentários, não posso mudar para diferentes texturas ou matrizes de textura.
fonte
GL_LINEAR
que dá um resultado semelhante, ou escolhe o pixel mais próximo,GL_NEAREST
que também resulta em listras entre os blocos. A última opção mencionada diminui, mas não elimina a falha de pixel.Respostas:
Ok, acho que você tem dois problemas acontecendo aqui.
O primeiro problema é com o mipmapping. Em geral, você não deseja misturar ingenuamente atlas com mipmapping, porque, a menos que todas as suas subtexturas tenham exatamente 1 x 1 pixel de tamanho, ocorrerá um sangramento na textura. Adicionar preenchimento simplesmente moverá o problema para um nível mip mais baixo.
Como regra geral, para 2D, que é onde você costuma fazer atlas, você não mipmap; enquanto que para 3D, que é onde você mipmap, você não atlas (na verdade, você esfolia de tal maneira que o sangramento não será um problema)
No entanto, o que acho que está acontecendo com o seu programa agora é que você provavelmente não está usando as coordenadas de textura corretas e, por isso, suas texturas estão sangrando.
Vamos supor uma textura 8x8. Você provavelmente está obtendo o trimestre superior esquerdo usando coordenadas uv de (0,0) a (0,5, 0,5):
E o problema é que, na coordenada u 0,5, o amostrador interpolará o fragmento de destino usando metade do texel esquerdo e metade do texel direito. O mesmo acontecerá na coordenada u 0 e o mesmo nas coordenadas v. Isso ocorre porque você está abordando as fronteiras entre texels, e não os centros.
O que você deve fazer é abordar o centro de cada texel. Neste exemplo, estas são as coordenadas que você deseja usar:
Nesse caso, você sempre estará amostrando o centro de cada texel e não deverá receber nenhum sangramento ... A menos que você use o mipmapping, nesse caso, você sempre terá o sangramento começando no nível mip, onde a sub-textura escalada não está bem cabe dentro da grade de pixels .
Para generalizar, se você deseja acessar um texel específico, as coordenadas são calculadas como:
Isso é chamado de "correção de meio pixel". Há uma explicação mais detalhada aqui, se você estiver interessado.
fonte
Uma opção que será muito mais fácil do que mexer com mipmaps e adicionar fatores de difusão de coordenadas de textura é usar uma matriz de textura. As matrizes de textura são semelhantes às texturas 3d, mas sem mipmapping na 3ª dimensão, portanto, são ideais para atlas de texturas nas quais as "subtexturas" são do mesmo tamanho.
http://www.opengl.org/wiki/Array_Texture
fonte
Depois de lutar muito com esse problema, finalmente cheguei a uma solução.
Para usar ambos, um atlas de textura e mipmapping, eu mesmo preciso realizar a downsampling, porque o OpenGL interpolaria sobre os limites dos ladrilhos no atlas. Além disso, eu precisava definir os parâmetros corretos de textura, porque a interpolação entre os mipmaps também causaria sangramento na textura.
Com esses parâmetros, não ocorre sangramento.
Há uma coisa que você deve observar ao fornecer mipmaps personalizados. Como não faz sentido encolher o atlas, mesmo que cada bloco já esteja
1x1
, o nível máximo do mipmap deve ser definido de acordo com o que você fornece.Obrigado por todas as outras respostas e comentários muito úteis! A propósito, ainda não sei como usar o escalonamento linear, mas acho que não há como.
fonte
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
comoGL_NEAREST_MIPMAP_LINEAR
causa sangramento não pelo motivo do mipmapping, mas pelo motivo da interpolação. Portanto, neste caso, é equivalente,GL_LINEAR
já que o nível mais baixo do mipmap é usado de qualquer maneira.glTexImage2D()
. A GPU escolhe automaticamente o nível correto com base no tamanho dos objetos na tela.Parece que o problema pode ser causado pelo MSAA. Veja esta resposta e o artigo vinculado :
A solução é usar amostragem centróide. Se você estiver calculando o agrupamento das coordenadas da textura em um sombreador de vértice, mover essa lógica para o sombreador de fragmento também poderá corrigir o problema.
fonte
Este é um tópico antigo e tive um problema semelhante ao tópico.
Eu tinha minhas coordenadas de textura muito bem, mas lendo a posição da câmera (que mudou as posições dos meus elementos) da seguinte forma:
O problema todo foi que Util.lerp () retorna um número flutuante ou duplo. Isso foi ruim porque a câmera estava traduzindo fora da grade e causando alguns problemas estranhos nos fragmentos de textura que> 0 em X e> 0 em Y.
TLDR: não entre ou qualquer coisa usando carros alegóricos
fonte