Un renderer de displacement voxel : moderniser l’esthétique 3D rétro
(blog.danielschroeder.me)- Daniel Schroeder développe un renderer temps réel qui étend la sensation de surface pixelisée des jeux 3D des années 1990 avec de petits détails de surface en voxels ; les assets d’entrée utilisent des meshes triangulaires low-poly et des textures classiques
- Au lieu de convertir toute la scène en grille de voxels, il utilise une displacement map pour donner uniquement aux surfaces une apparence voxelisée, visant un style visuel adapté aux environnements statiques à la Doom, Quake ou Duke Nukem
- Le CPU convertit les meshes triangulaires et les informations limitées de displacement en données géométriques destinées au GPU, et prétraite les textures ; le rendu image par image est ensuite géré presque indépendamment par le GPU
- La démo affiche des frame times de 4 à 9 ms en 1440p sur une Radeon RX 5700 XT et dépasse les 60 FPS en 800p sur la Steam Deck OLED, avec de nombreuses sections verrouillées à 90 FPS
- Comme l’environnement peut toujours être traité sous forme de meshes triangulaires, les collisions, le contrôleur de personnage et le pathfinding peuvent reposer sur des bibliothèques physiques existantes et sur des traitements basés sur les meshes ; seuls certains systèmes doivent connaître la géométrie voxelisée en détail
Étendre l’esthétique 3D des années 1990 avec des surfaces voxelisées
- L’objectif est de conserver la géométrie environnementale simple et les limites de texture nettes des jeux 3D classiques des années 1990, tout en ajoutant aux surfaces des détails 3D en blocs
- Les jeux 3D du début au milieu des années 1990 comme Doom, Quake et Duke Nukem ont eu une forte influence, tant sur le plan technique que sur celui du gameplay, et aujourd’hui leurs limitations visuelles d’alors sont elles-mêmes perçues comme un charme rétro
- Le point de départ est la question : « et si on fabriquait les détails de surface en voxels plutôt qu’en pixels ? »
- Par exemple, un mur de pierres peut conserver de près une sensation pixelisée tout en gagnant en profondeur géométrique
- Le résultat est conçu pour se situer entre l’apparence des jeux des années 1990 et une représentation plus moderne
Les limites des approches voxel classiques
- Un voxel mesh classique est une grille tridimensionnelle qui indique pour chaque cellule cubique si elle est remplie ou vide
- Il peut utiliser de gros voxels texturés, comme dans Minecraft
- Ou de petits voxels unis, comme dans Teardown
- Pour créer un environnement basé sur des voxels, il faut soit placer toute la géométrie dans une grille partagée, soit disposer plusieurs voxel meshes indépendants dans le même espace
- Il existe des outils permettant de créer directement de la géométrie voxel, mais le processus de production est souvent long et limité à de petits meshes
- On peut fabriquer des briques de construction comme des murs ou des sols modulaires pour assembler de grandes structures, mais cela convient bien aux bâtiments alignés sur une grille et beaucoup moins aux terrains libres
- La génération procédurale est utile pour les environnements naturels et les assemblages de blocs, mais elle apporte ses propres difficultés et ne convient qu’à certains types de jeux
- Il est aussi possible de rasteriser des meshes triangulaires existants dans une grille de voxels, mais la géométrie obtenue se retrouve alors enfermée dans une seule grille de voxels, ce qui peut produire un résultat esthétique indésirable
- Les faces alignées sur les axes peuvent ressembler à des plaques de voxels plates, et les faces à 45 degrés à des escaliers
- Quand la représentation formelle de la scène devient voxelisée, la logique du jeu elle aussi — physique, contrôleur de personnage, pathfinding des PNJ — peut devoir fonctionner au niveau du voxel
- En contrepartie, comme dans Minecraft et Teardown, il devient facile d’ajouter ou de retirer de la géométrie à partir d’un voxel mesh
Les limites des approches classiques de displacement
- Le displacement mapping utilise, avec la texture, une displacement map qui définit de combien chaque pixel de texture doit être déplacé vers l’intérieur ou l’extérieur de la surface du mesh
- Les logiciels de modélisation 3D peuvent subdiviser un mesh puis déplacer les nouveaux sommets pour transformer le displacement en véritable géométrie
- Cette approche modifie aussi la silhouette de l’objet
- Le nombre de polygones du mesh résultant augmente fortement
- Les meshes d’entrée avec des arêtes dures ou des coins nécessitent des ajustements pour obtenir un bon résultat
- En graphisme temps réel, des effets de shading de surface comme le parallax occlusion mapping peuvent donner l’impression d’une géométrie détaillée sans modifier la forme réelle
- Le rendu peut être convaincant sur de grands sols et murs
- Mais au bord des objets, la géométrie reste plate et l’illusion se brise
- Le shell mapping constitue une approche intermédiaire qui permet de voir le displacement dans la silhouette d’un objet sans mesh fortement subdivisé
- Il est difficile à gérer dans les zones où la courbure du mesh d’entrée est élevée
- Et il n’est pas simple d’adapter à cette technique des meshes d’entrée comportant des arêtes dures ou des coins
Mise en œuvre : combiner voxels et displacement mapping
- Ce renderer crée des environnements de type jeu 3D classique à partir de meshes triangulaires low-poly, définit les détails de surface à l’échelle du voxel avec des displacement maps, puis les rend comme s’ils étaient réellement assemblés en voxels
- Comme il vise des environnements riches en arêtes nettes, par exemple aux coins des bâtiments, il doit produire un résultat de type voxel même dans des zones où le displacement mapping classique fonctionne mal
- L’implémentation actuelle est un projet autonome en C++ / Vulkan
- L’infrastructure assure trois tâches principales
- Elle prend des meshes triangulaires et des informations limitées de displacement map, puis les convertit en données géométriques que le GPU utilisera pour dessiner le mesh déformé
- Cette étape s’exécute sur le CPU avant le rendu des frames
- Dans un jeu commercial, le résultat pourrait être baked sur disque
- Dans la démo vidéo, la conversion de tout l’environnement prend 0,5 seconde sur un seul thread
- Elle prétraite les textures pour générer les informations nécessaires au rendu, comme les normal maps
- Le travail lui-même est simple, mais lent, donc un bake est approprié
- Elle utilise l’état des meshes et textures générés pour dessiner sur le GPU la géométrie en displacement voxel
- L’implication du CPU par frame est presque nulle
- Elle prend des meshes triangulaires et des informations limitées de displacement map, puis les convertit en données géométriques que le GPU utilisera pour dessiner le mesh déformé
- Les performances sont déjà à un niveau exploitable en pratique
- Sur Radeon RX 5700 XT, la séquence de démonstration se rend en 4 à 9 ms par frame en 1440p
- Cela correspond à 250 à 110 FPS
- En 800p natif sur Steam Deck OLED, le rendu reste au-dessus de 60 FPS, avec de nombreuses sections verrouillées à 90 FPS
Production des assets artistiques
- La création de contenu nécessite deux types d’assets : des textures et des meshes
- Chaque texture se compose d’une albedo map et d’une displacement map
- Imiter la palette limitée des jeux rétro dans l’albedo aide à rendre le style visuel convaincant
- La displacement map fournit des valeurs de hauteur fines, dont l’intensité peut être ajustée dans le renderer via un changement d’échelle
- Après mise à l’échelle, l’unité de hauteur correspond au nombre de voxels de déplacement vers l’intérieur ou l’extérieur de la surface
- Le renderer ne déplace la surface qu’au voxel entier le plus proche, mais utilise les valeurs de hauteur exactes pour calculer les normal maps
- Des détails plus petits qu’un voxel peuvent donc quand même influencer l’éclairage
- Les meshes sont des meshes triangulaires low-poly texturés classiques avec des normales de shading
- Les normales indiquent quelles zones correspondent à des surfaces courbes lisses et quelles arêtes doivent rester nettes
- Le renderer effectue un travail supplémentaire pour produire de bons résultats sur les arêtes dures
- Pour le style visuel, il est préférable de conserver une taille de voxel cohérente dans le texturing, mais ce n’est pas une condition indispensable
- Il existe des contraintes sur la structure des meshes et leur mapping de texture
- Certaines pourront être levées à l’avenir
- D’autres sont inévitables en raison du fonctionnement du renderer
- Comme les assets sont des meshes triangulaires et non une représentation voxel dédiée, ils peuvent être créés avec divers outils
- L’environnement de la démo a été modélisé dans Blender
- Le format actuel d’export depuis Blender vers la démo est le fichier OBJ
Avantages et champ d’application pour le développement de jeux
- Cette approche permet de créer du contenu avec des workflows familiers plutôt qu’avec des outils d’édition voxel spécialisés
- Produire de bonnes textures peut être difficile, mais une fois créées, elles sont faciles à réutiliser sur plusieurs géométries
- Une grande partie de la géométrie de la démo vidéo utilise une seule texture de bloc de pierre en trois couleurs
- Comme l’environnement est créé sous forme de meshes triangulaires et que les caractéristiques voxelisées ne sont qu’un habillage de surface, on peut traiter l’environnement comme de la géométrie polygonale chaque fois que c’est plus pratique
- L’application de démonstration prend en charge les déplacements en vue à la première personne, les collisions, la montée d’escaliers et les collisions contre les murs
- Elle n’écrit ni moteur physique ni contrôleur de personnage maison
- Elle intègre l’open source Jolt Physics
- Elle utilise les meshes triangulaires d’origine comme géométrie de collision
- Le déplacement des ennemis et le pathfinding peuvent eux aussi être résolus à partir de ces mêmes meshes
- Seuls certains systèmes de gameplay doivent être conscients des voxels
- Par exemple, dans un FPS, on peut implémenter une fonction de raycast compatible displacement pour que les balles suivent la forme exacte de la géométrie déplacée
- De nombreux jeux basés sur les voxels utilisent leur propre moteur parce qu’ils doivent personnaliser plusieurs systèmes de jeu, alors qu’avec cette approche, l’essentiel de la logique hors rendu n’a pas besoin de connaître les détails à l’échelle du voxel
- La voie la plus réaliste semble être l’intégration de cette technique de rendu dans un moteur existant
Défis restants et prochaines étapes
- L’implémentation actuelle convient bien à la création de géométrie de niveau, mais un environnement de jeu a aussi besoin de petits objets, de décorations et d’éléments dynamiques comme des ennemis
- À l’avenir, il prévoit d’ajouter des moyens d’intégrer de petits objets ou des objets animés à ce style artistique
- L’éclairage de la démo est déjà convaincant, mais l’implémentation actuelle présente des limites
- Elle ne prend en charge qu’un petit nombre de lumières
- Il n’y a ni ombres, ni ambient occlusion, ni fonctionnalités plus avancées
- Ce renderer vise surtout les environnements majoritairement statiques que l’on trouve dans la plupart des jeux, plutôt qu’une géométrie très dynamique comme dans les jeux voxel classiques
- Selon les besoins de l’application, il reste de la marge pour différentes approches d’éclairage, y compris des méthodes baked
- Il n’y a actuellement pas d’anti-aliasing, ce qui se remarque surtout sur les sols lointains
- La suite du projet ainsi que la discussion destinée aux développeurs et aux studios se poursuivent dans un deuxième article
1 commentaires
Commentaires sur Hacker News
Je suis sans doute assez âgé pour me souvenir de l’époque où on téléchargeait des jeux avec des modems 2400 bauds, et je trouve cette esthétique vraiment séduisante
La vidéo était excellente et, personnellement, elle évoquait une ambiance très forte
Dans les passages où le plafond est très bas, j’ai même ressenti une forme de claustrophobie et d’oppression, tandis que les grottes au sol rocheux et sablonneux, ainsi que les grottes avec des rochers, étaient vraiment magnifiques, au point de me donner envie d’un jeu d’aventure à la Myst ou LucasArts réalisé avec ce moteur de rendu
Cela semblerait bien convenir à des thèmes comme l’exploration de grottes ou les fouilles archéologiques
Pour étendre en 3D un moteur de sable qui tombe, on pourrait peut-être aussi utiliser quelque chose comme la dynamique des fluides particulaires lissée
Dans les sections à plafond bas, on avait l’impression que les blocs suspendus au toit défiaient les lois de la physique
https://web.archive.org/web/20240524065427/https://blog.dani...
https://www.youtube.com/watch?v=1xFEbXWstCM
Il existe une autre approche avec Deep Bump. Elle traite le même problème d’une manière totalement différente
Deep Bump est un outil de machine learning qui génère des normal maps plausibles à partir d’images de texture
Il fonctionne particulièrement bien avec les textures de pierre ou de brique qu’utilise ce moteur de rendu à déplacement voxel, et avec les textures de tissu, il reconnaît dans une certaine mesure les plis, les poches et les cols pour produire des normales qui suggèrent de la profondeur
C’est passable pour l’écorce d’arbre et mauvais pour les plantes, probablement à cause du jeu de données d’entraînement
Si l’on voulait moderniser des jeux de la lignée de Doom/Wolfenstein, il existe déjà un outil open source utilisable
[1] https://github.com/HugoTini/DeepBump
Cet article se rapproche davantage d’une approche où les displacement maps sont traitées comme une petite représentation à base de voxels, et un outil comme Deep Bump pourrait éventuellement servir d’appoint pour créer les assets de texture d’un système comme celui décrit ici
Elles ne modifient pas réellement la géométrie, elles changent seulement l’illusion d’éclairage et de relief, donc vues sur les bords du mesh, les displacement maps restent un choix de meilleure qualité
Cela dit, DeepBump pourrait peut-être servir à extraire une height map unidimensionnelle pour un displacement traditionnel, c’est-à-dire une carte qui ne contient qu’une hauteur au lieu d’un déplacement vectoriel 3D complet
C’est impressionnant, mais je me demande à quel point cette approche conviendrait à des modèles 3D animés
Au mieux, j’imagine que ça ressemblerait à quelque chose comme le mode « Voxel Doom » de Doom
[1] https://media.moddb.com/cache/images/mods/1/55/54112/thumb_6...
[2] https://media.moddb.com/cache/images/mods/1/55/54112/thumb_6...
« Maintenant que tout ce contexte est posé, je voudrais rendre hommage au mod Voxel Doom pour le Doom classique. Le créateur du mod a remplacé les monstres et d’autres sprites du jeu par des meshes voxel, ajoutant ainsi de la profondeur, et c’était un travail vraiment impressionnant. Puis, fin 2022, il a commencé à expérimenter le parallax mapping pour ajouter des détails voxel à la géométrie des niveaux. À mon avis, cette partie n’avait pas très bonne allure, non pas à cause du travail artistique du créateur, mais à cause des limites fondamentales du rendu par parallax mapping. Ce mod n’a pas été l’inspiration de mon projet. J’étais déjà dessus. Mais voir ce mod être bien accueilli en ligne m’a donné un énorme élan pour continuer mon travail. ↩ »
Puisque l’approche elle-même semble aussi prendre en charge des éléments comme des portes animées, on pourrait peut-être l’utiliser pour des monstres ayant l’apparence du Doom original, en combinant meshes et flipbooks de textures
Cela dit, les zones de courbure marquée semblent être là où les artefacts du shell mapping seraient les plus visibles, et comme les limites de la mise en mesh des niveaux sont également mentionnées, ce n’est peut-être pas le cas
Cela ressemble beaucoup à ce sur quoi travaille Notch. Si l’on regarde son fil Twitter, il semble faire un autre type de rendu voxel
Mais celui-ci utilise C++/Vulkan et a vraiment beaucoup d’allure
Je me demande comment cette approche se compare à Nanite d’Unreal Engine 5. Peut-être qu’Unreal Engine fait déjà quelque chose de semblable
Si je me souviens bien, l’une des raisons d’utiliser des voxels dans d’anciens jeux, par exemple Comanche[1], était d’obtenir des terrains plausibles et complexes qui auraient coûté plus cher à modéliser en meshes triangulaires sur un matériel comparable
L’auteur mentionne 110 FPS sur une RX 5700 XT, mais je ne vois pas très bien ce que cela vaut par rapport à d’autres approches
[1] https://en.wikipedia.org/wiki/Comanche_(video_game_series)
Nanite part du principe qu’on crée des objets à très forte densité polygonale, puis streame des chunks simplifiés pour éviter que les triangles rendus ne deviennent plus petits qu’un pixel
Comme cela permet de produire naturellement une géométrie très détaillée, les displacement maps deviennent quelque peu redondantes, et il n’y a pas vraiment de raison de les traiter via des textures
Bien sûr, le terrain constitue un cas à part, mais c’est un cas spécial
L’approche décrite ici semble utiliser le displacement et des meshes low-poly pour générer au chargement une géométrie dense mais « voxelisée »
Si je me souviens bien, Comanche utilisait une approche de type ray tracing pour le rendu du terrain[1]
Ce n’étaient pas de vrais voxels, mais une height map 2D échantillonnée
Comme ils appelaient ça « VoxelSpace », la confusion est compréhensible
[1] https://github.com/s-macke/VoxelSpace
Contrairement à une idée répandue, ces jeux n’utilisaient pas de vrais voxels 3D, mais rendaient par ray marching une height map stockant les valeurs de couleur et de hauteur de la texture du terrain
En faisant du ray marching vers la texture dans le shader, on peut reproduire le même rendu, et cela semble très proche du résultat obtenu dans l’article de blog
À l’inverse, Nanite est une technologie de rendu pilotée par le GPU qui ajuste la densité de triangles selon la qualité visée
Nanite peut aussi utiliser des displacement maps et la tessellation, mais via un chemin séparé qui n’est pas forcément plus efficace que de simplement importer et rendre directement des assets très polygonés
C’est toujours agréable de voir une nouvelle approche dans le domaine des voxels
Cela dit, c’est un peu dommage que l’article mélange voxels et technique de rendu spécifique
Un voxel, c’est simplement l’usage d’une grille 3D, et à en juger par le milieu du texte, l’auteur semble assimiler l’usage des voxels à un rendu cubique, ce qu’on appelle souvent un renderer de blocksels à la Minecraft
Il dit aussi qu’on peut prendre une géométrie en triangles et l’utiliser directement dans le moteur, mais semble oublier que c’est tout aussi faisable avec des blocksels, ou en fait avec presque n’importe quel pipeline de rendu
C’est d’ailleurs exactement ainsi que des plugins de rendu voxel plus classiques, avec d’autres styles visuels, bénéficient d’une prise en charge de premier ordre dans les moteurs existants
J’aimerais que ce soit open source. Vraiment, vraiment
J’adore vraiment. Ça me rappelle Ultima Underworld
Voilà ce qui devrait être l’avenir de la modernisation des jeux 3D rétro. C’est vraiment magnifique