Fonctionnement du rendu de jeu 3D: texturation et filtrage de texture

image

Dans le troisième article sur le rendu dans les jeux 3D, nous découvrirons ce qui arrive au monde 3D après avoir traité le traitement des vertex et pixellisé la scène. La texturation est l'une des étapes les plus importantes du rendu, malgré le fait qu'elle calcule et modifie uniquement les couleurs d'une grille bidimensionnelle de blocs multicolores.

La plupart des effets visuels des jeux modernes se résument à une utilisation délibérée des textures - sans eux, les jeux sembleraient ennuyeux et sans vie. Voyons donc comment tout cela fonctionne!

Partie 1: traitement des sommets

Partie 2: tramage et lancer de rayons

Commençons par un simple


Vous pouvez prendre tous les jeux à trois dimensions les plus vendus au cours de la dernière année et dire avec confiance qu'ils ont tous quelque chose en commun: ils utilisent des cartes de texture (ou simplement des textures ). C'est un terme si courant que lorsque l'on pense aux textures, la plupart des gens présentent la même image: un simple carré plat ou rectangle contenant une image d'une surface (herbe, pierre, métal, tissu, visage, etc.).

Mais lorsqu'elles sont utilisées et combinées à l'aide de calculs complexes, de telles images simples dans une scène 3D peuvent créer des images incroyablement réalistes. Pour comprendre comment cela est possible, désactivons-les complètement et voyons à quoi ressembleront les objets du monde 3D sans textures.

Comme nous l'avons vu dans les articles précédents, le monde 3D est composé de sommets - des formes simples qui se déplacent puis se colorisent. Ils sont ensuite utilisés pour créer des primitives, qui à leur tour sont compressées en une grille bidimensionnelle de pixels. Comme nous n'utiliserons pas de textures, nous devons coloriser ces pixels.

L'une des méthodes pouvant être appliquées est appelée ombrage plat : la couleur du premier sommet de la primitive est prise, puis cette couleur est appliquée à tous les pixels couverts par la figure dans le raster. Cela ressemble à ceci:


De toute évidence, la bouilloire semble irréaliste, notamment en raison des couleurs de surface irrégulières. Les couleurs sautent d'un niveau à l'autre, il n'y a pas de transitions fluides. Une solution au problème pourrait être d'utiliser l' ombrage Gouraud .

Dans ce processus, les couleurs des sommets sont prises, après quoi le changement de couleur le long de la surface du triangle est calculé. Pour cela, une interpolation linéaire est utilisée . Cela semble compliqué, mais en réalité, cela signifie que si, par exemple, un côté de la primitive a une couleur de 0,2 rouge et l'autre 0,8 rouge, le milieu de la figure aura une couleur au milieu entre 0,2 et 0,8 (soit 0,5).

Ce processus est assez simple, et c'est son principal avantage, car la simplicité signifie la vitesse. De nombreux jeux 3D plus anciens utilisaient cette technique car l'équipement informatique était limité dans ses capacités.


Barrett et Cloud dans toute la grandeur de l'ombrage Gouraud (Final Fantasy VII, 1997)

Mais même une telle solution a des problèmes - si la lumière tombe en plein milieu du triangle, alors ses coins (et sommets) peuvent ne pas transmettre cette propriété. Cela signifie que l'éblouissement créé par la lumière peut être complètement perdu.

Bien que l'ombrage plat et l'ombrage de Gouraud aient pris la place qui leur revient dans les outils de rendu, les exemples ci-dessus sont des candidats clairs pour l'amélioration de la texture. Et pour bien comprendre ce qui se passe lorsque la texture se superpose à la surface, on va remonter dans le temps ... déjà en 1996.

Histoire du jeu et du GPU en bref


Il y a environ 23 ans, id Software a sorti Quake, et c'est devenu une étape importante. Bien que ce ne soit pas le premier jeu à utiliser des polygones et des textures 3D pour rendre des environnements, il a certainement été l'un des premiers à les utiliser efficacement.

Mais elle a fait autre chose aussi - elle a montré ce qui peut être fait en utilisant OpenGL (cette API graphique était alors dans la première version), et a également beaucoup aidé la première génération de cartes graphiques comme Rendition Verite et 3Dfx Voodoo .


Pics d'éclairage et textures simples. Nettoyez 1996, nettoyez Quake.

Selon les normes modernes, Voodoo était extrêmement simple: pas de support graphique 2D, pas de traitement de vertex, seulement le traitement de pixels le plus simple. Cependant, elle était belle:


Image: Musée VGA

Elle avait une puce entière (TMU) pour obtenir un pixel d'une texture et une autre puce (FBI) pour le mélanger plus tard avec un pixel raster. La carte pourrait effectuer quelques processus supplémentaires, par exemple, la mise en œuvre d'effets de brouillard ou de transparence, mais cela a essentiellement mis fin à ses capacités.

Si nous regardons l'architecture sous-jacente à la structure et au fonctionnement de la carte graphique, nous verrons comment ces processus fonctionnent.


Spécification 3Dfx. Source: Falconfly Central

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

Si vous regardez ce que Direct3D nous offre en ce qui concerne les fonctions et les opérations de mixage, nous verrons que chaque pixel est d'abord multiplié par un nombre de 0,0 à 1,0. Cela détermine dans quelle mesure la couleur du pixel affectera le résultat final. Ensuite, deux couleurs de pixels modifiées sont ajoutées, soustraites ou multipliées; dans certaines fonctions, une opération logique est effectuée dans laquelle, par exemple, le pixel le plus lumineux est toujours sélectionné.


Image: Blog technologique Taking Initiative

L'image ci-dessus montre comment cela fonctionne dans la pratique; notez que la valeur alpha du pixel est utilisée comme coefficient pour le pixel gauche . Ce nombre indique le degré de transparence du pixel.

À d'autres étapes, la valeur de brouillard est appliquée (elle est tirée de la table créée par le programmeur, puis les mêmes calculs de mélange sont effectués); effectuer des contrôles et des changements de visibilité et de transparence; à la fin, la couleur du pixel est écrite dans la mémoire de la carte graphique.

Pourquoi avez-vous besoin de cette excursion dans l'histoire? Eh bien, malgré la relative simplicité de la conception (en particulier par rapport aux monstres modernes), ce processus décrit les principes fondamentaux de la texturation: nous prenons les valeurs des couleurs et les mélangeons afin que les modèles et les environnements se présentent comme ils le devraient dans une situation particulière.

Les jeux modernes font la même chose, la seule différence est le nombre de textures utilisées et la complexité des calculs de mixage. Ensemble, ils simulent les effets visuels trouvés dans les films ou l'interaction de l'éclairage avec différents matériaux et surfaces.

Notions de base sur la texturation


Pour nous, une texture est une image 2D plate superposée aux polygones qui composent la structure 3D du cadre. Cependant, pour un ordinateur, ce n'est qu'un petit bloc de mémoire sous la forme d'un tableau 2D. Chaque élément du tableau indique la valeur de couleur de l'un des pixels de l'image de texture (communément appelés texels - pixels de texture).

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

Pour voir comment cela se produit, tournons-nous vers l'outil que nous avons déjà utilisé plusieurs fois dans cette série d'articles - Rendu en temps réel WebGL . Pour l'instant, nous supprimons également la coordonnée z des sommets et considérons tout sur un plan plat.


De gauche à droite: les coordonnées u, v de la texture, directement liées aux coordonnées x, y des sommets des coins. Dans la deuxième image, les coordonnées y sont augmentées aux sommets supérieurs , mais comme la texture y est toujours attachée, elle s'étire verticalement. La texture a déjà été modifiée dans l'image de droite: les valeurs u ont augmenté, mais en conséquence, la texture a été compressée puis répétée.

Cela s'est produit parce que, malgré le fait qu'en fait, la texture est devenue plus élevée en raison de la valeur accrue de u , elle devrait toujours tenir dans la primitive - en fait, la texture partiellement répétée. C'est une façon d'implémenter l'effet que l'on retrouve souvent dans les jeux 3D: répéter les textures. Des exemples de cet effet peuvent être vus dans des scènes avec des paysages pierreux ou herbeux, ainsi qu'avec des murs de briques.

Modifions maintenant la scène pour qu'il y ait plus de primitives, et retournons à nouveau la profondeur de la scène. La vue paysage classique est illustrée ci-dessous, mais maintenant la texture de la boîte est copiée et répétée pour toutes les primitives.


La texture de la boîte dans son format gif d'origine a une taille de 66 Ko et une résolution de 256 x 256 pixels. La résolution initiale de la partie du cadre couverte par les textures de boîte est de 1900 x 680, c'est-à-dire du point de vue de la «zone» de pixels, une telle zone ne devrait afficher que 20 textures de boîte.

Mais il est évident que nous voyons beaucoup plus de vingt boîtes, ce qui signifie que la texture de la boîte au loin doit être beaucoup plus petite que 256 x 256 pixels. En effet , ils ont subi un processus appelé «minification de texture» (oui, un tel mot existe en anglais!). Maintenant, répétons, mais cette fois rapprochez l'appareil photo de l'un des tiroirs.


N'oubliez pas que la texture a une taille de seulement 256 x 256 pixels, mais ici nous voyons une texture qui est plus grande que la moitié de l'image avec une largeur de 1900 pixels. Cette texture a été soumise à une opération de "grossissement de texture" .

Ces deux processus de texture se produisent constamment dans les jeux 3D, car lorsque la caméra se déplace autour de la scène, les modèles s'approchent ou s'éloignent, et toutes les textures appliquées aux primitives doivent évoluer avec les polygones. Du point de vue des mathématiques, c'est un petit problème, en fait, même les puces graphiques intégrées les plus simples peuvent facilement faire un tel travail. Cependant, la réduction et l'agrandissement des textures sont de nouveaux défis qui doivent être résolus d'une manière ou d'une autre.

Des mini-copies de textures apparaissent sur la scène


Le premier problème à résoudre pour les textures est la distance. Si nous revenons à la première image avec un paysage de boîtes, alors les boîtes situées près de l'horizon n'ont en fait qu'une taille de quelques pixels. Par conséquent, essayer de compresser une image de 256 x 256 pixels dans un si petit espace est inutile pour deux raisons.

Tout d'abord, la texture plus petite occupe moins de mémoire de la carte graphique, ce qui est pratique, car vous pouvez essayer de l'intégrer dans un cache plus petit. Cela signifie qu'il est moins susceptible d'être supprimé du cache, c'est-à-dire qu'une utilisation répétée de cette texture fournira des performances accrues, car les données seront en mémoire fermée. Pour la deuxième raison, nous reviendrons bientôt, car il est associé au même problème qui se pose dans les textures proches de la caméra.

La solution standard au problème de la nécessité de compresser de grandes textures en petites primitives est d'utiliser des textures mip (mipmaps) . Ce sont des versions réduites de la texture d'origine; ils peuvent être générés par le moteur lui-même (à l'aide des commandes API appropriées) ou pré-créés par les concepteurs de jeux. Chaque niveau de texture de mip suivant a une demi-taille par rapport au précédent.

Autrement dit, pour la texture de la boîte, les dimensions seront: 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.


Toutes les textures de mip sont emballées ensemble, donc la texture a le même nom de fichier, mais devient plus grande. La texture est compressée de telle manière que les coordonnées u, v déterminent non seulement quel texel est superposé au pixel dans le cadre, mais aussi avec quelle texture de mip. Ensuite, les programmeurs écrivent un rendu, basé sur la valeur de la profondeur de pixel de l'image, qui détermine la texture de mip à utiliser. Par exemple, si la valeur est très élevée, le pixel est loin, ce qui signifie que vous pouvez utiliser une petite texture de mip.

Les lecteurs attentifs pourraient remarquer le manque de textures MIP - ils doivent les payer en augmentant la taille des textures. La texture d'origine de la boîte était de 256 x 256 pixels, mais comme vous pouvez le voir dans l'image ci-dessus, la texture avec des textures de mip a maintenant une taille de 384 x 256. Oui, elle a beaucoup d'espace vide, mais peu importe comment nous emballons des textures plus petites, en général la taille de la texture d'un côté augmentera d'au moins 50%.

Mais cela n'est vrai que pour les textures mip précédemment créées; si le moteur de jeu est programmé pour les générer correctement, l'augmentation ne dépasse pas 33% de la taille de texture d'origine. Par conséquent, en raison d'une petite augmentation de la quantité de mémoire pour stocker les textures MIP, nous obtenons un gain en performances et en qualité visuelle.

Vous trouverez ci-dessous une comparaison d'images avec des textures MIP désactivées / activées:


Sur le côté gauche de l'image, les textures des boîtes ont été utilisées «telles quelles», ce qui a conduit à l'apparition de granularité et du soi-disant moiré au loin. À droite, l'utilisation de textures de mip a permis des transitions plus douces, et à l'horizon la texture de la boîte est floue dans une couleur uniforme.

Cependant, qui veut des textures floues pour gâcher les arrière-plans de leur jeu préféré?

Bilinéaire, trilinéaire, anisotrope - tout cela est pour moi une lettre chinoise


Le processus de sélection d'un pixel dans une texture pour le superposer sur un pixel dans un cadre est appelé échantillonnage de textures , et dans un monde idéal, il y aurait une texture qui correspond idéalement à la primitive pour laquelle il est conçu, indépendamment de la taille, de la position, de la direction, etc. En d'autres termes, l'échantillonnage de la texture serait un simple mappage de pixels texel un à un.

Mais comme ce n'est pas le cas, il y a plusieurs facteurs à considérer lors de l'échantillonnage des textures:

  • La texture a-t-elle été réduite ou agrandie?
  • La texture est-elle une texture source ou mip?
  • Sous quel angle la texture est-elle affichée?

Analysons-les dans l'ordre. Le premier facteur est assez évident: si la texture a été augmentée, alors dans la primitive, il y aura plus de texels couvrant le pixel dans la primitive que nécessaire; en diminuant, l'inverse est vrai - chaque texel devrait maintenant couvrir plusieurs pixels. Et c'est un problème.

Le deuxième facteur ne pose pas de problème, car les textures mip sont utilisées pour contourner le problème d'échantillonnage des textures des primitives lointaines, de sorte que la seule tâche consiste à afficher les textures sous un angle. Et oui, c'est aussi un problème. Pourquoi? Parce que toutes les textures sont des images générées pour une visualisation «strictement en face». Parlant dans un langage mathématique, la texture de surface normale correspond à la surface nominale sur laquelle la texture est actuellement affichée.

Par conséquent, s'il y a trop peu ou trop de texels, ou s'ils sont situés à un angle, alors un processus supplémentaire appelé filtrage de texture est requis . Si ce processus n'est pas utilisé, nous obtenons ceci:


Ici, nous avons remplacé la texture de la boîte par une texture avec la lettre R, pour montrer plus clairement dans quel désordre l'image se transforme sans filtrer les textures!

Les API graphiques telles que Direct3D, OpenGL et Vulkan fournissent le même ensemble de types de filtrage, mais utilisent des noms différents pour eux. En fait, ils se résument tous à ce qui suit:

  • Échantillonnage au point proche
  • Filtrage de texture linéaire
  • Filtrage de texture anisotrope

En fait, l' échantillonnage de l'échantillonnage ponctuel le plus proche n'est pas un filtre, car avec lui seul le texel le plus proche du pixel de texture requis est échantillonné (par exemple, copié de la mémoire), puis il est mélangé avec la couleur d'origine du pixel.

Ici le filtrage linéaire vient à notre aide. Les coordonnées de texel requises u, v sont transférées à l'équipement d'échantillonnage, mais au lieu de prendre le texel le plus proche de ces coordonnées, l'échantillonneur prend quatre texels. Ce sont des texels situés au-dessus, en dessous, à gauche et à droite du texel qui est sélectionné en échantillonnant les points les plus proches.

Ces quatre texels sont ensuite mélangés en utilisant une formule avec des poids. Dans Vulkan, par exemple, la formule ressemble à ceci:


T désigne la couleur du texel, où f est le résultat de la filtration, et 1-4 est la couleur de quatre texels échantillonnés. Les valeurs alpha et bêta sont prises en fonction de la distance entre le point de coordonnées u, v et le milieu de la texture.

Heureusement pour ceux impliqués dans les graphiques 3D, cela se produit automatiquement dans la puce graphique. En fait, c'est exactement ce qu'a fait la puce TMU de la carte 3dfx Voodoo: elle a échantillonné quatre texels puis les a mélangés. Dans Direct3D, ce processus a un nom étrange pour le filtrage bilinéaire.mais depuis l'époque de Quake et de la puce TMU, les cartes graphiques ont déjà appris à effectuer un filtrage bilinéaire en un seul cycle d'horloge (bien sûr, si la texture est déjà située dans la mémoire la plus proche).

Le filtrage linéaire peut être utilisé avec des textures mip, et si vous voulez compliquer le filtrage, vous pouvez prendre quatre texels de la texture, puis quatre autres du niveau suivant de texture mip, en les mélangeant tous. Et comment ça s'appelle dans Direct3D? Filtrage trilinéaire . D'où viennent les «trois» dans ce processus ? Nous ne savons donc pas ...

La dernière méthode de filtrage qui mérite d'être mentionnée est anisotrope . Il s'agit en fait d'une amélioration du processus effectué par filtrage bilinéaire ou trilinéaire. Initialement, il calculele degré d'anisotropie de la surface primitive (et c'est un processus étonnamment complexe ) - cette valeur augmente le changement du rapport d'aspect de la primitive en raison de son orientation:


La figure ci-dessus montre la même primitive carrée avec des longueurs de côté égales; mais en tournant progressivement, il se transforme en rectangle, et sa largeur change plus que sa hauteur. Par conséquent, la primitive de droite a un degré d'anisotropie supérieur à celui de gauche (et dans le cas d'un carré, le degré est nul).

De nombreux jeux 3D modernes vous permettent d'activer le filtrage anisotrope puis de changer son niveau (de 1x à 16x), mais qu'est-ce que cela change vraiment? Ce paramètre contrôle le nombre maximal d'échantillons de texels supplémentaires prélevés dans chaque échantillon linéaire initial. Supposons qu'un filtrage bilinéaire anisotrope de 8x soit activé dans le jeu. Cela signifie qu'au lieu de quatre valeurs de texel, il obtiendra 32 valeurs.

La différence lors de l'utilisation du filtrage anisotrope est clairement perceptible:


Montez simplement sur l'image ci-dessus et comparez l'échantillonnage des points les plus proches avec un filtrage trilinéaire anisotrope 16x maximum. Étonnamment lisse!

Mais pour cette beauté lisse des textures, vous devez payer avec les performances: aux paramètres maximaux, le filtrage trilinéaire anisotrope recevra 128 échantillons de la texture pour chaque pixel du rendu. Même avec les meilleurs GPU modernes, cela ne peut pas être réalisé en un seul cycle d'horloge.

Si vous prenez, par exemple, AMD Radeon RX 5700 XT, alors chacun des blocs de texturation à l'intérieur du processeur peut utiliser jusqu'à 32 adresses de texel dans un cycle d'horloge, puis dans le cycle d'horloge suivant charger 32 valeurs de texel à partir de la mémoire (dont chacune a une taille de 32 bits), puis mélanger quatre d'entre elles en une de plus tact. C'est-à-dire que mélanger 128 échantillons de texels en un seul nécessite au moins 16 cycles d'horloge.


GPU AMD RDNA Radeon RX 5700 avec technologie de processus à 7 nanomètres

Si la vitesse d'horloge du 5700 XT est de 1605 MHz, alors seize cycles ne prennent que 10 nanosecondes . L'exécution de ces cycles pour chaque pixel d'une image 4K en utilisant une seule unité de texture ne prendra que 70 millisecondes. Super, on dirait que la performance n'est pas un gros problème!

Même en 1996, 3Dfx Voodoo et les cartes similaires se sont rapidement adaptées aux textures. Au maximum, ils pouvaient donner 1 texel avec filtrage bilinéaire par cycle, et avec une fréquence de puce TMU de 50 MHz, cela signifiait que 50 millions de texels pouvaient être traités par seconde. Un jeu fonctionnant à 800 x 600 et 30 fps ne nécessite que 14 millions de texels avec filtrage bilinéaire par seconde.

Cependant, cela n'est vrai que dans l'hypothèse où toutes les textures sont dans la mémoire la plus proche et qu'un seul texel correspond à chaque pixel. Il y a vingt ans, l'idée de la nécessité de superposer plusieurs textures sur une primitive était complètement étrangère, mais aujourd'hui c'est un standard. Voyons pourquoi tout cela change.

Ajouter un éclairage


Pour comprendre pourquoi la texturation est devenue si importante, jetez un œil à cette scène de Quake:


C'est une image sombre, car l'obscurité était l'atmosphère du jeu, mais nous voyons que l'obscurité n'est pas la même partout - certains fragments de murs et de sols sont plus légers que d'autres, ce qui crée une sensation de légèreté dans ces zones.

Les primitives qui composent les murs et le sol sont superposées avec les mêmes textures, mais il existe une autre texture appelée «light map» mélangée aux valeurs des texels avant qu'elles ne soient appliquées aux pixels du cadre. À l'époque de Quake, les cartes d'éclairage ont été calculées à l'avance et créées par le moteur de jeu. Ils ont été utilisés pour générer des niveaux d'éclairage statiques et dynamiques.

L'avantage de leur utilisation est que les calculs d'éclairage complexes ont été effectués avec des textures plutôt qu'avec des sommets, ce qui a considérablement amélioré l'apparence de la scène au détriment des coûts à faible vitesse. Évidemment, l'image est imparfaite: au sol, on remarque que la frontière entre les zones éclairées et les ombres est très nette.

À bien des égards, une lightmap n'est qu'une autre texture (n'oubliez pas que ce sont tous des jeux de données 2D normaux), donc cette scène est l'un des premiers exemples d'utilisation du multitexturing. Comme son nom l'indique, il s'agit d'un processus dans lequel deux textures ou plus sont superposées à une primitive. L'utilisation de cartes d'éclairage dans Quake est devenue un moyen de surmonter les limites de l'ombrage Gouraud, mais dans le processus d'augmentation de la gamme de capacités des cartes graphiques, les méthodes d'application du multitexturing se sont également étendues.

3Dfx Voodoo, comme beaucoup d'autres cartes de cette époque, était limité dans la quantité d'opérations qu'il pouvait effectuer en une seule passe de rendu. En fait, une passe est un cycle de rendu complet: du traitement des sommets à la pixellisation de l'image, puis la modification des pixels et leur écriture dans le tampon d'image fini. Il y a vingt ans, les jeux utilisaient presque toujours le rendu en une seule passe.


Nvidia GeForce 2 Ultra, vers la fin de 2000. Image: Wikimedia

Cela s'est produit parce que le deuxième traitement de sommet juste pour appliquer des textures supplémentaires était trop coûteux en termes de performances. Après Voodoo, nous avons dû attendre quelques années lorsque les cartes graphiques ATI Radeon et Nvidia GeForce 2 sont apparues, capables de multitexturing en un seul passage.

Ces GPU avaient plusieurs unités de texture dans la zone de traitement des pixels (c'est-à-dire dans le pipeline ), donc obtenir un texel avec filtrage bilinéaire à partir de deux textures distinctes est devenu la tâche la plus simple. Cela a encore accru la popularité des cartes d'éclairage et a permis aux jeux de les rendre entièrement dynamiques, en changeant les valeurs d'éclairage en fonction des conditions de l'environnement de jeu.

Mais avec quelques textures, beaucoup plus pourrait être fait, alors explorons leurs capacités.

Changer la hauteur est normal


Dans cette série d'articles sur le rendu 3D, nous n'avons pas parlé de la façon dont le rôle du GPU affecte l'ensemble du processus (nous en parlerons, mais pas maintenant!). Mais si vous revenez à la partie 1 et lisez tout le processus complexe de traitement des sommets, vous pourriez penser que c'est la partie la plus difficile de tout le travail que le GPU doit faire.

Pendant longtemps, c'était le cas, et les programmeurs de jeux ont fait tout leur possible pour réduire cette charge. Ils ont dû recourir à toutes sortes d'astuces pour garantir la même qualité d'image que lors de l'utilisation de plusieurs sommets, mais ne les traitent pas.

La plupart de ces astuces utilisaient des textures appelées cartes de hauteur et cartes normales.. Ces deux concepts sont liés par le fait que ces derniers peuvent être créés à partir des premiers, mais pour l'instant, ne regardons qu'une technique appelée «bump mapping» .


Images créées dans un rendu de démonstration par Emil Persson . La texturation en relief est désactivée / activée. La texturation en relief

utilise un tableau 2D appelé «carte de hauteur» qui ressemble à une version étrange de la texture d'origine. Par exemple, l'image ci-dessus montre une texture de brique réaliste superposée sur deux surfaces planes. La texture et sa carte de hauteur ressemblent à ceci:


Les couleurs de la carte des hauteurs indiquent les normales de la surface des briques (nous avons décrit les normales dans la partie 1 d'une série d'articles). Lorsque le processus de rendu atteint le stade d'application de la texture de brique à la surface, une série de calculs est effectuée pour modifier la couleur de la texture de brique en fonction de ses normales.

En conséquence, les briques elles-mêmes semblent plus tridimensionnelles, malgré le fait qu'elles continuent de rester complètement plates. Si vous regardez attentivement, en particulier sur les bords des briques, vous pouvez voir les limites de cette technique: la texture semble légèrement déformée. Mais c'est une astuce rapide qui vous permet d'ajouter plus de détails sur la surface, donc la texturation en relief est très populaire.

Une carte normale est similaire à une carte de hauteur, seules les couleurs de texture sont les normales elles-mêmes. En d'autres termes, les calculs pour convertir la carte de hauteur en normale ne sont pas nécessaires. Vous pouvez poser une question: comment les couleurs peuvent-elles décrire un vecteur dans l'espace? La réponse est simple: chaque texel a un ensemble de valeurs r, g, b (rouge, vert, bleu) et ces valeurs correspondent directement aux valeurs x, y, z du vecteur normal.


Le diagramme de gauche montre le changement de direction des normales sur une surface inégale. Pour décrire les mêmes normales avec une texture plate (contour central), nous leur attribuons des couleurs. Dans ce cas, nous avons utilisé les valeurs r, g, b (0,255,0) pour le vecteur dirigé directement vers le haut, puis augmenté la valeur du rouge pour l'inclinaison vers la gauche et du bleu pour l'inclinaison vers la droite.

Gardez à l'esprit que cette couleur ne se mélange pas avec le pixel d'origine, elle indique simplement au processeur dans quelle direction la normale indique afin qu'il puisse calculer correctement les angles entre la caméra, les sources de lumière et la surface texturée.

Les avantages de la texturation en relief et des cartes normales sont pleinement visibles lorsque l'éclairage dynamique est utilisé dans la scène et lorsque le processus de rendu calcule l'effet du changement d'éclairage pixel par pixel, et non pour chaque sommet. Aujourd'hui, les jeux modernes utilisent un ensemble de textures pour améliorer la qualité de cette astuce.


Image: Ryan Benno de Twitter

Étonnamment, ce mur d'aspect réaliste n'est qu'une surface plane, les détails des briques et du ciment de maçonnerie ne sont pas fabriqués à l'aide de millions de polygones. Au lieu de cela, seulement cinq textures et l'utilisation réfléchie des calculs suffisent.

Une carte de hauteur a été utilisée pour générer une projection d'ombre avec des briques, et une carte normale a été utilisée pour simuler tous les changements mineurs de surface. La texture de rugosité a été utilisée pour changer la façon dont la lumière est réfléchie par divers éléments du mur (par exemple, la brique lisse réfléchit la lumière plus uniformément que le ciment brut).

La dernière carte, nommée dans l'image AO, crée une partie du processus appelé occlusion ambiante: nous examinerons cette technique plus en détail dans les articles suivants, mais pour l'instant, disons qu'elle aide à augmenter le réalisme des ombres.

La cartographie des textures est un processus critique.


La texturation est absolument essentielle lors du développement de jeux. Prenons, par exemple, le jeu Kingdom Come: Deliverance 2019 , un RPG à la première personne qui se déroule en Bohême au XVe siècle. Les concepteurs ont cherché à créer le monde le plus réaliste de cette période. Et pour plonger le joueur dans la vie d'il y a des centaines d'années, il est préférable de mettre en œuvre un paysage, des bâtiments, des vêtements, des coiffures, des objets de tous les jours historiquement précis et bien plus encore.

Chaque texture de cette image du jeu a été créée manuellement par des artistes, et aussi grâce à un moteur de rendu contrôlé par des programmeurs. Certains d'entre eux sont petits, avec des détails simples, et sont donc légèrement filtrés ou traités avec d'autres textures (par exemple, des ailes de poulet).


D'autres ont une haute résolution et de nombreux petits détails; ils subissent un filtrage et un mélange anisotropes avec des cartes normales et d'autres textures - il suffit de regarder le visage de la personne au premier plan. La différence dans les exigences de texturation de chaque objet de scène est prise en compte par les programmeurs.

Tout cela se produit aujourd'hui dans de nombreux jeux, car les joueurs attendent des niveaux de détail et de réalisme toujours plus élevés. Les textures deviennent plus grandes et de plus en plus se superposent à la surface, mais le processus d'échantillonnage des texels et de leur superposition sur les pixels reste essentiellement le même qu'à l'époque de Quake. Les meilleures technologies ne meurent jamais, quel que soit leur âge!

All Articles