Dans mon jeu, il y a un terrain ressemblant à Minecraft fait de cubes. Je génère un vertex buffer à partir des données voxel et utilise un atlas de texture pour l’apparence de différents blocs:
Le problème est que la texture des cubes distants s’interpole avec les carreaux adjacents dans l’atlas de texture. Cela se traduit par des lignes de couleurs incorrectes entre les cubes (vous devrez peut-être afficher la capture d'écran ci-dessous à sa taille maximale pour voir les défauts graphiques):
Pour le moment, j'utilise ces paramètres d'interpolation, mais j'ai essayé toutes les combinaisons et même GL_NEAREST
sans mappage, les résultats ne sont pas meilleurs.
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);
J'ai également essayé d'ajouter un décalage dans les coordonnées de la texture pour sélectionner une zone légèrement plus petite de la mosaïque, mais comme l'effet indésirable dépend de la distance qui le sépare de la caméra, le problème ne peut pas être résolu complètement. De loin, les rayures apparaissent quand même.
Comment puis-je résoudre ce saignement de texture? Étant donné que l’utilisation d’un atlas de texture est une technique populaire, il peut exister une approche commune. Malheureusement, pour certaines raisons expliquées dans les commentaires, je ne peux pas utiliser différentes textures ou tableaux de textures.
GL_LINEAR
un résultat similaire ou sélectionnera le pixel le plus proche,GL_NEAREST
ce qui entraînera également des bandes entre les blocs. La dernière option mentionnée diminue mais n'élimine pas le défaut de pixel.Réponses:
D'accord, je pense que vous avez deux problèmes qui se passent ici.
Le premier problème concerne le mappage. En général, vous ne voulez pas mélanger naïvement atlasing avec mipmapping, car à moins que toutes vos sous-textures ne soient exactement de la taille de 1x1 pixel, vous obtiendrez des saignements de texture. Ajouter du rembourrage déplacera simplement le problème à un niveau mip inférieur.
En règle générale, pour la 2D, où vous effectuez habituellement un atlas, vous ne mappez pas; alors que pour la 3D, où vous mappez, vous n’atlasez pas (en fait, vous épinglez de manière à ce que les saignements ne soient pas un problème)
Cependant, ce que je pense en ce moment avec votre programme, c'est que vous n'utilisez probablement pas les coordonnées de texture correctes et que, de ce fait, vos textures saignent.
Supposons une texture 8x8. Vous obtenez probablement le quart en haut à gauche en utilisant les coordonnées UV de (0,0) à (0.5, 0.5):
Et le problème est qu’à la coordonnée u 0,5, l’échantillonneur interpole le fragment de destination en utilisant la moitié du texel gauche et la moitié du texel droit. La même chose se produira à la coordonnée u 0, et la même chose pour les coordonnées v. C'est parce que vous abordez les frontières entre les texels et non les centres.
Ce que vous devriez faire à la place est d’adresser le centre de chaque texel. Dans cet exemple, ce sont les coordonnées que vous souhaitez utiliser:
Dans ce cas, vous échantillonnerez toujours le centre de chaque texel et vous ne devriez pas avoir de saignement ... Sauf si vous utilisez le mappage mip, dans ce cas, vous aurez toujours un saignement à partir du niveau mip où la sous-taille mise à l'échelle n'est pas parfaitement nette. s'adapter à l'intérieur de la grille de pixels .
Pour généraliser, si vous souhaitez accéder à un texel spécifique, les coordonnées sont calculées comme suit:
Ceci est appelé "correction de demi-pixel". Il y a une explication plus détaillée ici si vous êtes intéressé.
la source
Une option qui sera beaucoup plus facile que de jouer avec les mipmaps et d'ajouter des facteurs de fuzz de coordonnées de texture consiste à utiliser un tableau de texture. Les tableaux de texture sont similaires aux textures 3D, mais ne comportent pas de mappage dans la 3ème dimension, ils sont donc parfaits pour les atlas de texture où les "sous-textures" ont toutes la même taille.
http://www.opengl.org/wiki/Array_Texture
la source
Après avoir beaucoup lutté avec ce problème, j'ai finalement trouvé une solution.
Pour utiliser à la fois un atlas de texture et un mappage mip, je dois procéder moi-même au sous-échantillonnage, car OpenGL interpolerait sinon les limites des carreaux de l'atlas. De plus, je devais définir les paramètres de texture appropriés, car une interpolation entre mipmaps provoquerait également un fondu de texture.
Avec ces paramètres, aucun saignement ne se produit.
Vous devez noter une chose lorsque vous fournissez des mipmaps personnalisés. Comme il n’est pas logique de réduire l’atlas même si chaque mosaïque existe déjà
1x1
, le niveau maximal du mipmap doit être défini en fonction de ce que vous fournissez.Merci pour toutes les autres réponses et commentaires très utiles! En passant, je ne sais toujours pas comment utiliser la mise à l'échelle linéaire, mais je suppose qu'il n'y a pas moyen.
la source
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
surGL_NEAREST_MIPMAP_LINEAR
provoque le saignement, non pour la raison du mip-mappage, mais pour la raison de l'interpolation. Donc, dans ce cas, cela équivaut àGL_LINEAR
puisque le niveau de mipmap le plus bas est utilisé de toute façon.glTexImage2D()
. Le GPU choisit automatiquement le niveau correct en fonction de la taille des objets à l'écran.On dirait que le problème pourrait être causé par MSAA. Voir cette réponse et l' article lié :
La solution consiste à utiliser un échantillonnage centroïde. Si vous calculez le recouvrement des coordonnées de texture dans un vertex shader, le déplacement de cette logique vers le fragment shader peut également résoudre le problème.
la source
C'est un sujet ancien et j'ai eu un problème similaire au sujet.
J'avais très bien mes coordonnées de texture, mais en lerping la position de la caméra (ce qui changeait la position de mon élément) comme ceci:
Tout le problème était Util.lerp () renvoie un float ou un double. C'était mauvais parce que la caméra traduisait hors de la grille et posait quelques problèmes étranges avec des fragments de texture où> 0 dans X et> 0 dans Y.
TLDR: ne pas interpoler ou utiliser des flotteurs
la source