- La démo Nintendo 64 pour Revision 2025 produit des effets proches du normal mapping, de l’éclairage précalculé et du spéculaire en temps réel en mettant à jour uniquement la palette sans recalculer toute la texture
- Le CPU lit les normales et la couleur diffuse à chaque indice de palette pour créer une nouvelle palette RGB, ce qui fait réagir la texture indexée comme si chaque texel recevait un éclairage
- La texture diffuse et la normal map partagent les mêmes indices de palette, générés en les regroupant comme une image à 6 canaux via le K-means clustering de scikit-learn
- L’éclairage des bâtiments combine la couleur ambiante en RGB des sommets, la visibilité au soleil dans l’alpha des sommets, une irradiance map en niveaux de gris et la lumière solaire directionnelle via
dot(N, sun_dir)
- La technique est efficace pour la lumière diffuse directionnelle, mais ses limites sont importantes pour les ombres, les point lights, le spéculaire précis et les grands modèles avec textures répétées, au point de devoir les masquer par du prétraitement
Faire du shading en ne mettant à jour que la palette
- La démo Nintendo 64 a été réalisée pour Revision 2025 et utilise des effets proches de l’éclairage précalculé, du normal mapping et du shading spéculaire en temps réel
- Sur N64, la faisabilité du normal mapping était déjà connue grâce à des expérimentations homebrew, et cette démo a choisi de calculer à l’exécution non pas la texture mais la palette de résultat d’éclairage
- Sans support matériel dédié, il est possible d’exécuter un code de shading arbitraire sur le CPU, mais la vitesse de calcul reste faible
- Avec une texture indexée, il suffit de changer la palette plutôt que tous les texels pour donner l’impression que la texture entière a reçu un calcul d’éclairage
- la palette d’origine est remplacée par une palette ombrée
- la texture indexée est appliquée à l’objet comme une texture classique
- même une simple lumière diffuse
dot(N,L) donne un résultat visuellement convaincant
- L’exemple initial annulait la correction gamma de la texture de couleur pour faire le shading en espace linéaire, mais cela n’a pas pu être conservé dans la démo finale, car il fallait séparer les termes ambiant et direct puis les recomposer matériellement dans l’unité RDP de la N64
Normal mapping en espace objet
- Le normal mapping classique se fait en espace tangent
- il permet l’usage de textures répétées
- il peut corriger les détails normaux par rapport à des normales de sommet qui varient en douceur
- une normal map en espace tangent d’une seule couleur représente une surface lisse
- Les normales en espace objet simplifient les calculs mais imposent davantage de contraintes
- les texels de la normal map représentent les normales absolues de la surface, et non un écart par rapport aux normales de sommet
- le calcul à l’exécution devient aussi simple qu’une lecture de couleur dans une texture
- chaque point de la surface a besoin de son texel propre, comme avec une lightmap
Une palette partagée entre texture diffuse et normal map
- L’objet possède à la fois une texture diffuse
basecolor * ao et une normal map
- Les deux textures partagent les mêmes indices de palette, générés avec le K-means clustering de scikit-learn
- les images sont interprétées comme une seule image à 6 canaux
- un seul indice permet de récupérer à la fois la normale et la couleur diffuse de la surface
- Au chargement, ou à chaque frame, les couleurs de la palette sont parcourues
- le code de shading CPU produit une nouvelle couleur RGB pour chaque indice
- le résultat de la boucle devient une nouvelle palette éclairée
- En pratique, cette approche convient surtout à un éclairage directionnel
- Comme la palette seule exprime mal des effets comme les ombres, il faut la combiner à un éclairage précalculé
Ambiance directionnelle précalculée et lumière solaire
- Pour donner un éclairage plus réaliste aux bâtiments de la démo, les termes ambiant et solaire direct sont stockés séparément dans les couleurs de sommet
- RGB des sommets : couleur ambiante
- alpha des sommets : visibilité au soleil
- Le terme ambiant est séparé entre intensité directionnelle et couleur
- l’intensité directionnelle provient d’une irradiance map en niveaux de gris
- la couleur provient du RGB des sommets avec saturation renforcée
- Le soleil est une lumière directionnelle, dont la visibilité est transmise via l’alpha des sommets
- La formule de shading est la suivante
ambient = vertex_rgb * grey_irradiance_map(N)
direct = vertex_alpha * sun_color * dot(N, sun_dir)
color = diffuse_texture * (ambient + direct)
- Les couleurs de sommet sales utilisées pour la visibilité du soleil sont masquées par le calcul
N.L, ce qui nettoie leur contribution dans le résultat final de lumière directe
- Même avec un éclairage précalculé grossier, l’ambiance directionnelle peut sembler haut de gamme grâce au niveau de détail des textures
- Pour l’environment map floue, une projection équirectangulaire est utilisée pour sa simplicité
- les HDRI de Polyhaven utilisent déjà cette projection
- comme le shading a été précalculé au chargement, la complexité des mathématiques d’échantillonnage ne posait pas de problème
Gérer de grands modèles avec textures répétées
- L’algorithme de shading initial avait été conçu pour un seul objet et n’avait d’abord été testé qu’avec
potato_rock.obj
- Le maillage du château de la démo pose problème à cause de ses textures répétées
- Le contournement consiste à découper le grand maillage en plusieurs sous-maillages, chacun partageant conceptuellement la même normal map en espace objet
- la géométrie est regroupée manuellement dans Blender selon le matériau et l’orientation des surfaces
- une matrice world-to-model est calculée à partir des normales de polygones de chaque groupe
- cette matrice se rapproche d’un espace tangent approximatif
- Chaque groupe partage la palette, donc l’éclairage global n’est correct qu’au sens d’une moyenne
- Comme l’espace tangent n’est pas interpolé à l’exécution, le rendu ressemble à un éclairage par face, ce qui constitue l’un des principaux défauts de la technique
Approximation du shading spéculaire
- Comme plusieurs points de surface partagent la même couleur de shading, il est difficile de calculer précisément des point lights ou un shading spéculaire
- L’approche en espace de palette est bien adaptée à une lumière diffuse directionnelle qui ne nécessite pas de vecteur
to camera V
- L’effet spéculaire est approximé en assimilant l’objet à une sphère
- le point à éclairer
p est posé comme p = radius * normal
- comme de nombreux points de surface partagent le même indice de palette, le résultat ne peut qu’avoir un aspect anguleux
- Les reflets spéculaires de la démo paraissaient un peu étranges, mais fonctionnaient suffisamment bien pour tromper la plupart des gens
Limites et documents associés
- La démo cherche à dissimuler ses principales limites par le prétraitement et la composition de la scène
-
Discontinuités d’éclairage et plage d’expression
- seules les textures en niveaux de gris sont prises en charge
- il n’y a pas de point lights
- cette technique n’est vraiment pratique qu’avec un prétraitement sophistiqué
- la technique de Spooky Iluha n’a pas de problème de discontinuité d’éclairage, mais on ne sait pas si elle peut résoudre le même problème tout en conservant à la fois l’ambiant et la lumière directe
-
ROM et travaux antérieurs
1 commentaires
Avis de Hacker News
Voir des graphismes réalistes sur N64 est vraiment impressionnant, et cette démo me rappelle « ICO » sur PS2
Je me suis souvent demandé s’il serait possible de créer un SDK qui abstrairait le matériel graphique de la N64 pour fournir des primitives modernes, de l’éclairage, du shading, des outils pour précalculer l’éclairage comme dans cette démo, etc.
La N64 avait un matériel assez unique pour sa génération ; Copetti.org donne plus de détails : https://www.copetti.org/writings/consoles/nintendo-64/
Je serais même un peu surpris qu’il n’y ait pas eu de bibliothèque OpenGL
Il y a toutefois une grosse nuance : 1) il faut voir ce système comme une carte graphique avec un CPU attaché, et 2) le système graphique est exposé directement
L’architecture des puces graphiques tend vite à devenir un bazar sale et incompatible, donc les fabricants d’accélérateurs préfèrent généralement publier des API intermédiaires comme OpenGL, DirectX, CUDA ou Vulkan plutôt que de la documentation de référence
Cela leur permet de continuer à garder des implémentations internes incompatibles entre elles. Sans publier la documentation de référence, ils n’ont pas non plus besoin d’assurer une rétrocompatibilité matérielle ; l’avantage est de pouvoir créer de nouvelles conceptions, mais l’inconvénient est que personne ne peut vraiment les utiliser directement
Donc, quand on obtient un accès direct comme sur les consoles de cette génération, la réaction instinctive est de paniquer
À noter aussi qu’OpenGL vient de SGI, et que Nvidia a été fondée par d’anciens ingénieurs de SGI
J’aime bien qu’un article sur les astuces graphiques de la N64 se termine par la question « Is this the future? »
Une bonne douzaine de titres populaires ont été décompilés en fichiers source lisibles [1], ce qui facilite les portages PC sans émulateur et permet une foule de mods tournant sur le matériel d’origine
Il existe aussi plusieurs remakes de fans autour de Zelda [2], ainsi que des jeux complets avec de nouveaux donjons et une nouvelle histoire
Côté Mario 64, c’est particulièrement bouillonnant : Kaze a optimisé le jeu en profondeur [3], et travaille aussi sur son propre moteur et une suite. Si vous aimez les analyses techniques rétro en profondeur, sa chaîne est une vraie mine d’or
On voit même apparaître des démos improbables comme Portal [4], qui a malheureusement attiré l’attention du service juridique de Valve
Des jeux perdus comme Dinosaur Planet de Rare, après avoir fuité, sont aussi peaufinés jusqu’à devenir presque publiables, décompilés, et connaissent leur propre renaissance indie [5]
[1] https://wiki.deco.mp/index.php/N64
[2] https://m.youtube.com/watch?v=bZl8xKDUryI
[3] https://m.youtube.com/channel/UCuvSqzfO_LV_QzHdmEj84SQ
Toute la chaîne est excellente, avec des dizaines d’analyses comme celle-ci : https://m.youtube.com/watch?v=DdXLpoNLywg
Son jeu et son moteur sont eux aussi magnifiques : https://youtu.be/Drame-4ufso
[4] https://m.youtube.com/watch?v=yXzoZ2AfWwg
[5] https://m.youtube.com/watch?v=s0QSiPRmWaI
Je suis toujours impressionné de voir à quel point ces ingénieurs de jeux étaient géniaux
Ils ont trouvé des solutions excellentes et pleines d’imagination sous des contraintes énormes
C’est le secret de pico8, d’Animal Well et d’innombrables jeux étonnants
J’aurais préféré ne pas avoir eu, ce week-end, l’idée d’une bien meilleure structure pour mon moteur de création de jeux 2D en pixel art. Voilà encore un mois de plus avant la sortie :(
C’est vraiment agréable d’avoir aujourd’hui des systèmes plus rapides, mais il y avait quelque chose de plaisant dans le fait de contourner les contraintes des anciens jeux, et une immense satisfaction quand on y parvenait
Les lecteurs de HN connaissent sans doute les interruptions raster (https://en.wikipedia.org/wiki/Raster_interrupt) et le beam racing. Personnellement, je les ai toujours associés à l’Atari 800
À l’origine, on n’aurait pas dû pouvoir faire des choses comme https://youtu.be/GuHqw_3A-vo?t=33, mais les Display List Interrupts les ont rendues possibles
Ce que j’ignorais jusqu’à récemment, c’est à quel point les jeux Atari 2600 reposaient sur ce genre de folie : https://www.youtube.com/watch?v=sJFnWZH5FXc
Quand on voit ça, on se dit que même si les progrès matériels s’arrêtaient, on pourrait continuer pendant des décennies à découvrir des choses toujours plus intéressantes
La demoscene et ce genre de travaux sont impressionnants, mais ils semblent généralement tendre vers des scènes plus simples et plus vides
Elles se rapprochent plutôt de quelque chose qui pourrait servir de décor de jeu ou faire partie d’une mécanique de jeu. Avec la plupart de ces techniques, on a l’impression qu’il n’y a pas assez de ressources pour créer une expérience complète
Ce qui m’impressionne davantage, ce sont les travaux qui parviennent à tirer de bien meilleures performances d’un vieux matériel, comme FastDoom ou divers projets d’optimisation de Mario 64
Parfois même en ajoutant du contenu et des fonctionnalités. Je me demande aussi s’il existe des passerelles entre les développeurs de la demoscene et ce type de travaux plus globaux
Les jeux shareware des années 90 utilisaient une technique similaire d’éclairage basé sur la palette
En gros, quand on constituait une palette VGA 256 couleurs, on y plaçait, pour chaque couleur prise en charge, un dégradé de N niveaux de luminosité de cette couleur
Il suffisait alors d’ajouter ou de soustraire l’index de couleur pour modifier facilement la luminosité de chaque couleur
Les optimisations de l’époque PS1 et PS2 me manquent
La plupart de ces jeux sont vraiment superbes quand on les pousse en 1080p, 4K ou plus via l’émulation. Personnellement, des graphismes de l’époque de Halo 2 en 4K me suffisent largement
Bien sûr, Halo 2 est un jeu Xbox, mais si on joue à Halo 2 dans Halo MCC avec les graphismes classiques, il reste encore étonnamment beau
L’effet de mirage de chaleur de GT3 résume bien la chose
« Dans la démo de GT3, ils montraient le circuit de Seattle au coucher du soleil, avec la chaleur qui montait du sol et faisait onduler l’image. Sur PS3, on ne peut pas reproduire cet effet de mirage thermique. C’est parce que le read-modify-write n’est pas aussi rapide qu’à l’époque où l’on utilisait la PS2. Il y a ce genre de choses. »
https://old.reddit.com/r/ps2/comments/1cktw88/gran_turismos_...
https://youtu.be/ybi9SdroCTA?t=4103
Ce n’était pas une tentative d’émuler de vraies vagues de chaleur comme le feraient de nouveaux moteurs du genre UE5, mais un truc pour éviter de massacrer le framerate. Franchement, quand on voit à quel point RTX plombe les performances, je préfère ce genre d’astuces peu coûteuses
Un MIPS à 299 MHz faisait tourner ça
Shadow of the Colossus : https://www.youtube.com/watch?v=xMKtYM8AzC8
GoW2 : https://youtu.be/IpKLwIIdvuk?si=TjifKmlYsUuvhk0F&t=970
FFXII : https://youtu.be/NytHoYOs_4M?si=jE1Fxy40khEvV6Bn&t=51
GT4 : https://www.youtube.com/watch?v=F6lZIxk_h9g (l’écran de démarrage m’a ému)
Black, Renderware était un moteur complètement dingue : https://youtu.be/bZBjcwyq7fQ?si=Pev5ifpksJm4X6Oi&t=356
Valkyrie Profile 2 : https://youtu.be/9ScjO4NuUtA?si=Z29cR-hLsT2pnP2I&t=38
Rouge Galaxy : https://youtu.be/iR1evzyl-7Q?si=fldm3-NnuFxOITMn&t=624
Burnout 3 : https://www.youtube.com/watch?v=_r5r0nE1sA4
Il y a aussi Jak and Daxter, Ratchet
Côté GC, RE4, Metroid, les Zelda, etc., sont évidemment incroyablement beaux
Ça force le respect
Elle pouvait probablement rivaliser avec un Pentium 90, presque 100, mais un Pentium MMX équipé d’une 3DFX aurait écrasé la PSX et aurait été au niveau de la N64, voire meilleur
Le CPU MIPS était excellent et accomplissait des choses étonnantes malgré sa faible fréquence. Il suffit de regarder la PSP ou SGI Irix
Par ailleurs, le « GPU » de la PS2 n’est pas la même chose qu’un CPU R4k
J’ajouterais que le portage de Deus Ex sur PS2 était médiocre par rapport à la version PC et ne gérait pas vraiment l’Unreal Engine
Il est vrai que la PS2 produisait des effets incroyables, mais dans ce portage, les niveaux étaient vraiment petits. Il faut aussi tenir compte du fait qu’une grande partie de Deus Ex était presque en monde ouvert
Le flou, le bloom, le pop-in de l’herbe et de la végétation, ce genre de choses ne rend pas vraiment bien et paraît simplement pire que si tout était désactivé
Dans un FPS rapide, on n’a même pas le temps d’admirer des modèles très polygonés ; je ne vois donc pas vraiment l’intérêt
À mes yeux, la résolution des textures de Halo 3 suffit. Même si les textures étaient deux ou quatre fois plus grandes, je ne pense pas que je le remarquerais ; la seule chose visible serait les exigences matérielles
La vidéo de GoW2 a été capturée dans PCSX2, et dans ce clip, elle a probablement bénéficié de l’upscaling et d’autres fonctionnalités de confort
Je n’ai pas regardé toutes les autres vidéos, mais quoi qu’il en soit, ce que GoW2 a accompli sur PS2 était remarquable