Accueil » Dossier » Doom III : Behind the scenes » Page 4

Doom III : Behind the scenes

1 : Introduction, historique 2 : Historique, suite 3 : Technologie : les Shadow Volumes 5 : Les code path 6 : Conclusion

Technologie : le Per Pixel Lighting

Un terme très à la mode ces derniers temps : les fabricants de hardware n’ont plus que ça à la bouche per pixel lighting mais qu’est ce que ça veut dire au juste ? Littéralement que les calculs d’éclairage sont effectués au pixel près, la belle affaire et qu’est ce que ça change précisément ? Très bien commençons par un petit rappel : dans le modèle d’éclairage de Gouraud implémenté sur toutes les cartes les calculs d’éclairage sont effectués au niveau des sommets des triangles puis interpolés. Dans le modèle de Phong, nettement plus complexe et offrant de bien meilleurs résultats, les vecteurs normaux sont calculés par sommets puis interpolés pour chaque fragment et c’est au niveau de chaque fragment que sont effectués les calculs d’éclairage. Le problème du modèle de Gouraud concerne sa très forte dépendance sur la définition du modèle géométrique sous-jacent, si celui ci n’offre pas une tesselation suffisante des artefacts visuels se produisent en particulier avec les reflets spéculaires. En effet de part la définition même de l’algorithme un point interne à un polygone ne peut être plus lumineux que le plus lumineux des sommets entrant dans le calcul. Mais le modèle de Phong a un gros inconvénient : il est très lent…

Dés lors combiner la vitesse du Gouraud en offrant d’un éclairage au pixel près est devenu le Graal dans le domaine de la 3D temps réel et c’est désormais possible en utilisant quelques astuces et les possibilités des puces 3D récentes. L’idée consiste à précalculer les normales d’une surface, puis à les encoder dans une texture : après tout une texture 2D n’est rien d’autres qu’une fonction qui à deux scalaires u et v fait correspondre un vecteur. Que celui ci soit une couleur ou une normale dépend de l’interprétation que l’on en fait, on peut donc considérer les composantes R,G,B de chaque pixel comme les coordonnées x,y, z de la normale. Cette technique a l’avantage de pouvoir utiliser le matériel d’application de textures afin de pouvoir réaliser une interpolation peu coûteuse de ces normales sur la surface. Nous disposons donc désormais d’une normale à chaque fragment il ne suffit donc plus que d’effectuer le calcul d’éclairage à chaque fragment (en pratique un simple produit scalaire entre la normale du fragment et l’inverse du vecteur lumière) ? Non pas exactement, comme nous l’avons vu précédemment encoder une normale dans un texture présente de multiples avantages mais pour pouvoir effectuer les calculs d’éclairage le vecteur lumière et le vecteur normal doivent être exprimés dans le même espace. En effet nous sommes passés rapidement sur l’encodage du vecteur normal dans la normal map : tout vecteur doit être exprimé dans un espace, les vecteurs normaux contenus dans la normal map sont donc exprimés dans un espace local à la texture. Cet espace est formé de deux vecteurs allant dans le sens de la largeur croissante et de la hauteur croissante de la texture (u et v) et du vecteur normal à la surface (w). Cet espace est appelé l’espace tangent.


Une fois que la normal map est appliquée à un objet ces vecteurs sont « collés » sur l’objet texturé mais à ce moment à chaque sommet les vecteurs u,v et w pointent dans des directions complètement différentes. Pour pouvoir effectuer des calculs au pixel près il faut donc transformer l’inverse du vecteur lumière dans cet espace tangent (qui je le répète est propre à chaque sommet !). La technique consiste donc à calculer pour chaque sommet l’espace tangent puis à y exprimer l’inverse du vecteur lumière (ceci peut être effectuée dans un vertex program pour décharger le CPU) puis à appliquer pour chaque fragment le calcul d’éclairage souhaité (en utilisant les Registers Combiners ou un fragment program).

A propos de la normal map, Doom III utilise une nouvelle technique de génération qui va sans aucun doute se démocratiser (déjà le moteur de Halo 2 sur Xbox, et le Crytek Engine présente des techniques similaires). Initialement les normal map étaient créées par les graphistes à l’aide d’outils spécifiques (généralement un plug-in Photoshop qui permettait de convertir l’image crée par le graphiste au format convenable). Doom III pour sa part exporte les normales directement depuis l’outil de modélisation. En clair les graphistes réalisent une version extrêmement détaillée du modèle (entre 800 000 et 1 millions de polygones) à partir de laquelle sera générée la normal map. Cette normal map appliquée sur un modèle simplifié permettra de faire illusion, exceptés sur les contours bien sûr qui par conséquents conservent leur aspect anguleux.
L’image suivante montre cette technique en action :


En haut le modèle utilise une normal map, en bas il se contente d’une normale par sommet. Si lorsque le nombre de triangles est extrêmement élevé la différence est invisible elle saute aux yeux dés que la tesselation diminue. Même lorsqu’on descend en dessous des mille triangles, le modèle utilisant la normal map continue de faire illusion. ATI offre sur son site un plug-in Maya permettant d’exporter les normales d’un modèle dans une normal map ce qui devrait accélérer l’adoption de cette technique.

Les fonctions matérielles nécessaires pour implémenter cet algorithme se limitent au Dot3 texture blending (apparu sur certains chips Dx6 comme le Permedia 3 démocratisé sur l’ensemble des chips Dx7). Et au Cube Mapping (apparu avec les chips Dx7)… Le Cube Mapping quel rapport ici ? Effectivement traditionnellement le Cube Mapping est utilisé pour simuler des réflexions d’un environnement ce qui n’a pas grande utilité ici vous en conviendrez. Mais encore une fois il faut regarder les choses de façon moins spécifique : une Cube Map est un ensemble de six textures centrées sur un repère. Contrairement à l’adressage classique de textures à base de coordonnées u et v une cube map est adressée grâce à un vecteur. Autrement dit de façon purement mathématique une cube map peut être vue comme une fonction mathématique qui prend un vecteur et retourne un vecteur (en l’occurrence un vecteur RGB mais là encore tout est question d’interprétation de la valeur retournée). L’idée consiste donc à se servir d’une cube map comme d’un moyen peu coûteux de renormaliser les vecteurs : la cube map constitue donc une sorte de table de précalcul contenant les valeurs normalisées des vecteurs.

Sommaire :

  1. Introduction, historique
  2. Historique, suite
  3. Technologie : les Shadow Volumes
  4. Technologie : le Per Pixel Lighting
  5. Les code path
  6. Conclusion