Fonctionnement du rendu de jeu 3D: pixellisation et lancer de rayons

image

Partie 1: traitement des sommets

Dans cet article, nous allons voir de plus près ce qui arrive au monde 3D une fois tous ses sommets traités. Nous devrons à nouveau secouer la poussière des manuels de mathématiques, nous habituer à la géométrie des pyramides de troncature et résoudre le mystère des perspectives. Nous plongerons également brièvement dans la physique du lancer de rayons, de l'éclairage et des matériaux.

Le sujet principal de cet article est une étape de rendu importante, dans laquelle le monde tridimensionnel de points, segments et triangles devient une grille bidimensionnelle de blocs multicolores. Très souvent, ce processus semble invisible, car la conversion de 3D en 2D est invisible, contrairement au processus décrit dans l' article précédent , où l'on pouvait immédiatement voir l'influence des vertex shaders et de la tessellation. Si vous n'êtes pas encore prêt pour cela, vous pouvez commencer avec notre article 3D Game Rendering 101 .

Préparation pour deux mesures


La grande majorité des lecteurs lisent ce site Web sur un écran ou un écran de smartphone complètement plat; mais même si vous avez une technique moderne - un moniteur incurvé, l'image affichée par lui se compose également d'une grille plate de pixels multicolores. Cependant, lorsque vous jouez au nouveau Call of Mario: Deathduty Battleyard, les images semblent tridimensionnelles. Les objets se déplacent dans la scène, deviennent plus ou moins grands, s'approchant et s'éloignant de la caméra.


En prenant Fallout 4 de Bethesda comme exemple, sorti en 2014, nous pouvons facilement voir comment les pics sont traités, créant un sentiment de profondeur et de distance; Cela est particulièrement visible en mode filaire (voir ci-dessus).

Si vous prenez n'importe quel jeu 3D au cours des deux dernières décennies, presque chacun d'eux exécute la même séquence d'actions pour convertir le monde 3D des sommets en un tableau de pixels 2D. Cette conversion est souvent appelée rastérisation , mais ce n'est qu'une des nombreuses étapes de l'ensemble du processus.

Nous devons analyser les différentes étapes et étudier les techniques et les calculs qui y sont utilisés. Comme référence, nous utiliserons la séquence utilisée dans Direct3D. L'image ci-dessous montre ce qui se passe avec chaque sommet du monde:


Pipeline de conversion Direct3D

Dans le premier article, nous avons vu ce qui se passe dans l'espace mondial (espace mondial): ici, à l'aide de différents calculs matriciels, les sommets sont transformés et colorés. Nous allons sauter l'étape suivante, car dans l'espace de la caméra, seuls les sommets sont convertis et ajustés après le déplacement, de sorte que la caméra devient un point de référence.

Les étapes suivantes sont trop compliquées à ignorer, car elles sont absolument nécessaires pour la transition de la 3D à la 2D - si elles sont correctement mises en œuvre, notre cerveau regardera un écran plat, mais «verra» une scène avec profondeur et échelle. Si tout est mal fait, l'image sera très étrange!

Tout est question de perspective


La première étape de cette séquence consiste à définir la portée du point de vue de la caméra. Pour ce faire, vous devez d'abord définir les angles du champ de vision horizontal et vertical - le premier change souvent dans les jeux, car les gens ont développé une vision périphérique horizontale meilleure que verticale.

Nous pouvons comprendre cela en regardant l'image avec le champ de vision d'une personne:


Deux coins du champ de vision (champ de vision, fov) définissent la forme de la pyramide tronconique - une pyramide 3D avec une base carrée émanant de la caméra. Le premier coin définit la fov verticale , le deuxième horizontal ; nous les désignons par les symboles α et β . En fait, nous voyons le monde pas tout à fait comme ça, mais du point de vue des calculs, il est beaucoup plus facile de travailler avec la pyramide de troncature plutôt que d'essayer de générer une visibilité réaliste.


Vous devez également spécifier deux autres paramètres: l'emplacement des plans de détourage proches (ou avant) et éloignés (arrière) (plans de détourage) . La première coupe le sommet de la pyramide, mais détermine essentiellement à quelle distance de la position de la caméra tout est dessiné; ce dernier fait de même, mais détermine à quelle distance de la caméra les primitives seront rendues.

La taille et l'emplacement du plan de troncature proche sont très importants car ils deviennent ce qu'on appelle une fenêtre . En fait, c'est ce que nous voyons sur le moniteur, c'est-à-dire cadre rendu, et dans la plupart des API graphiques, la fenêtre est dessinée à partir du coin supérieur gauche. Dans l'image ci-dessous, le point (a1, b2) sera l'origine du plan: la largeur et la hauteur du plan sont mesurées par rapport à lui.


Le rapport hauteur / largeur de la fenêtre d'affichage est important non seulement pour afficher le monde rendu, mais également pour correspondre au rapport hauteur / largeur du moniteur. Pendant de nombreuses années, la norme était de 4: 3 (ou 1,3333 ... en décimal). Cependant, aujourd'hui, la majorité joue dans un rapport d'aspect 16: 9 ou 21: 9, appelé écran large et écran ultra large.

Les coordonnées de chaque sommet dans l'espace de la caméra doivent être transformées afin qu'elles s'adaptent toutes au plan de troncature proche, comme indiqué ci-dessous:


Garniture latérale et supérieure de la pyramide

La transformation est effectuée à l'aide d'une autre matrice appelée matrice de projection en perspective . Dans l'exemple ci-dessous, pour effectuer les transformations, nous utilisons les angles de l'oscilloscope et la position des plans de troncature; cependant, vous pouvez utiliser la taille de la fenêtre à la place.


Le vecteur de position du sommet est multiplié par cette matrice, ce qui nous donne un nouvel ensemble de coordonnées transformées.


Voila! Maintenant, tous les sommets sont écrits de telle manière que le monde source est présenté comme une perspective 3D, et les primitives près du plan de troncature avant semblent plus grandes que celles plus proches du plan lointain.

Bien que la taille de la fenêtre d'affichage et les angles d'angle de vue soient liés, ils peuvent être traités individuellement. En d'autres termes, vous pouvez définir la pyramide de troncature de manière à obtenir un plan de troncature proche dont la taille et le rapport d'aspect diffèrent de la fenêtre. Pour ce faire, une étape supplémentaire est nécessaire dans la chaîne d'opérations, à laquelle les sommets dans le plan de troncature proche doivent être à nouveau transformés pour tenir compte de cette différence.

Cependant, cela peut entraîner une distorsion de la perspective visible. En utilisant le jeu Bethesda Skyrim 2011 comme exemple , nous pouvons voir comment la modification de l'angle horizontal de la zone de visibilité β tout en conservant le même rapport hauteur / largeur de la fenêtre affecte grandement la scène:


Dans cette première image, nous avons défini β = 75 °, et la scène semble complètement normale. Essayons maintenant de définir β = 120 °:


Deux différences sont immédiatement perceptibles - premièrement, maintenant nous voyons beaucoup plus des côtés de notre "champ de vision"; deuxièmement, les objets semblent désormais beaucoup plus éloignés (surtout les arbres). Cependant, l'effet visuel sur la surface de l'eau semble maintenant faux, car le processus n'a pas été conçu pour une telle zone de visibilité.

Imaginons maintenant que notre personnage ait des yeux extraterrestres, et réglons β = 180 °!


Une telle zone de visibilité crée une scène presque panoramique, mais vous devez la payer avec une sérieuse distorsion des objets rendus sur les bords. Cela s’est produit à nouveau du fait que les concepteurs du jeu n’ont pas prévu une telle situation et n’ont pas créé les ressources et les effets visuels du jeu pour un tel angle de vision (la valeur standard est d’environ 70 °).

Il peut sembler que dans les images ci-dessus, la caméra a bougé, mais ce n'est pas le cas - le seul changement est de modifier la pyramide de troncature, qui à son tour a changé les dimensions du plan de troncature proche. Sur chaque image, le rapport d'aspect de la fenêtre reste le même, de sorte que la matrice de mise à l'échelle est appliquée aux sommets afin que tout y rentre.

Alors, restez-vous ou partez-vous?


Après avoir effectué les transformations au stade de la projection, nous passons à ce qu'on appelle un espace de clip . Bien que cela se fasse après la projection, il est plus facile de montrer ce qui se passe si nous effectuons les opérations à l'avance:


Dans la figure ci-dessus, nous voyons que dans le canard en caoutchouc, l'une des chauves-souris et une partie des arbres, les triangles sont à l'intérieur de la pyramide de troncature; cependant, l'autre chauve-souris et l'arbre le plus éloigné sont en dehors des limites de la pyramide de troncature. Bien que les sommets qui composent ces objets aient déjà été traités, nous ne les verrons pas dans la fenêtre. Cela signifie qu'ils sont coupés .

Lors de la troncature le long de la pyramide (écrêtage tronconique), toutes les primitives en dehors de la pyramide de troncature sont complètement supprimées et celles situées aux frontières sont converties en nouvelles primitives. La troncature n'améliore pas considérablement les performances, car tous ces sommets invisibles ont déjà été traités avant cette étape dans les vertex shaders, etc. Si nécessaire, l'étape de troncature entière peut même être complètement ignorée, mais cette fonctionnalité n'est pas prise en charge par toutes les API (par exemple, l'OpenGL standard ne permettra pas qu'elle soit ignorée, mais cela peut être fait en utilisant l'extension API).


Il convient de noter que la position du plan de troncature éloignée dans les jeux n'est pas toujours égale à la distance de tirage , car celle-ci est contrôlée par le moteur de jeu lui-même. Le moteur effectue également un écrêtage sur la pyramide (tri sélectif) - il exécute un code qui détermine si l'objet sera dessiné dans la pyramide de troncature et s'il affectera les objets visibles; si la réponse est non , l'objet n'est pas transféré au rendu. Ce n'est pas la même chose que l'écrêtage frustrum car il supprime également les primitives en dehors de la pyramide, mais elles ont déjà franchi l'étape de traitement des sommets. Lors de l'abattage, ils ne sont pas du tout traités, ce qui économise pas mal de ressources.

Nous avons fait toutes les transformations et la troncature, et il semble que les sommets soient enfin prêts pour la prochaine étape de la séquence de rendu. Mais en fait, ce n'est pas le cas, car tous les calculs effectués au stade du traitement des sommets et dans les opérations de transformation de l'espace mondial en espace de troncature doivent être effectués dans un système de coordonnées uniforme (c'est-à-dire que chaque sommet a 4 composantes, pas 3) . Cependant, la fenêtre d'affichage est entièrement bidimensionnelle, c'est-à-dire que l'API s'attend à ce que les informations de sommet contiennent uniquement les valeurs de x, y (bien que la valeur de la profondeur z soit enregistrée).

Pour se débarrasser du quatrième composant, une division en perspective est effectuée, dans laquelle chaque composant est divisé par la valeur de w . Cette opération restreint x et y à l' intervalle de valeurs possibles [-1,1] et z à l'intervalle [0,1]. Celles-ci sont appelées coordonnées de périphérique normalisées (NDC).

Si vous voulez en savoir plus sur ce que nous venons d'expliquer et que vous aimez les mathématiques, alors lisez l' excellent tutoriel sur ce sujet Song Ho An. Maintenant, transformons ces sommets en pixels!

Nous maîtrisons la rastérisation


Comme dans le cas des transformations, nous examinerons les règles et processus utilisés pour transformer une fenêtre en grille de pixels, en utilisant Direct3D comme exemple. Ce tableau ressemble à une feuille de calcul Excel avec des lignes et des colonnes, dans laquelle chaque cellule contient différentes valeurs de données (telles que la couleur, les valeurs de profondeur, les coordonnées de texture, etc.). Habituellement, cette grille est appelée image raster , et le processus de sa génération est appelé rasterisation . Dans l'article Rendu 3D 101, nous avons simplifié cette procédure:


L'image ci-dessus donne l'impression que les primitives sont simplement coupées en petits blocs, mais en réalité il y a beaucoup plus d'opérations. La toute première étape consiste à déterminer si la primitive fait face à la caméra - par exemple, dans l'image ci-dessus avec une pyramide de troncature, les primitives qui composent le dos du lapin gris ne seront pas visibles. Par conséquent, bien qu'ils soient présents dans la fenêtre, ils n'ont pas besoin d'être rendus.

Nous pouvons à peu près imaginer à quoi il ressemble en regardant le diagramme ci-dessous. Le cube a subi diverses transformations pour placer le modèle 3D dans l'espace 2D de l'écran et du point de vue de la caméra, certaines faces du cube ne sont pas visibles. Si nous supposons que toutes les surfaces sont opaques, alors certaines de ces primitives peuvent être ignorées.


De gauche à droite: espace monde> espace caméra> espace projection> espace écran

Dans Direct3D, cela peut être implémenté en indiquant au système quel sera l' état de rendu , et cette instruction indiquera clairement qu'il est nécessaire de supprimer ( couper ) les côtés de chaque primitive en regardant vers l'avant ou vers l'arrière (ou de ne pas couper complètement, par exemple, en mode filaire ) . Mais comment sait-elle de quel côté regarde en avant ou en arrière? Lorsque nous avons examiné les mathématiques du traitement des sommets , nous avons vu que les triangles (ou plutôt les sommets) ont des vecteurs normaux indiquant au système dans quelle direction il regarde. Grâce à ces informations, vous pouvez effectuer une simple vérification, et si la primitive échoue, elle est supprimée de la chaîne de rendu.

Il est maintenant temps d'appliquer la grille de pixels. Il s'agit là encore d'un processus d'une complexité inattendue, car le système doit comprendre si le pixel est à l'intérieur de la primitive - complètement, partiellement ou pas du tout. Pour ce faire, le processus de test de couverture est effectué. La figure ci-dessous montre comment les triangles sont pixellisés dans Direct3D 11:


La règle est assez simple: un pixel est considéré comme étant à l'intérieur du triangle si le centre du pixel passe une vérification, ce que Microsoft appelle la règle «en haut à gauche» . «Haut» fait référence à la vérification de la ligne horizontale; le centre du pixel doit être sur cette ligne. «Gauche» fait référence à des lignes non horizontales et le centre du pixel doit être à gauche d'une telle ligne. Il existe d'autres règles liées aux non-primitives, par exemple, des segments et des points simples, et lors de l'utilisation du multi - échantillonnage , des conditions supplémentaires apparaissent si dans les règles.

Si vous regardez attentivement la documentation de Microsoft, vous pouvez voir que les formes créées par les pixels ne sont pas très similaires aux primitives d'origine. En effet, les pixels sont trop grands pour créer un triangle réaliste - l'image bitmap ne contient pas suffisamment de données sur les objets d'origine, ce qui provoque un phénomène appelé aliasing .

Regardons l'alias avec un exemple de UL Benchmark 3DMark03 :


Pixellisation de 720 x 480 pixels

Dans la première image, l'image raster a une très faible résolution - 720 x 480 pixels. Le repliement est clairement visible sur la balustrade et l'ombre projetée par les armes du soldat supérieur. Comparez cela avec le résultat obtenu pendant la pixellisation avec une augmentation de 24 fois du nombre de pixels:


Pixellisation 3840 x 2160 pixels

On voit ici que l'aliasing sur la balustrade et l'ombre a complètement disparu. Il semble que vous devez toujours utiliser un grand bitmap, mais la taille de la grille doit être prise en charge par le moniteur sur lequel le cadre sera affiché. Et compte tenu du fait que tous ces pixels doivent être traités, il est évident qu'il y aura une diminution des performances.

Le multi-échantillonnage peut aider ici. Voici comment cela fonctionne dans Direct3D:


Au lieu de vérifier si le centre du pixel correspond aux règles de pixellisation, plusieurs points à l'intérieur de chaque pixel (appelés échantillons ou sous-échantillons de sous-pixels) sont vérifiés , et si certains d'entre eux satisfont aux exigences, ils font partie de la figure. Il peut sembler qu'il n'y ait aucun avantage et que l'aliasing est même amélioré, mais lors de l'utilisation du multi-échantillonnage, les informations sur les sous-échantillons couverts par la primitive et les résultats du traitement des pixels sont stockées dans un tampon en mémoire.

Ce tampon est ensuite utilisé pour mélanger ces sous-échantillons et pixels afin que les bords de la primitive soient moins déchirés. Nous examinerons plus en détail l'aliasing dans un autre article, mais pour l'instant, ces informations nous suffisent pour comprendre ce que le multi-échantillonnage peut faire lorsqu'il est utilisé pour pixelliser trop peu de pixels:


Comme vous pouvez le voir, la quantité d'aliasing sur les bords de différentes formes a considérablement diminué. Une rastérisation à haute résolution est certainement meilleure, mais la dégradation des performances peut vous inciter à utiliser le multi-échantillonnage.

Également pendant la pixellisation, un test d'occlusion est effectué. Cela est nécessaire car la fenêtre sera remplie de primitives superposées les unes aux autres - par exemple, dans la figure ci-dessus, les triangles prospectifs qui composent le soldat au premier plan chevauchent les mêmes triangles d'un autre soldat. En plus de vérifier si la primitive recouvre un pixel, vous pouvez également comparer les profondeurs relatives, et si une surface est derrière une autre, elle doit être supprimée du processus de rendu restant.

Cependant, si la primitive proche est transparente, alors la primitive lointaine restera visible, bien qu'elle ne réussisse pas le test de chevauchement. C'est pourquoi presque tous les moteurs 3D effectuent des vérifications de chevauchement avant d' envoyer des données au GPU et créent à la place quelque chose appelé un z-buffer , qui fait partie du processus de rendu. Ici, le cadre est créé de la manière habituelle, mais au lieu d'enregistrer les couleurs de pixels prêtes à l'emploi dans la mémoire, le GPU enregistre uniquement les valeurs de profondeur. Plus tard, ils peuvent être utilisés dans des shaders pour vérifier la visibilité et avec un grand contrôle et une grande précision des aspects liés aux objets qui se chevauchent.


Dans l'image ci-dessus, plus la couleur des pixels est sombre, plus le sujet est proche de l'appareil photo.Le cadre est rendu une fois pour créer un z-buffer, puis rendu à nouveau, mais cette fois pendant le traitement des pixels, un shader est lancé, vérifiant les valeurs dans le z-buffer. S'il est invisible, la couleur des pixels n'est pas écrite dans le tampon de l'image finie.

Jusqu'à présent, notre dernière étape principale sera l' interpolation des attributs des sommets - dans le schéma simplifié d'origine, la primitive était un triangle complet, mais n'oubliez pas que la fenêtre de vue est remplie uniquement avec les coins des figures, et non avec les figures elles-mêmes. Autrement dit, le système doit déterminer la couleur, la profondeur et la texture de la primitive entre les sommets, et cette opération est appelée interpolation . Comme vous l'avez peut-être deviné, il s'agit d'un autre calcul, et ce n'est pas si simple.

Malgré le fait que l'écran tramé soit présenté en 2D, les structures à l'intérieur représentent une perspective 3D. Si les lignes étaient vraiment bidimensionnelles, nous pourrions utiliser une simple équation linéaire pour calculer les couleurs et d'autres choses , car nous nous déplaçons d'un sommet à un autre. Mais en raison de l'aspect 3D de la scène, l'interpolation doit tenir compte de cette perspective; Pour en savoir plus sur ce processus, lisez l' excellent article de Simon Young .

Ainsi, la tâche est terminée - de sorte que le monde 3D des sommets se transforme en une grille 2D de blocs colorés. Mais nous n'avons pas encore tout à fait terminé.

De l'avant à l'arrière (à quelques exceptions près)


Avant de terminer l'examen de la pixellisation, nous devons parler de l'ordre de la séquence de rendu. Nous ne parlons pas de l'étape où, par exemple, la tessellation apparaît dans la séquence de traitement; nous voulons dire l'ordre dans lequel les primitives sont traitées. Les objets sont généralement traités dans l'ordre dans lequel ils se trouvent dans le tampon d'index (un bloc de mémoire indiquant au système comment les sommets sont regroupés) et cela peut affecter de manière significative la façon dont les objets et les effets transparents sont traités.

La raison en est que les primitives sont traitées une à la fois, et si vous rendez d'abord celles devant, alors toutes celles qui se trouvent derrière elles seront invisibles (c'est là que l'abattage d'occlusion entre en jeu) et peuvent être rejetées du processus (aidant à sauver performances). Ceci est généralement appelé rendu avant-arrière , et pour ce processus, le tampon d'index doit être ordonné de cette manière.

Cependant, si certaines de ces primitives sont transparentes devant la caméra, le rendu d'avant en arrière entraînera la perte d'objets qui se trouvent derrière la transparence. Une solution consiste à effectuer un rendu vers l'arrière, dans lequel les primitives et les effets transparents sont calculés en dernier.


De gauche à droite: l'ordre dans la scène, le rendu d'avant en arrière, le rendu d'arrière en avant

C'est-à-dire que dans tous les jeux modernes, le rendu est effectué d'arrière en avant? Dans tous les cas, n'oubliez pas que le rendu de chaque primitive individuelle entraînera une diminution des performances beaucoup plus importante que le rendu uniquement de ce que nous voyons. Il existe d'autres façons de traiter des objets transparents, mais dans le cas général, il n'y a pas de solution idéale adaptée à n'importe quel système, et chaque situation doit être considérée séparément.

En fait, cela nous permet de comprendre les principaux avantages et inconvénients de la pixellisation - sur un équipement moderne, c'est un processus rapide et efficace, mais c'est toujours un reflet approximatif de ce que nous voyons. Dans le monde réel, chaque objet peut absorber, réfléchir et parfois réfracter la lumière, et tout cela affecte l'apparence finale de la scène affichée. Divisant le monde en primitives et n'en rendant que des parties, nous obtenons rapidement. mais un résultat très approximatif.

Maintenant, s'il y avait un autre moyen ...

Une autre façon est: le lancer de rayons!


Il y a près de cinquante ans, un informaticien du nom d'Arthur Eppel a travaillé sur un système de rendu d'images sur un ordinateur dans lequel un faisceau de lumière était émis par la caméra en ligne droite jusqu'à ce qu'il entre en collision avec un objet. Après la collision, les propriétés du matériau (sa couleur, sa réflectivité, etc.) ont modifié la luminosité du faisceau lumineux. Pour chaque pixel de l'image rendue, il y avait un rayon émis et l'algorithme a effectué une chaîne de calculs pour déterminer la couleur du pixel. Le processus d'Eppel est appelé lancer de rayons .

Environ dix ans plus tard, un autre scientifique nommé John Whiteda développé un algorithme mathématique qui met en œuvre le processus Eppel, mais lorsqu'un rayon entre en collision avec un objet, il génère des rayons supplémentaires divergeant dans différentes directions, selon le matériau de l'objet. Comme ce système générait de nouveaux faisceaux à chaque interaction avec des objets, l'algorithme était par nature récursif et beaucoup plus complexe sur le plan des calculs; cependant, elle avait un avantage significatif sur la méthode d'Eppel, car il pouvait correctement prendre en compte les réflexions, les réfractions et les ombres. Cette procédure est appelée raytracing (ray traçage) ( à proprement parler, il est l'inverse raytracing parce que nous suivons le faisceau de la caméra et non par les objets) et depuis lors , il est devenu un saint graal pour l' infographie et des films .


À partir de l'image ci-dessus, vous pouvez comprendre le fonctionnement de l'algorithme Whited. Pour chaque pixel du cadre, un faisceau est émis par la caméra et se déplace jusqu'à ce qu'il atteigne la surface. Dans cet exemple, la surface est translucide, de sorte que la lumière peut être réfléchie et réfractée à travers elle. Dans les deux cas, des rayons secondaires sont générés qui voyagent jusqu'à ce qu'ils entrent en collision avec la surface. De nouveaux rayons secondaires sont également générés pour tenir compte de la couleur des sources lumineuses et des ombres qu'elles créent.

La nature récursive du processus est que des rayons secondaires peuvent être générés chaque fois qu'un nouveau rayon émis coupe la surface. Cela peut rapidement devenir incontrôlable, de sorte que le nombre de rayons secondaires générés est toujours limité. Une fois le trajet du faisceau terminé, la couleur à chaque point final est calculée en fonction des propriétés du matériau de cette surface. Cette valeur est ensuite transmise le long du rayon précédent, en changeant la couleur de cette surface, et ainsi de suite, jusqu'à ce que nous atteignions le point de départ du rayon primaire, à savoir le pixel dans le cadre.

Un tel système peut être extrêmement complexe et même des scènes simples peuvent générer une grande quantité de calcul. Heureusement, il existe des astuces qui simplifient le travail - tout d'abord, vous pouvez utiliser un équipement spécialement conçu pour accélérer ces opérations mathématiques, semblable à la façon dont cela se passe avec les mathématiques matricielles dans le traitement des vertex (plus de détails plus loin). Une autre astuce importante est une tentative d'accélérer le processus de détermination de l'objet dans lequel le rayon est tombé et de l'endroit exact de leur intersection - si l'objet est composé de nombreux triangles, cette tâche peut être étonnamment difficile:


Source: Ray tracing en temps réel avec Nvidia RTX.Au

lieu de vérifier chaque triangle individuel dans chaque objet, une liste de volumes englobants (BV) est générée avant d'effectuer le ray tracing - ce sont des parallélépipèdes ordinaires qui décrivent un objet. Pour diverses structures à l'intérieur de l'objet, des volumes de délimitation plus petits sont créés de manière cyclique.

Par exemple, le premier BV sera le lapin entier. Le couple suivant décrira sa tête, ses jambes, son corps, sa queue, etc.; chaque volume à son tour sera une autre collection de volumes pour des structures plus petites de la tête, du corps, etc., et le dernier niveau de volume contiendra un petit nombre de triangles pour vérification. Tous ces volumes sont souvent organisés dans une liste ordonnée (appelée la hiérarchie BVou BVH); grâce à cela, le système vérifie à chaque fois une quantité relativement faible de BV:


Bien que l'utilisation de BVH, à proprement parler, n'accélère pas le lancer de rayons lui-même, générer une hiérarchie et l'algorithme de recherche subséquent requis dans le cas général est beaucoup plus rapide que de vérifier l'intersection d'un rayon avec l'un des millions de triangles dans le monde 3D.

Aujourd'hui, des programmes tels que Blender et POV-ray utilisent le ray tracing avec des algorithmes supplémentaires (tels que le photon tracing et la radiosité) pour générer des images très réalistes:


La question évidente peut se poser: si le lancer de rayons est si bon, pourquoi n’est-il pas utilisé partout? La réponse réside dans deux domaines: premièrement, même un simple traçage des rayons crée des millions de rayons qui doivent être calculés encore et encore. Le système démarre avec un seul faisceau par pixel d'écran, c'est-à-dire qu'avec une résolution de 800 x 600, il génère 480 000 rayons primaires, puis chacun génère de nombreux rayons secondaires. C'est un travail très difficile, même pour les PC de bureau modernes. Le deuxième problème est que le simple lancer de rayons n'est pas très réaliste et pour sa bonne mise en œuvre, vous avez besoin de tout un tas d'équations très complexes supplémentaires.

Même avec un équipement moderne, la quantité de travail dans les jeux 3D est inaccessible pour une implémentation en temps réel. En rendu 3D 101nous avons vu qu'un repère de lancer de rayons prend des dizaines de secondes pour créer une seule image basse résolution.

Comment le premier Wolfenstein 3D a-t-il effectué le lancer de rayons en 1992, et pourquoi des jeux comme Battlefield V et Metro Exodus , sortis en 2019, offrent-ils des capacités de lancer de rayons ? Réalisent-ils une pixellisation ou un lancer de rayons? Peu à peu des deux.

Une approche hybride pour le présent et l'avenir


En mars 2018, Microsoft a annoncé la sortie d'une nouvelle extension d'API pour Direct3D 12 appelée DXR (DirectX Raytracing). Il s'agissait d'un nouveau pipeline graphique qui complète les pipelines de tramage et de calcul standard. Des fonctionnalités supplémentaires ont été fournies par l'ajout de shaders, de structures de données, etc., mais n'ont pas nécessité de prise en charge matérielle, à l'exception de celle qui était déjà nécessaire pour Direct3D 12.


Lors de la même conférence des développeurs de jeux, au cours de laquelle Microsoft a parlé de DXR , Electronic Arts a parlé de son projet Pica Pica - une expérience avec un moteur 3D utilisant DXR. La société a montré que le lancer de rayons peut être utilisé, mais pas pour rendre le cadre entier. La majeure partie du travail utilise des techniques de tramage traditionnelles et des shaders de calcul, tandis que DXR est utilisé dans des domaines spécifiques. Autrement dit, le nombre de rayons générés est bien inférieur à ce qu'il serait pour toute la scène.


Cette approche hybride a été utilisée dans le passé, quoique dans une moindre mesure. Par exemple, Wolfenstein 3D a utilisé le lancer de rayons pour rendre un cadre, mais il a été effectué avec un faisceau par colonne de pixels, pas un pixel. Cela peut encore sembler impressionnant, à moins que vous vous souveniez que le jeu a fonctionné avec une résolution de 640 x 480 [env. transl.: en fait 320 x 200], c'est-à-dire qu'en même temps pas plus de 640 rayons ont été émis.

Les cartes graphiques du début de 2018 comme l'AMD Radeon RX 580 ou la Nvidia GeForce 1080 Ti répondaient aux exigences du DXR, mais même avec leurs capacités informatiques, on craignait qu'elles ne soient pas assez puissantes pour donner un sens au DXR.

La situation a changé en août 2018 lorsque Nvidia a publié sa dernière architecture GPU , nommée Turing . La caractéristique la plus importante de cette puce était l'apparition des soi-disant noyaux RT: des blocs logiques séparés pour accélérer les calculs de l'intersection rayon-triangle et le passage de la hiérarchie des volumes englobants (BVH). Ces deux processus sont des procédures chronophages pour déterminer les points d'interaction de la lumière avec les triangles qui composent les objets de la scène. Étant donné que les cœurs RT étaient des unités de processeur Turing uniques, leur accès ne pouvait se faire que via l'API propriétaire Nvidia.

Le premier jeu à prendre en charge cette fonctionnalité était Battlefield V. d'EA Lorsque nous y avons testé le DXR , nous avons été impressionnés par l'amélioration des réflexions dans l'eau, sur l'herbe et les métaux, ainsi que par une diminution correspondante des performances:


Pour être honnête, les correctifs ultérieurs ont amélioré la situation, mais il y avait toujours une diminution de la vitesse de rendu des images (et c'est toujours le cas). En 2019, d'autres jeux prenaient en charge cette API et effectuaient le lancer de rayons pour des parties individuelles du cadre. Nous avons testé Metro Exodus et Shadow of the Tomb Raider , confrontés à la même situation - l'utilisation active de DXR réduit considérablement la fréquence d'images.

Vers la même époque, UL Benchmarks a annoncé la création d'un test de fonction DXR pour 3DMark :


DXR est utilisé dans la carte graphique Nvidia Titan X (Pascal) - oui, le résultat est de 8 ips

Cependant, une étude des jeux avec prise en charge DXR et le test 3DMark ont ​​montré que le ray tracing même en 2019 reste une tâche très difficile pour le GPU, même à un prix de plus de 1000 $. Est-ce à dire que nous n'avons pas de réelle alternative à la tramage?

Les fonctionnalités progressives des technologies graphiques 3D grand public sont souvent très coûteuses et leur prise en charge initiale des nouvelles fonctionnalités API peut être assez fragmentée ou lente (comme nous l'avons découvert lors du test de Max Payne 3 sur différentes versions de Direct3D en 2012). Ce dernier problème se pose généralement parce que les développeurs de jeux essaient d'incorporer autant de fonctionnalités modernes que possible dans leurs produits, parfois sans expérience suffisante.

Cependant, les shaders de vertex et de pixels, la tessellation, le rendu HDR et l'occlusion ambiante de l'espace à l'écran étaient également des techniques coûteuses adaptées uniquement aux GPU puissants, et maintenant ils sont la norme pour les jeux et de nombreuses cartes graphiques sont prises en charge. La même chose se produira avec le lancer de rayons; au fil du temps, il se transformera simplement en un autre paramètre de détail, activé par défaut pour la plupart des joueurs.

En conclusion


Nous sommes donc arrivés à la fin de la deuxième partie de l'analyse, dans laquelle nous avons approfondi le monde des graphiques 3D. Nous avons appris comment les sommets des mondes et des modèles sont transférés de trois dimensions et se transforment en une image 2D plate. Nous avons vu que nous devons prendre en compte la portée et réalisé son impact. Nous avons examiné le processus de conversion de ces vérines en pixels et avons terminé avec un bref aperçu des alternatives au processus de tramage traditionnel.

Comme dans l'article précédent, il était peu probable que nous soyons en mesure de révéler tous les sujets, et nous avons manqué quelques détails - au final, ce n'est pas un manuel! Mais nous espérons que vous avez appris quelque chose de nouveau et respectez maintenant le travail des programmeurs et des ingénieurs qui ont utilisé l'informatique et la science pour implémenter tout cela dans vos jeux 3D préférés.

Source: https://habr.com/ru/post/fr480338/


All Articles