Textures

Suivez ces bonnes pratiques pour optimiser l'aspect et les performances des textures dans votre jeu Android.

Les textures sont un élément essentiel de tout graphisme en 3D. Les jeux en 3D compatibles avec un grand nombre d'appareils reposent sur des graphismes en 3D qui ont été conçus pour tirer le meilleur parti des processeurs graphiques. Ce guide présente les optimisations et les bonnes pratiques concernant les textures sur mobile que vous pouvez adopter pour améliorer les performances de votre jeu et réduire la consommation d'énergie tout en maintenant une qualité visuelle élevée.

Certaines parties de cet article sont basées sur un document fourni par Arm Limited, qui en détient les droits d'auteur.

Créer des atlas de textures

Un atlas de texture est une texture conçue pour contenir les données d'image de différents objets graphiques tels que des maillages 3D ou des sprites 2D. Au lieu que chaque objet ait sa propre texture, une texture d'atlas est utilisée pour combiner les images de chaque objet.

Maillages partageant un atlas de texture
Figure 1 Le surlignage jaune dans la scène rendue (à gauche) délimite les maillages qui partagent l'atlas de texture (à droite).

Le nombre d'appels de dessin d'une image de jeu doit être limité afin d'optimiser les performances de rendu. L'utilisation de la même texture pour différents objets facilite leur combinaison en un seul appel de dessin. Il est particulièrement important de réduire le nombre d'appels de dessin pour les jeux qui utilisent le processeur de manière intensive, car chaque appel de dessin se traduit par une surcharge du processeur lors de son traitement par le pilote graphique. Les atlas de textures réduisent également le nombre de fichiers de texture dans les données d'exécution de votre jeu. Des centaines, voire des milliers de textures peuvent être regroupées dans un nombre beaucoup plus restreint de fichiers d'atlas de texture.

Lorsque vous créez des maillages 3D, vous devez planifier la disposition de l'atlas de texture. Si l'atlas est créé avant de créer l'élément de maillage, celui-ci doit être désencapsulé en UV après l'atlas de texture. Si l'atlas est créé après le maillage à l'aide d'outils de fusion ou de création d'atlas dans un logiciel de peinture, l'îlot UV doit être réorganisé en fonction de la texture.

Fonctionnalité de traitement par lot des appels de dessin spécifique au moteur

Le moteur de jeu Unity dispose d'une fonctionnalité de traitement par lot des appels de dessin qui peut combiner automatiquement des objets. Pour être éligibles au traitement par lot automatique, les objets doivent partager un matériau commun, comme des textures, et être marqués comme statiques.

Unreal Engine 4 requiert une configuration manuelle pour le traitement par lot. Vous pouvez fusionner des objets dans un logiciel 3D avant de les importer dans Unreal. Il inclut également l'outil UE4 Actor Fusion, qui peut combiner des maillages et créer des fichiers d'atlas de texture.

Générer des mipmaps

Les mipmaps sont des versions de résolutions inférieures d'une texture. Une collection de mipmaps associée à une texture donnée est appelée une chaîne de mipmaps. Chaque niveau de mipmap suivant d'une chaîne présente une résolution inférieure à celle du niveau précédent. Les mipmaps sont utilisés pour implémenter le niveau de détail (LOD) de la texture lors du rendu. Lorsqu'une texture mipmap est liée à une étape de texture, le matériel graphique utilise l'espace de texture occupé par un fragment pour choisir un niveau dans la chaîne de mipmaps. Lors du rendu d'une scène 3D, un objet éloigné de la caméra utilise un mipmap de résolution inférieure à celui d'un même objet proche de la caméra.

Une texture mipmap utilise plus de mémoire qu'une autre texture. Les niveaux supplémentaires de mipmaps augmentent l'espace mémoire utilisé d'une texture de 33 %. Si une texture est dessinée à une distance fixe de la caméra, toute génération de mipmaps constitue une utilisation inutile de la mémoire.

Chaîne de mipmaps. La résolution de base de la texture est de 512x512 pixels.
Figure 2 : chaîne de mipmaps. La résolution de base de la texture est de 512 x 512 pixels.

Une utilisation appropriée des mipmaps améliore les performances du GPU. La disponibilité des niveaux de mipmaps de résolution inférieure réduit l'utilisation de la bande passante mémoire et améliore la résidence du cache de texture.

Le mipmapping permet également d'améliorer la qualité visuelle en réduisant le crénelage des textures. Le crénelage des textures peut se manifester sous la forme d'un effet de scintillement sur des zones éloignées de la caméra.

Exemple de crénelage de texture
Figure 3  : Exemple de crénelage de texture. Image rendue sans mipmaps (à gauche) et avec mipmaps (à droite). Un crénelage de texture peut être observé dans le rectangle rouge de l'image de gauche.

Informations détaillées sur les mipmaps spécifiques au moteur

Pour pouvoir utiliser le mipmapping, Unreal Engine 4 exige que les dimensions des textures soient des puissances de deux (par exemple, 512x1 024, 128x128). Les chaînes de mipmaps ne peuvent pas être générées si au moins une des deux dimensions de texture n'est pas une puissance de deux.

Le moteur Unity redimensionne automatiquement les textures avec des dimensions d'une puissance de deux pour créer des mipmaps. Pour éviter cette mise à l'échelle, assurez-vous que les dimensions de vos fichiers de texture sources sont des puissances de deux.

Sélectionner les modes de filtrage de texture appropriés

Le filtrage de texture est une fonctionnalité de rendu matériel qui modifie l'aspect visuel d'un triangle rendu. Une utilisation appropriée du filtrage de texture peut améliorer la qualité visuelle d'une scène. Différents modes de filtrage de texture sont disponibles, chacun présentant un rapport d'amélioration du rendu/coût différent. Le coût englobe à la fois le temps de calcul et la bande passante mémoire. Les trois modes de filtrage de texture les plus courants sont les suivants : ponctuel, bilinéaire et trilinéaire. Le filtrage anisotrope est une autre méthode qui peut être combinée au filtrage bilinéaire ou trilinéaire.

Ponctuel

Le mode ponctuel est le mode de filtrage de texture le plus simple et le moins coûteux. Il échantillonne un texel individuel à l'aide des coordonnées spécifiées dans la texture source. Les triangles rendus à l'aide de ce mode de filtrage ont un aspect bloc ou pixélisé, en particulier lorsqu'ils sont rendus à proximité de la caméra.

Bilinéaire

Le mode de filtrage bilinéaire échantillonne les quatre texels qui entourent les coordonnées spécifiées dans la texture source. La moyenne de ces quatre texels est calculée pour déterminer la couleur de la texture du fragment. Le filtrage bilinéaire produit un dégradé plus régulier entre les pixels, ce qui évite l'aspect bloc obtenu avec le filtrage ponctuel. Les triangles rendus à proximité de la caméra sont flous au lieu d'être pixélisés. Le filtrage bilinéaire est plus coûteux que le filtrage ponctuel en raison des échantillons de texels supplémentaires et du calcul de la moyenne.

Comparaison entre le filtrage ponctuel et le filtrage bilinéaire
Figure 4 : Comparaison entre les modes de filtrage de texture le plus proche (à gauche) et bilinéaire (à droite).

Trilinéaire

Lors du rendu d'un maillage dans lequel la distance entre les sommets et la caméra varie, vous pouvez sélectionner plusieurs niveaux de mipmaps. Les changements entre deux niveaux de mipmaps peuvent entraîner une coupure nette au point de transition. Le filtrage trilinéaire adoucit ces transitions en effectuant un filtrage bilinéaire sur deux niveaux de mipmaps différents et en interpolant les résultats. Compte tenu de l'utilisation de plusieurs niveaux de mipmaps et de l'interpolation, le filtrage trilinéaire est plus coûteux que le filtrage bilinéaire en termes de calcul.

Comparaison entre le filtrage bilinéaire et le filtrage trilinéaire
Figure 5  : Comparaison entre les modes de filtrage de texture bilinéaire (à gauche) et trilinéaire (à droite). La zone zoomée met en évidence la différence de rendu le long des transitions de mipmaps

Anisotrope

Le filtrage anisotrope améliore la qualité visuelle des maillages texturés rendus sous un angle extrême par rapport à la caméra. Un plan de sol est un bon exemple de ce type de maillage. Le filtrage anisotrope nécessite des textures mipmap pour fonctionner. Vous pouvez configurer le ratio ou le niveau de filtrage anisotrope appliqué lors du rendu. Le coût du filtrage anisotrope augmente à mesure que le niveau augmente.

Comparaison entre les modes de filtrage anisotrope 1x et 2x
Figure 6 : Comparaison entre le filtrage anisotrope bilinéaire/x1 (à gauche) et le filtrage anisotrope bilinéaire/x2 (à droite)

Stratégie de sélection du mode

Le filtrage bilinéaire offre généralement le meilleur compromis entre performances et qualité visuelle. Le filtrage trilinéaire requiert beaucoup plus de bande passante mémoire et doit être utilisé avec circonspection. Souvent, le filtrage bilinéaire associé à un filtrage anisotrope 2x donne de meilleurs résultats qu'un filtrage trilinéaire associé à un filtrage anisotrope 1x en termes d'aspect et de performances. L'augmentation des niveaux anisotropes au-delà de 2x est très coûteuse et doit être réservée aux éléments de jeu critiques.

Le filtrage de texture peut représenter jusqu'à la moitié de la consommation d'énergie totale du GPU. Choisir des filtres de texture plus simples, lorsque cela est possible, est un excellent moyen de réduire les besoins en énergie de votre jeu.

Optimiser les dimensions des textures

Veillez à ce que les dimensions de vos textures soient aussi réduites que possible tout en offrant la qualité d'image souhaitée. Passez vos textures en revue pour repérer celles qui sont trop volumineuses. Ce principe s'applique à la fois aux textures discrètes et aux textures d'atlas. Si votre jeu est compatible avec de nombreux appareils couvrant un large éventail de résolutions et de performances, pensez à créer des versions basse et haute résolution de vos textures pour la classe d'appareils appropriée.

Lors du rendu d'un maillage englobant différentes textures, n'hésitez pas à réduire de manière sélective la résolution de certaines d'entre elles. Par exemple, si vous utilisez une texture de type "Diffuse" de 1 024x1 024, il est possible de réduire la texture de type "Roughness" ou "Metallic Map" à 512x512 avec un impact minime sur la qualité de l'image. Vérifiez l'impact de tous ces redimensionnements pour vous assurer qu'ils ne compromettent pas le niveau de qualité souhaité.

Utiliser l'espace de couleur approprié

De nombreux packages logiciels utilisent l'espace de couleur sRVB pour créer des textures et les exporter. Les textures diffuses, qui sont traitées comme des couleurs, peuvent utiliser un espace de couleur sRVB. Celles qui ne sont pas traitées comme des couleurs, comme les textures de type "Metallic", "Roughness" ou "Normal Map", ne doivent pas être exportées dans l'espace de couleur sRVB.

Les paramètres de texture du moteur de jeu incluent un paramètre indiquant si une texture utilise un espace de couleur sRVB.

Paramètres de texture sRVB dans Unity et Unreal Engine 4
Figure 7 : Paramètres de texture sRVB dans Unity (à gauche) et Unreal Engine 4 (à droite)

Étant donné que les données de pixel de ces textures ne sont pas utilisées comme des couleurs, l'utilisation de l'espace de couleur sRVB produit des images erronées.

Rendu d'une texture de type "Roughness Metallic Map" en mode linéaire par rapport à un espace de couleur sRVB
Figure 8  : Texture de type "Roughness Metallic Map" linéaire (non sRVB) (à gauche) et de type "Roughness Metallic Map" sRVB (à droite). Les reflets de droite semblent erronés

Utiliser la compression de texture

La compression de texture est un algorithme de compression d'image appliqué aux données de pixel non compressées. Il en résulte une texture qui peut être rapidement décompressée par le matériel graphique lors du rendu. Une utilisation efficace de la compression de texture peut réduire l'utilisation de la mémoire et améliorer les performances avec un impact minime sur la qualité visuelle. Les trois algorithmes de compression de texture les plus courants sous Android sont les suivants : ETC1, ETC2 et ASTC. Pour les jeux récents, ASTC est généralement la meilleure option. ETC2 peut également être utilisé si votre jeu cible des appareils non compatibles avec ASTC.

ETC1

ETC1 est compatible avec tous les appareils Android. ETC1 n'est compatible qu'avec un seul mode de quatre bits par pixel pour les données de couleur RVB. ETC1 n'est pas compatible avec les canaux alpha. De nombreux moteurs de jeu compatibles avec ETC1 permettent de désigner une deuxième texture ETC1 pour représenter les données des canaux alpha.

ETC2

ETC2 est compatible avec plus de 90 % des appareils Android actifs. Les appareils très anciens qui ne sont pas compatibles avec l'API OpenGL ES 3.0 ne peuvent pas utiliser ETC2. Par rapport à ETC1, ETC2 offre ce qui suit :

  • Compatibilité avec les canaux alpha, à la fois 8 bits et 1 bit "punchthrough"
  • Versions sRVB des textures RVB et RVBA
  • Textures à un et deux canaux, R11 et RG11

ASTC

ASTC est compatible avec plus de 75 % des appareils Android actifs. ASTC propose des tailles de bloc de compression configurables, ce qui vous confère un contrôle précis pour équilibrer le taux de compression et la qualité de l'image d'une texture donnée. ASTC offre souvent une qualité supérieure avec la même taille de mémoire qu'ETC2, ou une quantité similaire avec une taille de mémoire inférieure à ETC2.

Comparaison visuelle des formats de compression de texture à l'aide de la même image source
Figure 9  : Comparaison entre une image non compressée (à gauche, 17 Mo), une image compressée avec ETC1 (au centre, 3 Mo) et une image compressée avec ASTC (à droite, 2,5 Mo)

Vitesse de compression des textures

La compression des textures peut prendre beaucoup de temps si votre jeu comporte beaucoup de textures. ETC et ASTC proposent des paramètres de qualité de compression sélectionnables. Les paramètres de qualité supérieure rallongent le délai de compression. Lors du développement, vous pouvez diminuer le niveau de qualité afin de réduire le temps de compression et améliorer le niveau de qualité avant de créer des builds importants.

Compression de texture dans les moteurs de jeu

Si vous utilisez un moteur de jeu, vous devrez peut-être choisir votre format de compression de texture (ETC ou ASTC) au niveau du projet. Pour accepter plusieurs formats de compression afin d'optimiser la compatibilité, des tâches supplémentaires peuvent être nécessaires. La fonctionnalité Texture Compression Format Targeting de Google Play Asset Delivery permet d'inclure plusieurs formats dans un jeu et de ne fournir à un appareil individuel que le format optimal au moment de l'installation.

Déplier des UV

L'îlot UV doit être aussi droit que possible. Cela offre différents avantages pour la texture :

  • L'empaquetage des îlots UV est plus facile, et l'espace perdu est réduit.
  • Les UV droits réduisent "l'effet escalier" sur les textures.
  • Un bon empaquetage des UV garantit une résolution optimale de la texture.
  • La texturation est de meilleure qualité, même si les UV sont légèrement déformés par le redressement.
Îlot UV non optimisé et îlot UV optimisé
Figure 10 : îlot UV non optimisé (à gauche) et îlot UV redressé/déplié (à droite).

L'aspect des coutures de texture visibles sur un modèle n'est pas optimal. Essayez de placer les coutures UV à des emplacements où elles seront moins visibles. Pour créer des cartes de normales optimales, fractionnez votre îlot UV à des emplacements où les arêtes sont nettes et laissez un peu d'espace autour de l'îlot.

Éviter les détails imperceptibles

Lorsque vous créez un graphisme, n'ajoutez pas de détails qui ne seront pas visibles, en particulier dans les jeux conçus pour des appareils équipés d'un petit écran. Il est inutile de créer une texture 4 096x4 096 aux détails complexes pour un petit modèle de chaise à peine visible dans le coin d'une pièce. Dans certains cas, vous devrez peut-être exagérer les arêtes (en ajoutant des tons clairs) et les ombres pour améliorer la perception des formes.

Une petite texture est utilisée sur un modèle rendu à distance
Figure 11 Une petite texture 256x256 sans détails excessifs est utilisée sur un modèle de soldat rendu à distance.

Informations détaillées sur le "baking"

Les appareils mobiles sont équipés d'écrans plus petits et de matériel graphique moins puissant que les ordinateurs personnels ou les consoles de jeu. Au lieu de calculer des effets tels que l'occlusion ambiante ou la lumière spéculaire au moment de l'exécution, veillez si possible à les transférer ("baking") dans la texture diffuse. Cela améliore les performances et assure la visibilité de vos détails.

Baking de la lumière et de l'occlusion ambiante dans une texture diffuse
Figure 12 Mises en surbrillance et occlusion ambiante intégrées à la texture diffuse (à gauche) et rendues dans le jeu (à droite).

Utiliser le nuançage de couleur (ou "color tinting")

Si vous avez la possibilité de créer des nuanceurs personnalisés et que vos maillages disposent d'un jeu de couleurs similaire ou uniforme, n'hésitez pas à avoir recours au nuançage de couleur sur les maillages applicables. Le nuançage de couleur utilise une texture en nuances de gris, qui nécessite moins de mémoire qu'une texture RVB. Les données de couleur des sommets sont appliquées par le nuanceur pour colorer le maillage. Une autre méthode de nuançage de couleur consiste à utiliser un masque RVB et à appliquer la texture en fonction de la gamme de couleurs du masque.

Texture en nuances de gris nuancée au moment de l'exécution
Figure 13 : Texture en nuances de gris (à gauche) nuancée au moment de l'exécution pour le modèle de pilier (à droite).

Combiner les canaux de texture

Lors du rendu de matériaux composés de plusieurs textures, recherchez les possibilités de combiner les textures qui n'utilisent qu'un seul canal de couleur en une seule texture utilisant les trois canaux de couleur. Cela réduit l'utilisation de la mémoire et diminue le nombre d'opérations d'échantillonnage de texture effectuées par le nuanceur de fragments.

Trois textures à un seul canal combinées en une seule
Figure 14  : Trois textures à un seul canal (à gauche) sont combinées en une seule texture à plusieurs canaux (à droite). Les données d'occlusion ambiante sont attribuées au rouge, le type "Roughness/Smoothness Map" au vert, et le type "Metallic Map" au bleu

Lors de la combinaison, attribuez les données les plus détaillées au canal vert. Comme l'œil humain est plus sensible au vert, le matériel graphique attribue généralement plus de bits au canal vert. Par exemple, un type "Roughness/Smoothness Map" est généralement plus détaillé qu'un type "Metallic Map". Il est donc préférable de l'attribuer au canal vert.

Pour les matériaux qui utilisent un canal alpha, si vous n'utilisez que deux canaux dans votre texture combinée, vous pouvez intégrer les données du canal alpha dans votre texture combinée plutôt que dans votre texture diffuse. Selon le format de votre texture diffuse, vous pouvez ainsi réduire sa taille ou améliorer sa qualité visuelle en omettant les données du canal alpha.

Canal alpha combiné à une autre texture
Figure 15  : Un type "Opacity Map" (Carte d'opacité) de canal alpha est combiné à une texture avec un type "Roughness/Smoothness Map" (Carte de rugosité/texture douce) et un type "Metallic Map" (Carte métallique).

Assurez-vous que vos textures combinées sont définies sur un espace de couleur RVB linéaire, et non sur sRVB

Créer des cartes de normales

Le "normal mapping" est une technique qui donne l'apparence d'un détail à un modèle 3D sans utiliser de géométrie supplémentaire. Les caractéristiques telles que les rides ou les boulons, dont la modélisation peut nécessiter de nombreux triangles, peuvent être simulées à l'aide d'une carte de normales (ou "normal map"). Le normal mapping peut être approprié ou non selon le style artistique et l'orientation du jeu.

Modèle rendu avec et sans carte de normales
Figure 16  : Modèle rendu sans carte de normales (à gauche), et le même modèle rendu avec une carte de normales (au centre), et la texture de la carte de normales (à droite)

Les cartes de normales, qui ont un coût en termes de performances, doivent être utilisées avec parcimonie sur les appareils bas de gamme. La carte de normales nécessite une texture supplémentaire, ce qui entraîne un autre échantillonnage de texture et des calculs du nuanceur de fragments.

Bonnes pratiques concernant les cartes de normales

Voici quelques bonnes pratiques à suivre pour créer une carte de normales :

Utiliser une cage

Une cage est une version plus grande ou plus étendue de votre modèle à faible polygone. Elle doit englober le modèle doté d'un nombre élevé de polygones pour fonctionner correctement pendant le processus de baking de la carte de normales. La cage est utilisée pour limiter la distance de raycasting lors du processus de baking de la carte de normales, et pour éviter les problèmes liés au fractionnement des coutures de normales sur la carte de normales.

Cage entourant le maillage à faible polygone
Figure 17  : Cage entourant le maillage à faible polygone
Modèle rendu à l'aide d'une carte de normales avec et sans cage
Figure 18  : Rendu d'un modèle à l'aide d'une carte de normales générée avec une cage (à gauche) par rapport à un modèle rendu à l'aide d'une carte de normales générée sans cage (à droite)

"Bake matching" par nom de maillage

Si votre logiciel de baking le permet, vous pouvez effectuer un "bake matching" par nom de maillage. Cette fonctionnalité atténue le problème de projection erronée de la carte de normales. Lorsque des objets sont trop proches les uns des autres, ils peuvent projeter de manière inattendue leur carte de normales sur la mauvaise surface. La mise en correspondance par nom de maillage garantit que le transfert (baking) a été effectué sur la bonne surface. Pour en savoir plus sur cette fonctionnalité dans Substance Painter, consultez cette page. Pour en savoir plus sur cette fonctionnalité dans Marmoset Toolbag, consultez cette page.

Faire éclater le maillage

Si vous ne parvenez pas à faire correspondre le nom du maillage lors du processus de baking, vous pouvez faire éclater votre maillage. Cela permet d'éloigner les différentes parties du maillage les unes des autres afin que la carte de normales ne se projette pas sur la mauvaise surface. Si vous procédez également à un transfert (baking) pour l'occlusion ambiante, vous devrez peut-être l'effectuer séparément avec un maillage non éclaté.

Maillage éclaté pour le processus de baking d'une carte de normales
Figure 19  : Maillage éclaté pour le processus de baking d'une carte de normales

Réduire les coutures

Des UV continus sur des arêtes dures rendent les coutures visibles. Fractionnez les UV sur les arêtes dures pour réduire cet effet. Lorsque vous définissez des groupes de lissage, optez généralement pour un angle inférieur à 90 degrés. Les coutures UV doivent disposer d'un groupe de lissage différent sur les triangles.