J'ai une routine de sprite personnalisée (openGL 2.0) qui utilise une simple feuille de sprite (mes textures sont disposées horizontalement les unes à côté des autres).
Donc, par exemple, voici une feuille de sprite de test avec 2 textures simples:
Maintenant, ce que je fais lors de la création de mon objet sprite openGL est de spécifier le nombre total de cadres dans son atlas et lors du dessin, de spécifier le cadre que je veux dessiner.
Il détermine ensuite où récupérer la texture en:
Division du numéro de trame requis par le nombre total de trames (pour obtenir la coordonnée de gauche)
Et puis plongée 1 par le nombre total d'images et en ajoutant le résultat à la coordonnée de gauche calculée ci-dessus.
Cela semble fonctionner mais j'ai parfois des problèmes. Dites par exemple, je veux dessiner le X ci-dessous et je reçois ...........
J'ai entendu parler de mettre un «rembourrage» de 1 px entre chaque texture, mais quelqu'un pourrait-il expliquer exactement comment cela fonctionne? Je veux dire que si je fais cela, cela détruira sûrement les calculs pour obtenir la texture.
Si j'inclus simplement le rembourrage dans la texture ramassée (de sorte que le sprite est dessiné avec une bordure vierge), alors cela causera sûrement un problème avec la détection de collision? (c'est-à-dire que les sprites peuvent sembler entrer en collision lors de l'utilisation de boîtes englobantes lorsque les parties transparentes entrent en collision).
J'apprécierais si quelqu'un pouvait expliquer.
la source
GL_NEAREST
ouGL_LINEAR
pour rendre la texture?Réponses:
Le problème de l'utilisation des atlas de texture et des fuites de texels adjacentes est lié au fonctionnement du filtrage de texture linéaire.
Pour tout point de la texture qui n'est pas échantillonné exactement au centre d'un texel, l'échantillonnage linéaire échantillonnera 4 texels adjacents et calculera la valeur à l'emplacement que vous avez demandé comme moyenne pondérée (basée sur la distance du point d'échantillonnage) des 4 échantillons.
Voici une belle visualisation du problème:
Comme vous ne pouvez pas utiliser quelque chose comme
GL_CLAMP_TO_EDGE
dans un atlas de texture, vous devez créer des texels de bordure autour du bord de chaque texture. Ces texels de bordure empêcheront les échantillons voisins de textures complètement différentes dans l'atlas de modifier l'image par l'interpolation pondérée expliquée ci-dessus.Notez que lorsque vous utilisez le filtrage anisotrope, vous devrez peut-être augmenter la largeur de la bordure. En effet, le filtrage anisotrope augmentera la taille du voisinage de l'échantillon à des angles extrêmes.
Pour illustrer ce que je veux dire en utilisant une bordure autour du bord de chaque texture, considérez les différents modes d'habillage disponibles dans OpenGL. Portez une attention particulière à
CLAMP TO EDGE
.Bien qu'il existe un mode appelé "Clamp to Border", ce n'est en fait pas ce qui nous intéresse. Ce mode vous permet de définir une seule couleur à utiliser comme bordure autour de votre texture pour toutes les coordonnées de texture qui se situent en dehors de la normalisée [0.0 -1,0] plage.
Ce que nous voulons, c'est reproduire le comportement de
CLAMP_TO_EDGE
, où toute coordonnée de texture en dehors de la plage appropriée pour la (sous-) texture reçoit la valeur du dernier centre de texels dans la direction où elle était hors limites. Puisque vous avez un contrôle presque complet sur les coordonnées de texture dans un système d'atlas, le seul scénario dans lequel les coordonnées de texture (effectives) pourraient se référer à un emplacement en dehors de votre texture sont pendant l'étape moyenne pondérée du filtrage de texture.Nous savons que
GL_LINEAR
nous échantillonnerons les 4 voisins les plus proches comme le montre le diagramme ci-dessus, nous n'avons donc besoin que d'une bordure de 1 texel. Vous pouvez avoir besoin d'une bordure de texel plus large si vous utilisez le filtrage anisotrope, car il augmente la taille du voisinage de l'échantillon dans certaines conditions.Voici un exemple d'une texture qui illustre plus clairement la bordure, bien que pour vos besoins, vous pouvez faire la bordure de 1 texel ou 2 texels de large.
(REMARQUE: la bordure à laquelle je fais référence n'est pas le noir autour des quatre bords de l'image, mais la zone où le motif en damier cesse de se répéter régulièrement)
Au cas où vous vous poseriez la question, voici pourquoi je continue d'évoquer le filtrage anisotrope. Il modifie la forme du voisinage de l'échantillon en fonction de l'angle et peut entraîner l'utilisation de plus de 4 texels pour le filtrage:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Plus le degré d'anisotropie que vous utilisez est élevé, plus vous aurez de chances de traiter des échantillons de voisinage contenant plus de 4 texels. Une bordure de 2 texels devrait être adéquate pour la plupart des situations de filtrage anisotrope.
Enfin, voici comment un atlas de textures compacté serait construit qui reproduirait le
GL_CLAMP_TO_EDGE
comportement en présence d'unGL_LINEAR
filtre de textures:( Soustrayez 1 de X et Y dans les coordonnées noires, je n'ai pas vérifié la lecture de l'image avant de poster. )
En raison du stockage des bordures, le stockage de 4 textures 256x256 dans cet atlas nécessite une texture aux dimensions 516x516. Les bordures sont codées par couleur en fonction de la façon dont vous les remplissez de données texels lors de la création de l'atlas:
En effet, dans cet exemple compact, chaque texture de l'atlas utilise une région 258x258 de l'atlas, mais vous générerez des coordonnées de texture qui correspondent à la région 256x256 visible. Les texels de bordure ne sont utilisés que lorsque le filtrage des textures est effectué sur les bords des textures de l'atlas, et la façon dont ils sont conçus imite le
GL_CLAMP_TO_EDGE
comportement.Au cas où vous vous poseriez la question, vous pouvez implémenter d'autres types de modes d'habillage en utilisant une approche similaire -
GL_REPEAT
peut être implémenté en échangeant les texels de bordure gauche / droite et haut / bas dans l'atlas de texture et un peu de mathématiques de coordonnées de texture intelligentes dans un shader. C'est un peu plus compliqué, alors ne vous en faites pas pour l'instant. Puisque vous ne traitez qu'avec des feuilles de sprite, limitez-vous àGL_CLAMP_TO_EDGE
:)la source