Préface
Après la sortie du dernier jeu de la série Metro, j'ai passé plusieurs heures à étudier son travail interne et j'ai décidé de partager quelque chose qui pourrait sembler intéressant d'un point de vue technologique. Je ne procéderai pas à une analyse détaillée ni à l'étude du code démonté des shaders, mais je montrerai les décisions de haut niveau prises par les développeurs en cours de création du jeu.
Pour le moment, les développeurs n'ont pas encore parlé des techniques de rendu utilisées dans le jeu. La seule source officielle d'informations est le
rapport GDC , que l'on ne trouve nulle part ailleurs sur Internet. Et c'est ennuyeux, car le jeu fonctionne sur un moteur propriétaire très intéressant qui a évolué par rapport aux jeux précédents de la série Metro. C'est l'un des premiers jeux à utiliser
DXR .
Remarque: cet article n'est pas une description complète et j'y reviendrai si je trouve quelque chose qui mérite d'être ajouté. Peut-être que j'ai raté quelque chose, car certains aspects n'apparaissent que dans les prochaines étapes du jeu, ou je viens de regarder les détails.
Premiers pas
Il m'a fallu plusieurs jours pour trouver un environnement capable de travailler avec ce jeu. Après avoir testé plusieurs versions de RenderDoc et PIX, j'ai décidé d'étudier les résultats du lancer de rayons à l'aide de Nvidia NSight. Je voulais apprendre le rendu sans lancer de rayons, mais NSight m'a également permis d'explorer les détails de cette fonctionnalité, j'ai donc décidé de la laisser activée. Pour le reste du rendu, PIX est un bon ajustement. Des captures d'écran ont été prises à l'aide des deux applications.
NSight a un inconvénient - il ne prend pas en charge l'enregistrement de la capture dans un fichier, donc je ne pouvais pas revenir aux images que j'étudiais.
Au tout début de mon travail, j'ai également rencontré un autre problème qui n'avait rien à voir avec les applications de débogage d'images: les fonctions de lancer de rayons nécessitaient l'installation de la dernière mise à jour de Windows, mais le jeu leur permettait d'être incluses dans les options sans installer la mise à jour. Dans ce cas, l'inclusion de fonctions a provoqué un plantage du jeu au démarrage. L'expérience GeForce n'a également rien dit sur la nécessité de la bonne version de Windows pour activer ces fonctionnalités. Ce problème doit être résolu des deux côtés.
Par souci d'exhaustivité, j'ai fait des captures à partir d'un jeu fonctionnant avec le maximum de paramètres possibles, mais sans DLSS.
Analyse de trame
Cadre finiUne brève analyse du rendu montre un ensemble de fonctions assez standard, à l'exception de l'illumination globale effectuée par lancer de rayons (GI raytracé).
Avant de rendre l'image, l'échelle de l'image précédente est réduite dans la file d'attente de calcul et la luminosité moyenne est calculée.
La file d'attente graphique commence par le rendu des particules de distorsion (gouttelettes sur la caméra), qui sont appliquées au stade du post-traitement. Ensuite, un rapide passage préliminaire des profondeurs crée une partie des profondeurs avant le Gbuffer; on dirait que ça ne fait que soulager.
La passe GBuffer remplit 4 cibles de rendu selon le diagramme ci-dessous et termine également le remplissage du tampon de profondeur.
1. Cible au format RGBA8 avec albédo et, éventuellement, occlusion ambiante dans le canal alpha; Sur certaines surfaces, il semble très sombre.2. Cible au format RGB10A2 avec des normales et, éventuellement, un masque de diffusion souterrain dans le canal alpha.3. Cible au format RGBA8 avec d'autres paramètres de matériau, probablement la métallité et la rugosité du canal alpha. Curieusement, les canaux RVB dans ce cas contiennent exactement les mêmes données.4. Cible au format RG16F avec des vecteurs de mouvement 2D.Une fois les profondeurs complètement remplies, un tampon de profondeur linéaire est construit et son échelle diminue. Tout cela se fait dans la file d'attente de calcul. Dans la même file d'attente, le tampon est rempli de quelque chose de similaire à l'éclairage directionnel sans utiliser d'ombres.
Dans la file d'attente graphique, le GPU trace les rayons de l'illumination globale, mais j'en parlerai plus en détail ci-dessous.
La file d'attente de calcul calcule l'occlusion ambiante, les réflexions et quelque chose de similaire à la reconnaissance des contours.
Dans la file d'attente graphique, une carte d'ombre à quatre étapes est rendue dans une carte de profondeur 32 bits de taille 6k * 6k. Plus d'informations ci-dessous. Après avoir terminé la carte des ombres dirigées, la résolution de la troisième cascade pour des raisons inconnues diminue à 768 * 768.
Au milieu du processus de rendu des ombres, il y a un moment curieux: l'atlas des imposteurs est complété par certains objets avant de restituer les ombres locales à partir de l'éclairage (à propos des imposteurs qui peuvent être trouvés
ici ). Les tampons d'imposteur et les tampons d'ombre d'éclairage locaux sont également des textures 6k * 6k.
Une fois toutes les ombres terminées, le calcul de l'éclairage commence. Cette partie du rendu est plutôt incompréhensible, car il existe de nombreux rendus qui effectuent des actions mystérieuses et nécessitent donc une étude supplémentaire.
Le rendu de la scène se termine avec des objets éclairés de face (yeux, particules). Les effets visuels sont rendus dans un tampon à demi-résolution, après quoi ils sont composés avec des objets opaques à l'aide du zoom.
L'image finale est obtenue par la correction tonale et le calcul de la floraison (diminuez puis augmentez la résolution de l'image avec la correction tonale). Enfin, l'interface utilisateur est rendue dans un tampon séparé et, avec le compositing de floraison, est superposée au-dessus de la scène.
Je n'ai pas trouvé la partie dans laquelle le lissage est effectué, je vais donc le laisser pour plus tard.
Traçage global des rayons lumineux
Quelques informations sur l'éclairage global réalisé par GI raytraced. Cette structure accélératrice couvre une grande partie du monde du jeu, probablement plusieurs centaines de mètres, tout en maintenant des détails très élevés partout. Il semble être diffusé en quelque sorte. La scène de la structure accélérée ne coïncide pas avec la scène tramée, par exemple, les bâtiments de l'image ci-dessous ne sont pas visibles sous la forme tramée.
Vue de dessusIci, nous pouvons voir quatre tuiles entourant la position du joueur. Le manque de géométrie testé sur le canal alpha est également apparent. Les arbres ont des troncs, mais pas de feuillage, pas d'herbe, pas de buissons.
Fermer la vueEn vue rapprochée, les détails et la densité des objets sont mieux visibles. Chaque objet d'une couleur différente a sa propre structure accélératrice du niveau inférieur. Seulement sur cette photo, il y en a plusieurs centaines.
Objets du joueur sous le piedFait intéressant, les objets du joueur font également partie de la structure d'accélération, mais pour une raison quelconque, ils sont situés sous ses pieds.
Peau cassée?Peau cassée à nouveau?Certains des objets avec écorché semblent cassés dans la structure accélérée. L’un des problèmes observés est l’étirement de la maille (sur les jambes de l’enfant). Un autre problème conduit au fait que différentes parties du personnage avec skinning sont dans des positions différentes. Il n'y a pas d'étirement, mais les pièces sont séparées les unes des autres. Il semble que rien de tout cela ne soit visible dans l'éclairage global de lancer de rayons, ou du moins je n'ai pas pu le remarquer dans le jeu.
Un grand nombre d'objetsSur un plan plus général, vous pouvez voir le nombre d'objets différents dans la structure accélératrice. La plupart d'entre eux ne contribueront pas réellement aux résultats des calculs de l'illumination globale. On voit également ici qu'il n'y a pas de schéma LOD. Tous les objets sont ajoutés avec tous les détails. Il serait intéressant de savoir si cela a un effet sur le lancer de rayons (je suppose que oui).
LOD ultra-élevé, chaque échelle et commutateur entièrement modélisésUne autre capture d'écran montre un énorme détail d'objets, même loin du lecteur. Chaque interrupteur et chaque échelle de cette image sont clairement lisibles même sans textures. L'endroit où j'ai déplacé l'appareil photo pour prendre cette capture d'écran est situé à des dizaines de mètres du lecteur et l'élimination de ces détails n'aurait pas détérioré la qualité de l'image. La mise à jour de la structure d'accélération à l'aide de LOD serait peut-être trop coûteuse, mais il existe une forte probabilité que cette mise à jour puisse être effectuée de manière asynchrone. Ce point mérite certainement d'être exploré plus en détail.
Rendu des ombres directionnelles
La partie principale du rendu des ombres est simple et ne nécessite pas de mention spéciale, mais il y a des points intéressants ici.
Mailles pour lesquelles la projection d'ombres est peu probableD'énormes détails dans les cartes fantômesMaillages qui semblent utiliser le mauvais tampon d'indexIl semble que, comme l'accélération des structures, le rendu des ombres comprend absolument tout. Il y a des objets qui ne contribuent presque pas à la texture de l'ombre, mais ils sont toujours rendus. Je me demande si cela se produit à cause d'une autorisation, ou n'y a-t-il aucun moyen facile dans le moteur de les exclure?
Il y a des objets qui sont difficiles à remarquer même avec des ombres dans l'espace d'écran. Leur rendu ne prend pas beaucoup de temps, mais il serait intéressant de voir s’ils peuvent être supprimés pour gagner un peu de temps.
Lors de l'examen du maillage, il semble que certains des maillages rendus dans la carte d'ombre ont des tampons d'index cassés, mais après le vertex shader, ils semblent corrects (les résultats sont les mêmes dans PIX et NSight). C'est le meilleur exemple que j'ai réussi à trouver, mais il est loin d'être le seul. Peut-être que c'est une sorte de position d'emballage spéciale?
Les mailles semblent avoir une peau écorchéeLe dépouillement semble poser des problèmes non seulement dans l'accélération des structures. Fait intéressant, cela ne conduit pas à des artefacts visibles à l'écran.
2e partie
Amendement mineur
Dans la partie précédente, j'ai écrit que la troisième cible de rendu du tampon GBuffer contient probablement de la métallité, mais il semble qu'elle contient en fait une couleur spéculaire. Au début, je n'ai vu aucune couleur et je n'ai pas compris pourquoi les trois canaux RVB contiennent les mêmes données, mais c'était probablement parce qu'il n'y avait pas de reflets de couleur dans la scène. Pour cette arme, le tampon contient beaucoup plus de couleurs différentes.
J'ai également oublié d'ajouter ma texture préférée, que j'ai trouvée en recherchant le rendu du jeu. Cela vaut vraiment la peine d'être mentionné car il démontre la nature chaotique du développement de jeux quand il n'est pas toujours possible de le nettoyer.
"Améliorez-moi!"Composite de transparence et lissage
En essayant de comprendre comment la résolution du tampon de transparence demi-taille augmente et comment le jeu effectue l'anticrénelage, j'ai remarqué quelque chose d'intéressant. J'avais besoin d'une scène où il y avait beaucoup plus de contraste pour que ce qui se passait soit clairement visible. Heureusement, j'ai réussi à capturer une image dans laquelle l'arme du joueur se déplace légèrement entre les images.
Avant de rendre la transparenceIl semble qu'avant de composer le tampon de transparence, le tampon contient déjà une image entièrement rendue, et puisqu'il n'y a pas de bords nets dans ce cadre, il est logique de supposer que ce sont les données du cadre précédent.
Après composition de la transparence de l'image actuelleLors de l'ajout de transparence à l'image actuelle, nous pouvons remarquer des bords cassés individuels. Cela s'est produit parce que l'arme s'est légèrement déplacée vers la droite. Certains nuages sont rendus transparents, mais ils sont coupés à l'horizon (qui est opaque), donc la composition ne change pas le fond, mais rend déjà le maillage de l'arme de l'image précédente en utilisant le tampon de profondeur de l'image actuelle.
Après avoir ajouté l'opacité à l'image actuelleAprès plusieurs appels de dessin, la composition et les maillages opaques sont effectués. Il ne semble pas y avoir de raison particulière de procéder ainsi dans cet ordre. Il est logique de composer le tampon de transparence dans les données des objets opaques de la trame courante, mais cela ne se produit pas, et il serait intéressant de savoir pourquoi.
Après TAAAprès avoir terminé le cadre complet, le passage TAA (lissage temporel) lisse les bords. J'étais déjà intéressé par cela auparavant, car je ne voyais pas où se déroulait le lissage. Mais j'ai sauté cela parce qu'immédiatement après cet appel de tirage, le sous-échantillonnage pour la passe de floraison commence et je manque cet appel de tirage.
Éblouissement de l'objectif
Habituellement, je ne veux pas analyser les effets individuels, mais il existe de nombreuses façons d'implémenter la lumière parasite, donc j'étais curieux de savoir quels développeurs avaient choisi.
Éblouissement des lentilles en compositing prêt à l'emploiDans la plupart des cas, la lumière parasite est à peine perceptible, mais c'est un bel effet. Il est difficile de montrer dans la capture d'écran, donc je n'y mettrai pas beaucoup d'efforts.
Éblouissement de la lentille dans le tampon de floraisonAprès la recherche, j'ai trouvé un appel de tirage qui ajoute cet effet, et il s'est avéré que c'était un appel après la dernière étape de l'augmentation de la résolution de floraison. Dans ce tampon, l'effet est beaucoup plus visible.
Flare géométriqueSi vous regardez la géométrie, la lumière parasite est assez simple. Au moins 6 quadrangles sont impliqués dans la création du résultat final à l'écran, mais aucune série de quadrangles plus petits ne se rapproche de la position du soleil. Nous pouvons conclure qu'il s'agit d'une solution assez standard, bien que certains développeurs rendent la lumière parasite directement dans la scène cible de rendu, tandis que d'autres calculent l'effet en tant que post-traitement.
Rendu du terrain
Dans tous les jeux en monde ouvert, l'une des difficultés les plus intéressantes est le rendu du terrain. J'ai décidé qu'il pourrait sembler intéressant d'étudier cet aspect, mais, franchement, un peu déçu.
À première vue, un fragment du relief donne l'impression qu'une sorte de pavage est en cours. La façon dont le relief est déformé pendant le mouvement rend logique de supposer qu'il y a un déplacement supplémentaire. De plus, sur PC, le jeu utilise activement la tessellation, il serait donc logique de l'utiliser en relief.
Peut-être que les mauvais paramètres ont été définis, mais le jeu rend tous les fragments du relief sans pavage. Pour chaque fragment du relief, elle utilise cette grille uniforme 32 * 32. Il n'y a pas non plus de LOD.
En regardant un fragment du relief après le vertex shader, vous pouvez voir que la plupart des paires de sommets ont fusionné pour former une grille 16 * 16 presque parfaite, à l'exception de certains endroits qui nécessitent plus de précision (probablement en raison de la courbure du relief). La déformation mentionnée ci-dessus résulte probablement de la lecture des textures de mip de la carte d'élévation du relief lorsque le relief est loin de la caméra.
Ray Tracking Tricks
Et maintenant ce que tout le monde attendait.
Streaming de données
L'un des aspects les plus intéressants de toute implémentation DXR pour le moment est la façon dont vous travaillez avec les données. La chose la plus importante est de savoir comment les données sont chargées dans les structures accélératrices et comment elles sont mises à jour. Pour tester cela, j'ai pris deux captures et comparé les structures accélératrices dans NSight.
Le joueur est à l'intérieur du navireLors de la première capture, je me tenais à l'intérieur d'un vaisseau cassé, visible au milieu de cette image. Seuls les objets les plus proches sont chargés, à l'exception des gros rochers au bord de la carte.
Le joueur s'est déplacé dans le coin supérieur gauche de cette image.Dans la deuxième capture, je me suis éloigné du bord de la carte et je me suis rapproché du bord supérieur gauche de l'image. Le navire et tout ce qui l'entoure est toujours chargé, mais de nouveaux objets ont également été chargés. Fait intéressant, je ne peux définir aucune structure de tuile. Les objets peuvent être chargés / retirés de la structure accélératrice en fonction de la distance et de la visibilité (peut-être en limitant le parallélogramme?). De plus, le bord supérieur droit semble plus détaillé, bien qu'il s'en soit éloigné. Il serait intéressant d'en savoir plus à ce sujet.
Le soulagement et ce qu'il y a sous
Plusieurs aspects de l'implémentation DXR dans Metro: Exodus concernant le terrain peuvent être mentionnés.
Tout d'abord, il est intéressant de noter que les structures accélératrices ne contiennent pas de maillage en relief (à l'exception de cas particuliers). Ces monstres courent réellement dans le jeu sur le terrain, mais à en juger par les données de NSight, vous pourriez penser qu'ils volent. Cela nous pose une question intéressante: la mise en œuvre de l'éclairage global peut-elle en quelque sorte prendre en compte le relief (éventuellement à l'aide d'une carte des hauteurs et de matériaux en relief) ou non.
Le moment suivant, je n'aurais jamais remarqué si le soulagement était en place. En regardant le début du niveau à la structure accélératrice dans NSight, j'ai remarqué quelques mailles sous le relief.
Les artistes placent assez souvent, pour diverses raisons, des maillages de débogage sous le niveau, mais ils sont généralement supprimés avant la sortie du jeu. Dans ce cas, ces mailles ont non seulement survécu jusqu'à la libération, mais sont également devenues une partie de la structure accélératrice.
En plus de celles mentionnées ci-dessus, j'ai trouvé d'autres mailles éparpillées sous le relief. Fondamentalement, ils ne valent pas beaucoup de mention, mais celui-ci était très intéressant - c'est un personnage se tenant juste en dessous du point de départ du niveau. Il a même sa propre piscine.
Enfin, le dernier élément curieux de la structure accélératrice est les mailles unilatérales regardant vers l'extérieur du niveau. À moins qu'ils ne soient considérés comme bilatéraux, il y a très peu de chances qu'ils contribuent à l'image du jeu. Même si les maillages sont bilatéraux, ils sont si loin de la zone jouable qu'ils étirent probablement la structure accélératrice. Il est intéressant de voir qu'ils ne sont pas filtrés. Cette image montre également l'un des cas particuliers de la "maille en relief" dans le coin inférieur droit, entre le train et le bâtiment.
Sans tête avec dépouillement
J'ai déjà parlé des problèmes de skinning des mailles, mais à ce niveau j'ai remarqué autre chose.
Tout d'abord, ce monstre montre les deux erreurs dans une image, que j'ai remarquées ci-dessus. Je me demande toujours ce qui les a causés.
J'ai également remarqué que ces petites créatures, comme les chauves-souris, n'ont pas de tête dans la structure accélératrice.
Un autre exemple. Remarquez le trou où la tête devrait être. Je n'ai pas vu un seul cas où la tête était visible.
Le même genre de créatures en mode rasterisation.
Notez que la tête est clairement visible.Et voici le filaire de la tête.En conclusion
C'est tout pour aujourd'hui. J'espère que vous avez apprécié ce regard sur l'intérieur de Metro: Exodus.Je continuerai d'explorer le rendu du jeu, mais je ne publierai pas de nouvelles parties de l'article à moins de trouver des parties spéciales qui seraient intéressantes pour les gens ou de trouver quelque chose qui mérite d'être partagé.