Fonctionnement du rendu de jeu 3D: Texturing

Dans cette troisième partie de notre examen plus approfondi du rendu de jeu en 3D, nous allons nous concentrer sur ce qui peut arriver au monde 3D après le traitement du sommet et la pixellisation de la scène. La texturation est l'une des étapes les plus importantes du rendu, même si tout ce qui se passe est que les couleurs d'une grille bidimensionnelle de blocs colorés soient calculées et modifiées.

La majorité des effets visuels observés dans les jeux d’aujourd’hui sont dus à l’utilisation intelligente des textures – sans elles, les jeux seraient ternes et sans vie. Alors plongeons-nous et voyons comment tout cela fonctionne!

Comme toujours, si vous n'êtes pas prêt pour une plongée en profondeur dans le texturage, ne paniquez pas – vous pouvez commencer avec notre 3D Rendu de jeu 101. Mais une fois que vous avez dépassé les bases, continuez la lecture pour notre prochain look. dans le monde des graphiques 3D.

Commençons simple

Choisissez les jeux 3D les plus vendus des 12 derniers mois et ils auront tous un point en commun: l’utilisation de cartes de texture (ou juste les textures). C’est un terme si courant que la plupart des gens évoquent la même image lorsqu’on pense à des textures: un carré ou un rectangle simple et plat contenant l’image d’une surface (herbe, pierre, métal, vêtements, visage, etc.).

Toutefois, lorsqu'elles sont utilisées dans plusieurs couches et tissées ensemble selon une arithmétique complexe, l'utilisation de ces images de base dans une scène 3D peut produire des images incroyablement réalistes. Pour voir comment cela est possible, commençons par les ignorer complètement et par voir à quoi peuvent ressembler les objets d'un monde 3D sans eux.

Comme nous l'avons vu dans de précédents articles, le monde 3D est constitué de sommets, formes simples qui sont déplacées, puis colorées. Ils sont ensuite utilisés pour créer des primitives, qui sont à leur tour écrasées dans une grille 2D de pixels. Puisque nous n'allons pas utiliser de textures, nous devons colorier ces pixels.

Une méthode utilisable, appelée ombrage platconsiste à prendre la couleur du premier sommet de la primitive, puis à utiliser cette couleur pour tous les pixels recouverts par la forme dans le raster. Cela ressemble à quelque chose comme ça:

Ce n’est évidemment pas une théière réaliste, notamment parce que la couleur de la surface est mauvaise. Les couleurs sautent d'un niveau à l'autre, il n'y a pas de transition en douceur. Une solution à ce problème pourrait être d'utiliser quelque chose appelé Ombrage Gouraud.

Il s’agit d’un processus qui prend les couleurs des sommets, puis calcule l’évolution de la couleur sur la surface du triangle. Le calcul utilisé est connu sous le nom interpolation linéaire, ce qui semble fantaisiste mais signifie en réalité que si un côté de la primitive a la couleur 0,2 rouge, par exemple, et que l’autre côté est 0,8 rouge, le milieu de la forme a une couleur médiane comprise entre 0,2 et 0,8 (c.-à-d. 0,5).

C'est relativement simple à faire et c'est son principal avantage, car simple signifie vitesse. De nombreux premiers jeux 3D utilisaient cette technique, car le matériel utilisé pour effectuer les calculs était limité dans la mesure de ses possibilités.

Mais même cela pose des problèmes, car si une lumière pointe directement au centre d'un triangle, ses coins (les sommets) risquent de ne pas le saisir correctement. Cela signifie que les points forts causés par la lumière pourraient être totalement ignorés.

Bien que les ombrages plat et Gouraud aient leur place dans l'armurerie pour le rendu, les exemples ci-dessus sont des candidats clairs pour l'utilisation de textures destinées à les améliorer. Et pour bien comprendre ce qui se passe lorsqu'une texture est appliquée sur une surface, nous remonterons dans le temps … jusqu'en 1996.

Un peu d'histoire de jeu et de GPU

Quake est sorti il ​​y a environ 23 ans, un jeu phare de id Software. Bien que ce ne soit pas le premier jeu à utiliser des polygones et des textures 3D pour restituer l’environnement, ce fut certainement l’un des premiers à les utiliser aussi efficacement.

Une autre chose qu’elle a faite a été de montrer ce qui pouvait être fait avec OpenGL (l’API graphique en était encore à sa première révision à ce moment-là) et cela a également beaucoup aidé à la vente du premier lot de cartes graphiques comme la Rendition. Verite et le 3Dfx Voodoo.

Comparé aux normes actuelles, le Voodoo était exceptionnellement basique: pas de support graphique 2D, pas de traitement de sommet, et juste les bases du traitement de pixel. C'était quand même une beauté:

Il disposait d'une puce complète (le TMU) pour obtenir un pixel d'une texture et d'un autre fragment (le FBI) ​​pour le fusionner ensuite avec un pixel du raster. Il pourrait faire quelques autres processus, tels que des effets de brouillard ou de transparence, mais c'était à peu près tout.

Si nous jetons un coup d'œil à l'architecture de la conception et du fonctionnement de la carte graphique, nous pouvons voir comment ces processus fonctionnent.

La puce FBI prend deux valeurs de couleur et les mélange; l'un d'eux peut être une valeur d'une texture. Le processus de mélange est mathématiquement assez simple, mais varie légèrement entre ce qui est mélangé et l'API utilisée pour exécuter les instructions.

Si nous regardons ce que Direct3D offre en termes de fonctions de fusion et d'opérations de fusion, nous pouvons voir que chaque pixel est d'abord multiplié par un nombre compris entre 0,0 et 1,0. Ceci détermine la quantité de couleur du pixel qui influencera l'apparence finale. Ensuite, les deux couleurs de pixels ajustées sont soit ajoutées, soit soustraites, soit multipliées. dans certaines fonctions, l'opération est un énoncé logique dans lequel quelque chose comme le pixel le plus lumineux est toujours sélectionné.

L'image ci-dessus est un exemple de la façon dont cela fonctionne dans la pratique. notez que pour le pixel de gauche, le facteur utilisé est celui du pixel alpha valeur. Ce nombre indique comment transparent le pixel est.

Les autres étapes consistent à appliquer une valeur de brouillard (extraite d’une table de nombres créée par le programmeur, puis en effectuant les mêmes opérations de calcul); effectuer des contrôles et des ajustements de visibilité et de transparence; avant d’écrire enfin la couleur du pixel dans la mémoire de la carte graphique.

Pourquoi la leçon d'histoire? Malgré la relative simplicité de la conception (en particulier par rapport aux monstres modernes), le processus décrit les bases de la texturation: obtenir des valeurs de couleur et les mélanger afin que les modèles et les environnements ressemblent à ce qu’ils sont supposés donner dans une situation donnée. .

Les jeux actuels font encore tout cela, la seule différence est la quantité de textures utilisées et la complexité des calculs de fusion. Ensemble, ils simulent les effets visuels observés dans les films ou l'interaction de la lumière avec différents matériaux et surfaces.

Les bases de la texturation

Pour nous, une texture est une image 2D plate qui s'applique aux polygones qui composent les structures 3D du cadre visualisé. Pour un ordinateur, ce n’est rien de plus qu’un petit bloc de mémoire, sous la forme d’un tableau 2D. Chaque entrée du tableau représente une valeur de couleur pour l’un des pixels de l’image de texture (mieux connu sous le nom de texels – pixels de texture).

Chaque sommet d'un polygone a un ensemble de 2 coordonnées (généralement appelées u, v) qui lui est associé et indique à l’ordinateur quel pixel de la texture lui est associé. Le sommet a lui-même un ensemble de 3 coordonnées (x, y, z), et le processus de liaison des texels aux sommets est appelé mappage de texture.

Pour voir cela en action, passons à un outil que nous avons utilisé à quelques reprises dans cette série d'articles: l'outil WebGL de rendu en temps réel. Pour le moment, nous allons aussi laisser tomber le z coordonner à partir des sommets et garder le tout sur un plan plat.

De gauche à droite, nous avons la texture u, v coordonnées mappées directement sur les sommets d'angle ' x, y coordonnées. Ensuite, les sommets supérieurs ont eu leur y les coordonnées ont augmenté, mais comme la texture est toujours directement mappée sur elles, la texture est étirée vers le haut. À l'extrême droite, c'est la texture qui a été modifiée cette fois-ci: le vous des valeurs ont été relevées, mais la texture est écrasée puis répétée.

En effet, bien que la texture soit désormais effectivement plus haute, grâce à la plus grande vous valeur, il doit encore tenir dans la primitive – essentiellement la texture a été partiellement répétée. C’est une façon de faire quelque chose qui se voit dans beaucoup de jeux 3D: texture répétant. Des exemples courants de ceci peuvent être trouvés dans des scènes avec des paysages rocheux ou herbeux, ou des murs de briques.

Maintenant, ajustons la scène pour qu'il y ait plus de primitives, et nous allons aussi redonner de la profondeur à la profondeur. Ce que nous avons ci-dessous est une vue de paysage classique, mais avec la texture de la caisse copiée, ainsi que répétée, à travers les primitives.

Maintenant, cette texture de caisse, dans son format gif original, a une taille de 66 Ko et une résolution de 256 x 256 pixels. La résolution d'origine de la partie du cadre couverte par les textures de caisse est de 1900 x 680; ainsi, en termes de pixels, cette région ne devrait afficher que 20 textures de caisse.

Nous cherchons évidemment beaucoup plus que 20, cela veut donc dire que beaucoup de textures de caisse dans le fond doivent être beaucoup inférieure à 256 x 256 pixels. En effet ils sont, et ils ont subi un processus appelé minification de la texture (oui, c'est un mot!). Maintenant, essayons encore, mais cette fois zooma dans l'une des caisses.

N'oubliez pas que la texture n'a qu'une taille de 256 x 256 pixels, mais nous pouvons voir ici qu'une texture fait plus de la moitié de la largeur de l'image large de 1900 pixels. Cette texture a traversé quelque chose appelé grossissement de la texture.

Ces deux processus de texture se produisent constamment dans les jeux 3D, car à mesure que la caméra se déplace autour de la scène ou que les modèles se rapprochent, toutes les textures appliquées aux primitives doivent être mises à l'échelle avec les polygones. Mathématiquement, ce n’est pas un gros problème. En fait, c’est tellement simple que même les puces graphiques les plus élémentaires font l’objet d’un blitz. Cependant, la minification et l’agrandissement de la texture posent de nouveaux problèmes qui doivent être résolus d’une manière ou d’une autre.

Entrez le mini-moi de textures

Le premier problème à résoudre concerne les textures au loin. Si nous regardons cette image de paysage de première caisse, celle qui se trouve juste à l’horizon n’a en réalité que quelques pixels. Il est donc inutile d'essayer de réduire une image de 256 x 256 pixels dans un espace aussi réduit.

Premièrement, une texture plus petite occupera moins d’espace mémoire dans une carte graphique, ce qui est pratique pour essayer de s’intégrer dans une petite quantité de cache. Cela signifie qu'il est moins probable que le contenu soit supprimé du cache et qu'une utilisation répétée de cette texture permettra de tirer pleinement parti des performances des données stockées dans la mémoire proche. La deuxième raison pour laquelle nous en viendrons dans un instant est liée au même problème pour les textures agrandies.

Une solution commune à l’utilisation de grandes textures écrasées en petites primitives implique l’utilisation de mipmaps. Ce sont des versions réduites de la texture d'origine; ils peuvent être générés par le moteur de jeu lui-même (à l'aide de la commande d'API appropriée) ou prédéfinis par les concepteurs de jeux. Chaque niveau de texture mipmap a la moitié des dimensions linéaires du précédent.

Donc, pour la texture de caisse, cela ressemble à ceci: 256 x 256 → 128 x 128 → 64 x 64 → 32 x 32 → 16 x 16 → 8 x 8 → 4 x 4 → 2 x 2 → 1 x 1.

Les mipmaps sont tous regroupés, de sorte que la texture est toujours le même nom de fichier mais est maintenant plus grande. La texture est emballée de telle sorte que le u, v Les coordonnées déterminent non seulement quel texel est appliqué à un pixel du cadre, mais également à partir de quel mipmap. Les programmeurs codent ensuite le moteur de rendu pour déterminer le mipmap à utiliser en fonction de la valeur de profondeur du pixel de l’image, c’est-à-dire que si elle est très haute, le pixel se trouve à très grande distance, de sorte qu’un minuscule mipmap peut être utilisé.

Les lecteurs aux yeux pointus auraient peut-être constaté un inconvénient pour les mipmaps, mais cela a un coût par rapport aux textures plus volumineuses. La texture originale de la caisse est de 256 x 256 pixels, mais comme vous pouvez le voir dans l'image ci-dessus, la texture avec les mipmaps est maintenant de 384 x 256. Oui, il y a beaucoup d'espace vide, mais peu importe la façon dont vous emballez les textures plus petites , l’augmentation globale d’au moins une des dimensions de la texture est de 50%.

Mais cela n’est vrai que pour les mipmaps préfabriquées; si le moteur de jeu est programmé pour les générer en fonction des besoins, l'augmentation ne dépasse jamais 33% de la taille de la texture d'origine. Ainsi, pour une augmentation relativement faible de la mémoire des mipmaps de texture, vous bénéficiez d'avantages en termes de performances et d'améliorations visuelles.

Ci-dessous, une comparaison des mipmaps de texture:

Sur la gauche de l'image, les textures de caisse sont utilisées "telles quelles", ce qui donne un aspect granuleux et des motifs de moiré au loin. Sur le côté droit, l'utilisation de mipmaps permet une transition beaucoup plus douce dans le paysage, où la texture de la caisse se transforme en une couleur uniforme à l'horizon.

Le problème, cependant, est de savoir qui veut des textures floues gâchant l’arrière-plan de son jeu préféré?

Bilinéaire, trilinéaire, anisotrope – tout est grec pour moi

Le processus de sélection d’un pixel d’une texture à appliquer à un pixel d’une image est appelé échantillonnage de textureet, dans un monde parfait, il y aurait une texture qui correspond exactement à la primitive pour laquelle elle est conçue – peu importe sa taille, sa position, sa direction, etc. En d'autres termes, l'échantillonnage de texture ne serait rien de plus qu'un processus de mappage rectiligne de texel-à-pixel.

Comme ce n'est pas le cas, l'échantillonnage de texture doit prendre en compte un certain nombre de facteurs:

  • La texture a-t-elle été grossie ou réduite?
  • La texture est-elle originale ou un mipmap?
  • À quel angle la texture est-elle affichée?

Analysons-les un à la fois. Le premier est assez évident: si la texture a été agrandie, le nombre de texels couvrant le pixel dans la primitive sera alors supérieur au nombre requis. avec la minification, ce sera l'inverse: chaque texel doit maintenant couvrir plus d'un pixel. C'est un peu un problème.

La seconde ne l’est pas, car les mipmaps sont utilisées pour contourner le problème d’échantillonnage de texture avec des primitives distantes, de sorte qu’il ne reste que les textures sous un angle. Et oui, c'est un problème aussi. Pourquoi? Parce que toutes les textures sont des images générées pour une vue "face dessus", ou pour être toutes de type mathématique: la normale d'une surface de texture est identique à la normale de la surface sur laquelle la texture est actuellement affichée.

Donc, avoir trop peu ou trop de texels, et avoir des texels en angle, nécessite un processus supplémentaire appelé filtrage de texture. Si vous n'utilisez pas ce processus, voici ce que vous obtenez:

Ici, nous avons remplacé la texture de caisse par une texture de lettre R, pour montrer plus clairement à quel point cela peut être gâché sans filtrage de texture!

Les API graphiques telles que Direct3D, OpenGL et Vulkan offrent toutes les mêmes types de filtrage de plage, mais leur attribuent des noms différents. Essentiellement, ils vont tous comme ceci:

  • Échantillonnage du point le plus proche
  • Filtrage de texture linéaire
  • Filtrage de texture anisotrope

À toutes fins utiles, point d'échantillonnage le plus proche n'est pas un filtrage – c'est parce que tout ce qui se passe est le texel le plus proche du pixel nécessitant que la texture soit échantillonnée (c'est-à-dire copiée à partir de la mémoire), puis fusionnée avec la couleur d'origine du pixel.

Voici le filtrage linéaire à la rescousse. Le nécessaire u, v les coordonnées du texel sont envoyées au matériel pour échantillonnage, mais au lieu de prendre le texel le plus proche de ces coordonnées, l'échantillonneur prend quatre texels. Celles-ci sont directement au-dessus, au-dessous, à gauche et à droite de celle sélectionnée en utilisant l'échantillonnage ponctuel le plus proche.

Ces 4 texels sont ensuite mélangés en utilisant une formule pondérée. À Vulkan, par exemple, la formule est la suivante:

le T fait référence à la couleur texel, où F est pour le 1 filtré et 1 à 4 sont les quatre texels échantillonnés. Les valeurs pour alpha et bêta proviennent de la distance entre le point défini par le u, v les coordonnées sont à partir du milieu de la texture.

Heureusement pour toutes les personnes impliquées dans les jeux 3D, que ce soit en les jouant ou en les fabriquant, cela se produit automatiquement dans la puce de traitement graphique. En fait, c’est ce que la puce TMU du 3dfx Voodoo a fait: échantillonner 4 texels puis les combiner. Direct3D appelle curieusement cela filtrage bilinéaire, mais depuis l'époque de Quake et de la puce TMU de Voodoo, les cartes graphiques ont été capables de faire du filtrage bilinéaire en un seul cycle d'horloge (à condition que la texture se trouve facilement dans la mémoire proche, bien sûr).

Le filtrage linéaire peut être utilisé à côté des mipmaps, et si vous voulez avoir du style avec ce filtrage, vous pouvez extraire 4 texels d'une texture, puis 4 autres du niveau suivant de mipmap, puis mélanger le tout. Et le nom de Direct3D pour cela? Trilinéaire filtration. C'est quoi tri à propos de ce processus? Votre supposition est aussi bonne que la nôtre…

La dernière méthode de filtrage à mentionner est appelée anisotrope. Il s’agit en réalité d’un ajustement du processus de filtrage bilinéaire ou trilinéaire. Il s’agit d’abord d’un calcul de la degré d'anisotropie de la surface de la primitive (et elle est étonnamment complexe aussi) – cette valeur augmente les rapports d'aspect de la primitive en raison de son orientation:

L'image ci-dessus montre la même primitive carrée, avec des côtés de même longueur; mais à mesure qu’il s’éloigne de notre perspective, le carré semble devenir un rectangle et sa largeur augmente avec sa hauteur. Ainsi, le primitif de droite a un degré d'anisotropie plus grand que ceux qui le restent (et dans le cas du carré, le degré est exactement égal à zéro).

De nombreux jeux 3D actuels vous permettent d'activer le filtrage anisotrope, puis d'ajuster son niveau (1x à 16x), mais qu'est-ce que cela change réellement? Le paramètre contrôle le nombre maximal d'échantillons de texels supplémentaires prélevés par échantillonnage linéaire d'origine. Par exemple, supposons que le jeu soit configuré pour utiliser un filtrage bilinéaire anisotrope 8x. Cela signifie qu'au lieu d'extraire 4 valeurs de texels, il en extraira 32.

La différence que l'utilisation du filtrage anisotrope peut faire est évidente:

Faites simplement défiler un peu en arrière et comparez l’échantillonnage ponctuel le plus proche au filtrage trilinéaire 16x maximum. Si lisse, c'est presque délicieux!

Mais il doit y avoir un prix à payer pour toute cette délicieuse texture au beurre et à la performance: le filtrage trilinéaire anisotrope maximise l'extraction et récupère 128 échantillons d'une texture, pour chaque pixel restitué. Même pour le meilleur des derniers GPU, cela ne peut pas être fait en un seul cycle d'horloge.

Si nous prenons quelque chose comme Radeon RX 5700 XT d’AMD, chacune des unités de texturation à l’intérieur du processeur peut déclencher 32 adresses de texel en un cycle d’horloge, puis charger 32 valeurs de texel de la mémoire (d’une taille de 32 bits chacun) au cours d’un autre cycle, puis mélangez 4 d'entre eux dans une coche supplémentaire. Ainsi, pour 128 échantillons de texels mélangés en un seul, il faut au moins 16 cycles d'horloge.

Maintenant, la fréquence de base d’un 5700 XT est de 1605 MHz, donc seize cycles ne prennent que 10 secondes. nanosecondes. Faire cela pour chaque pixel dans une image 4K, en utilisant seulement une unité de texture, ne prendrait que 70 millisecondes. Ok, alors peut-être que la performance n'est pas un problème!

Même en 1996, les utilisateurs de 3Dfx Voodoo étaient assez chics pour gérer les textures. Il pouvait atteindre un texel filtré bilinéaire par cycle d'horloge, et avec le basculement de la puce TMU à 50 MHz, il était ainsi possible d'extraire 50 millions de texels par seconde. Un jeu fonctionnant à 800 x 600 et 30 images par seconde ne nécessiterait que 14 millions de texels filtrés bilinéaires par seconde.

Cependant, tout cela suppose que les textures sont dans la mémoire proche et qu'un seul texel est mappé sur chaque pixel. Il y a vingt ans, l'idée de devoir appliquer plusieurs textures à un primitif était presque complètement étrangère, mais c'est devenu monnaie courante maintenant. Voyons pourquoi ce changement est survenu.

Éclairer le chemin des images spectaculaires

Pour aider à comprendre à quel point la texturation est devenue si importante, jetez un coup d'œil à cette scène de Quake:

C'est une image sombre, c'était la nature du jeu, mais vous pouvez voir que l'obscurité n'est pas la même partout – les taches sur les murs et le sol sont plus lumineuses que les autres, pour donner une idée de l'éclairage général dans cette zone.

Les primitives qui composent les côtés et le sol ont toutes la même texture, mais il en existe une seconde, appelée carte lumineuse, qui est mélangé avec les valeurs de texel avant qu’elles ne soient mappées sur les pixels de l’image. À l'époque de Quake, les cartes de luminosité étaient pré-calculées et créées par le moteur de jeu, et utilisées pour générer des niveaux de lumière statiques et dynamiques.

L'avantage de les utiliser réside dans le fait que des calculs d'éclairage complexes sont effectués sur les textures plutôt que sur les sommets, améliorant ainsi considérablement l'aspect d'une scène et pour un coût de performances très faible. Ce n’est évidemment pas parfait: comme vous pouvez le constater à l’étage, la frontière entre les zones éclairées et celles dans l’ombre est très nette.

À bien des égards, une carte claire n’est qu’une autre texture (rappelez-vous qu’il ne s’agit que de tableaux de données 2D), nous nous intéressons donc ici à une utilisation précoce de ce qui est devenu connu sous le nom de multitexturation. Comme son nom l'indique clairement, il s'agit d'un processus dans lequel deux textures ou plus sont appliquées à une primitive. L’utilisation de light maps dans Quake était une solution permettant de surmonter les limites de l’ombrage Gouraud, mais au fur et à mesure que les capacités des cartes graphiques augmentaient, les applications du multitexturing se développaient.

Le 3Dfx Voodoo, comme les autres cartes de son époque, était limité par tout ce qu'il pouvait faire avec un rendu passer. Il s’agit essentiellement d’une séquence de rendu complète: du traitement des sommets à la pixellisation de la trame, puis à la modification des pixels dans un tampon de trame final. Il y a vingt ans, les jeux affichaient un rendu passe-tout à peu près tout le temps.

Cela s'explique par le fait que le traitement des sommets deux fois, simplement parce que vous vouliez appliquer davantage de textures, était trop coûteux en termes de performances. Nous avons dû attendre quelques années après le Voodoo, le temps que les cartes graphiques ATI Radeon et Nvidia GeForce 2 soient disponibles avant de pouvoir effectuer la multitexturation en une passe de rendu.

Ces GPU avaient plus d’une unité de texture par section de traitement de pixels ( pipeline), ainsi chercher un texel filtré bilinéaire à partir de deux textures séparées était un jeu d'enfant. Cela a rendu la cartographie de la lumière encore plus populaire, permettant aux jeux de les rendre totalement dynamiques, modifiant les valeurs de lumière en fonction des modifications apportées à l'environnement du jeu.

Mais il y a tellement de choses qui peuvent être faites avec plusieurs textures, alors jetons un coup d'œil.

Il est normal d'augmenter la hauteur

Dans cette série d’articles sur le rendu 3D, nous n’avons pas expliqué en quoi le rôle du GPU s’intègre réellement dans l’ensemble du shebang (nous le ferons, mais pas encore!). Mais si vous revenez à la partie 1 et examinez tout le travail complexe impliqué dans le traitement des sommets, vous pouvez penser que c'est la partie la plus difficile de la séquence à traiter par le processeur graphique.

Pendant longtemps, les programmeurs de jeux ont tout mis en œuvre pour réduire cette charge de travail. Cela signifiait aller dans le sac de tours visuels et tirer le plus grand nombre possible de raccourcis et astuces, pour donner la même apparence visuelle en utilisant beaucoup de sommets, mais pas en utiliser autant pour commencer.

Et la plupart de ces astuces impliquaient l’utilisation de textures appelées cartes de hauteur et cartes normales. Les deux sont liés en ce que le dernier peut être créé à partir du premier, mais pour l'instant, jetons un coup d'œil à une technique appelée cartographie des bosses.

Le mappage en relief implique l'utilisation d'un tableau 2D appelé carte de hauteur, qui ressemble à une version étrange de la texture d'origine. Par exemple, dans l'image ci-dessus, une texture de brique réaliste est appliquée sur 2 surfaces planes. La texture et sa carte de hauteur ressemblent à ceci:

Les couleurs de la carte des hauteurs représentent les normales de la surface de la brique (nous avons expliqué ce qu'est une normale dans la première partie de cette série d'articles). Lorsque la séquence de rendu atteint le point d'application de la texture de brique sur la surface, une séquence de calculs a lieu pour ajuster la couleur de la texture de brique en fonction de la normale.

Le résultat est que les briques elles-mêmes ont un aspect plus 3D, même si elles sont encore totalement plates. Si vous regardez attentivement, en particulier sur les bords des briques, vous pouvez voir les limites de la technique: la texture semble légèrement déformée. Mais pour une astuce permettant d’ajouter plus de détails à une surface, le mappage de relief est très populaire.

Une carte normale est comme une carte de hauteur, sauf que les couleurs de cette texture sont les normales elles-mêmes. En d'autres termes, un calcul pour convertir la carte de hauteur en normales n'est pas nécessaire. Vous vous demandez peut-être comment les couleurs peuvent être utilisées pour représenter une flèche pointant dans l'espace? La réponse est simple: chaque texel a un ensemble donné de r, g, b valeurs (rouge, vert, bleu) et ces chiffres représentent directement le x, y, z valeurs pour le vecteur normal.

Dans l'exemple ci-dessus, le diagramme de gauche montre comment la direction des normales change sur une surface bosselée. Pour représenter ces mêmes normales dans une texture plate (diagramme du milieu), nous leur attribuons une couleur. Dans notre cas, nous avons utilisé r, g, b les valeurs de (0,255,0) pour directement vers le haut, puis des quantités croissantes de rouge pour gauche et de bleu pour droite.

Notez que cette couleur n'est pas mélangée avec le pixel d'origine. Elle indique simplement au processeur la direction dans laquelle la normale est dirigée afin qu'il puisse calculer correctement les angles entre la caméra, les lumières et la surface à texturer.

Les avantages du mappage normal et normal apparaissent lorsque l'éclairage dynamique est utilisé dans la scène et le processus de rendu calcule les effets des changements de lumière par pixel, plutôt que pour chaque sommet. Les jeux modernes utilisent maintenant une pile de textures pour améliorer la qualité du tour de magie exécuté.

Ce mur d'aspect réaliste est étonnamment toujours juste une surface plane – les détails sur les briques et le mortier ne sont pas finis en utilisant des millions de polygones. Au lieu de cela, seulement 5 textures et beaucoup de maths intelligents font le travail.

La carte des hauteurs a été utilisée pour générer la manière dont les briques jettent des ombres sur elles-mêmes et la carte normale pour simuler tous les petits changements de la surface. La texture de rugosité a été utilisée pour modifier la manière dont la lumière réfléchie par les différents éléments du mur (par exemple, une brique lissée reflète plus systématiquement que le mortier rugueux).

La carte finale, nommée AO dans l'image ci-dessus, fait partie d'un processus appelé occlusion ambiante: il s'agit d'une technique que nous verrons plus en détail dans un article ultérieur, mais pour l'instant, cela contribue simplement à améliorer le réalisme de les ombres.

Le mappage de texture est crucial

La texturation est absolument cruciale pour la conception de jeux. Prenez Kingdom Come: Deliverance, la version 2019 de Warhorse Studio, un RPG à la première personne se déroulant dans la Bohême du XVe siècle, un ancien pays du centre-est de l'Europe. Les concepteurs étaient désireux de créer un monde aussi réaliste que possible pour la période donnée. Et la meilleure façon d’attirer le joueur dans une vie, il ya des centaines d’années, était d’avoir la bonne apparence pour chaque vue de paysage, bâtiment, vêtements, cheveux, objets du quotidien, etc.

Chaque texture unique de cette image unique du jeu a été conçue à la main par des artistes et leur utilisation par le moteur de rendu contrôlé par les programmeurs. Certains sont petits, avec des détails de base, et reçoivent peu de filtrage ou d’être traités avec d’autres textures (par exemple les ailes de poulet).

D'autres sont en haute résolution, montrant beaucoup de détails fins; ils ont été filtrés de manière anisotrope et fusionnés avec des cartes normales et d'autres textures – il suffit de regarder le visage de l'homme au premier plan. Les programmeurs ont tenu compte des différentes exigences en matière de texturation de chaque élément de la scène.

Tout cela se produit maintenant dans de nombreux jeux, car les joueurs attendent de plus en plus de détails et de réalisme. Les textures deviendront plus grandes et plus nombreuses seront utilisées sur une surface, mais le processus consistant à échantillonner les texels et à les appliquer aux pixels restera essentiellement le même qu’il était à l’époque de Quake. La meilleure technologie ne meurt jamais, peu importe son âge!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.