1 points par GN⁺ 2024-09-29 | 1 commentaires | Partager sur WhatsApp
  • GodotOceanWaves est une expérimentation de rendu dans Godot Engine qui génère une surface de haute mer à l’aide de la transformée de Fourier inverse d’un spectre directionnel de vagues océaniques, et simule divers environnements marins grâce à des paramètres ajustables en temps réel par script
  • Les ondes de Gerstner conviennent aux détails basse fréquence d’une eau calme, mais montrent leurs limites pour une surface de haute mer agitée ; ce projet utilise donc un spectre fondé sur des données empiriques d’océanographie et la FFT
  • La génération des vagues suit la méthode de Tessendorf : création d’un état spectral initial, propagation temporelle via la relation de dispersion, puis transformée de Fourier inverse pour produire des cartes de déplacement, de normales et d’écume
  • Le rendu suit la BSDF de la présentation Atlas GDC, mais utilise une distribution GGX ; l’écume s’accumule et se dissipe dans les zones où le Jacobien du déplacement est négatif, et le sea spray est implémenté avec GPUParticles3D de Godot et un shader personnalisé
  • Plusieurs wave cascades, le réglage de la fréquence de mise à jour et la répartition de charge par cascade permettent de gérer le tiling et la charge GPU, mais toutes les cascades doivent utiliser la même résolution de texture spectrale, et l’approche par particules pour le sea spray est peu efficace quand on augmente la densité

Ce que fait GodotOceanWaves

  • GodotOceanWaves est un projet expérimental de rendu de haute mer dans Godot Engine
  • La génération des vagues repose sur la transformée de Fourier inverse d’un spectre directionnel de vagues océaniques
  • Les paramètres exposés restent volontairement simples et peuvent être modifiés en temps réel par script afin de simuler différents environnements de vagues marines
  • Deux vidéos de démonstration sont incluses : ocean_demo.mp4 et environment_demo.mp4

Pourquoi utiliser des vagues basées sur Fourier plutôt que des ondes de Gerstner

  • Une méthode courante pour animer l’eau dans les jeux consiste à déplacer les sommets avec des ondes de Gerstner
  • Les ondes de Gerstner sont adaptées à la modélisation des détails basse fréquence d’une eau calme, mais insuffisantes pour représenter fidèlement la surface agitée d’une haute mer ouverte
  • L’utilisation de spectres de vagues océaniques fondés sur des données empiriques collectées par les océanographes permet d’agir plus directement sur les vagues et paramètres à modifier pour obtenir un état de mer donné
  • La FFT a une complexité en O(N log N), inférieure au O(N^2) de la transformée de Fourier discrète classique, et se prête bien à une exécution sur GPU grâce à sa compatibilité avec les systèmes parallèles
  • Avec les ondes de Gerstner, chaque thread doit calculer N vagues, alors qu’avec des vagues basées sur la FFT, chaque thread n’effectue qu’un calcul de l’ordre de log(N)

Shading, écume et sea spray

  • Le modèle d’éclairage océanique suit globalement la BSDF de la présentation Atlas GDC
  • La distribution microfacette utilise GGX au lieu de Beckmann
    • Les reflets plus plats et plus doux de GGX donnaient un rendu plus homogène dans les différents environnements marins testés
  • Les cartes de normales et d’écume sont échantillonnées en mélangeant filtrage bicubique et bilinéaire selon la densité de pixels en espace monde
    • Cela réduit les artefacts d’aliasing de texture lorsque la résolution de surface est faible, tout en conservant les détails quand elle est élevée
  • La sea foam est générée, selon la méthode de Tessendorf, aux endroits où la crête de vague s’enroule vers l’intérieur, c’est-à-dire là où le Jacobien du déplacement est négatif
    • L’écume s’accumule linéairement dans la texture au fil de plusieurs mises à jour des vagues
    • Les paramètres "foam grow rate" et "foam decay rate" contrôlent respectivement l’accumulation et la dissipation exponentielle
  • Le sea spray est implémenté avec le nœud GPUParticles3D de Godot et un shader de particules personnalisé
    • Les particules sont réparties uniformément sur un plan à l’intérieur de la boîte englobante de GPUParticles3D
    • Elles sont éliminées selon la quantité d’écume présente à leur position, et celles qui ne le sont pas démarrent leur cycle de vie avec un décalage aléatoire
    • Chaque particule utilise un sprite billboard avec une seule texture statique
    • Pendant son cycle de vie, son échelle et son déplacement varient pour reproduire l’apparence d’un splash, et un effet de dissolution dans le mesh shader donne l’impression que les embruns s’atomisent dans l’air
  • Le principal inconvénient de cette approche du sea spray est qu’une forte augmentation du nombre de particules n’entraîne qu’un faible gain de densité
    • Comme les particules sont uniformément réparties dans la boîte englobante, la plupart des particules ajoutées sont éliminées

Pipeline de simulation des vagues

  • La méthode de génération de la surface suit de très près Tessendorf
  • Un état spectral initial de la mer est créé en multipliant une fonction de spectre directionnel de vagues océaniques par des nombres aléatoires à distribution gaussienne
  • Cet état initial est propagé dans le temps via la relation de dispersion, qui relie la fréquence des vagues à leur vitesse de propagation
  • Une transformée de Fourier inverse est ensuite appliquée à l’état propagé pour générer les cartes de déplacement et de normales
  • L’implémentation repose sur un pipeline de compute shaders utilisant l’abstraction RenderingDevice de Godot

Composition du spectre de vagues océaniques

  • La fonction de spectre directionnel S(ω, θ) renvoie l’énergie d’une vague pour une fréquence ω et une direction θ données
  • Cette fonction se compose d’un spectre non directionnel S(ω) et d’une fonction d’étalement directionnel D(ω, θ), les deux choix étant indépendants l’un de l’autre
  • Pour le spectre non directionnel, l’implémentation utilise le spectre Texel-Marsen-Arsloe (TMA) décrit par Horvath
    • Le TMA utilise la vitesse du vent U, la profondeur D et la longueur de fetch F
    • Il combine le spectre JONSWAP qui le précède avec une fonction d’atténuation liée à la profondeur
  • Pour la fonction d’étalement directionnel, le projet utilise un mélange des diffusions directionnelles flat et Hasselmann de Horvath, contrôlé par le paramètre spread μ
    • Le paramètre swell ξ proposé par Horvath est également inclus pour modéliser l’allongement des vagues océaniques
    • La diffusion directionnelle de Hasselmann a été retenue parce qu’elle fournit une solution analytique approchée pour le coefficient de normalisation Q(σ)
  • Conformément à la proposition de Tessendorf, la fonction spectrale résultante est aussi multipliée par un terme de suppression des petites vagues
    • Ce terme utilise la norme du vecteur d’onde k et le paramètre detail δ
  • Le spectre directionnel final combine donc TMA, étalement directionnel mixte et suppression des petites vagues

Implémentation GPU de la FFT

  • La FFT repose sur une implémentation GPU personnalisée écrite en compute shader
  • L’algorithme Stockham FFT est utilisé à la place de Cooley-Tukey afin d’éviter la permutation initiale par inversion de bits
  • En suivant Flügge, le projet calcule une texture "butterfly" qui encode le flux de données de la FFT
    • Cette texture n’est recalculée qu’une seule fois à chaque changement de résolution de la texture spectrale
  • La FFT 2D applique d’abord le noyau FFT aux lignes de la texture spectrale
  • La texture est ensuite transposée via compute shader pour réutiliser le même noyau FFT sur les colonnes comme s’il s’agissait de lignes
  • La transposition permet non seulement de réutiliser le pipeline, mais améliore aussi les schémas d’accès mémoire

Wave cascades et gestion du tiling

  • À longue distance, les artefacts de tiling deviennent très visibles, surtout en présence de sea foam
  • Le système de génération des vagues traite ce problème en permettant de superposer plusieurs wave cascades simultanément
  • Chaque cascade possède sa propre taille de tiling et son propre ensemble de paramètres
  • Les cascades peuvent être ajoutées ou retirées dynamiquement en temps réel
  • Comme toutes les cascades utilisent le même pipeline de calcul, elles doivent toutes avoir la même résolution de texture spectrale
  • Une alternative consiste à mélanger les déplacements et normales des vagues avec du bruit afin de réduire les artefacts de tiling à moindre coût en performances
  • Pour éviter les interférences entre vagues lors de la superposition des cascades, il faut choisir avec soin les paramètres et la taille de chaque cascade
  • Les phases des cascades doivent aussi être décalées pour ne pas interférer entre elles
    • Le système essaie de le faire automatiquement en décalant différemment le temps de départ de chaque cascade
    • Une réserve est toutefois mentionnée : rien ne garantit que cette méthode fonctionne réellement

Répartition de la charge des mises à jour

  • Comme le mouvement des vagues est irrégulier, il peut rester visuellement fluide même si le déplacement n’est pas mis à jour à chaque frame
  • Le paramètre "update rate" contrôle la fréquence de mise à jour de chaque wave cascade par seconde
  • Sauter des frames réduit le temps GPU consacré à la FFT, mais du stutter subsiste sur les frames où le pipeline de génération des vagues s’exécute
  • Des essais de calcul asynchrone des mises à jour de cascade avec le RenderingDevice local de Godot ont entraîné un important surcoût de performances à cause des transferts de textures entre CPU et GPU
  • À la place, le système tente une répartition de charge entre cascades
    • Si le temps de frame est inférieur à la fréquence de mise à jour, une seule cascade est mise à jour par frame
    • Cette approche réduit le stutter tout en conservant l’avantage d’une charge GPU plus faible obtenu par le saut de frames

Références

1 commentaires

 
GN⁺ 2024-09-29
Avis sur Hacker News
  • Les deux autres dépôts Godot créés par cette personne sont aussi très intéressants. J’aime le niveau de détail qu’elle met dans les descriptions des dépôts, et celui-ci ressort particulièrement : https://github.com/2Retr0/GodotGaussianSplatting
    Je me demande si c’est un étudiant. Il cite souvent d’autres travaux et semble assez bien comprendre des publications récentes.

    • Il y a des chances que ce soit un étudiant. Le titre et la description d’un dépôt sont ENGR96A-coursework, Relevant coursework for ENGR 96A Introduction to Engineering Design F23, et d’après les dates de commit, F23 semble vouloir dire semestre d’automne 2023.
      Bien sûr, les cours de l’UCLA mentionnés dans le dépôt peuvent être ouverts à tout le monde, donc il n’est peut-être pas nécessaire d’être inscrit à l’UCLA au sens traditionnel pour les suivre.
  • Il y a 20 ans, je pense qu’on aurait pu passer des mois à ajuster la surface de la mer dans un rendu sans approcher ce niveau. Le résultat est vraiment très bien fait.
    Cela dit, la vidéo de démo a l’air un peu exagérée. Avec plus de 50 000 milles nautiques de navigation au large dans mon journal de bord, je dirais que des vagues aussi hautes et acérées impliqueraient un vent bien plus fort. Mais ça semble être une question de réglage des paramètres.
    Si c’est fait avec Godot, peut-on considérer que c’est du rendu temps réel ? Je me demande aussi s’il faut un GPU monstrueux.

    • Ce n’est pas une critique, plutôt une observation : on dirait ce qu’on obtiendrait en imaginant une mer de sirop de maïs chaud teinté en bleu. La viscosité semble correcte, mais la tension de surface pourrait être différente de celle de l’eau de mer réelle. L’eau de mer est un colloïde d’eau salée H2O et de matière biologique : courant dans la réalité, mais assez sale pour la mécanique des fluides numérique.
      Ici, l’embrun marin ressemble aussi à un effet de post-traitement, alors que dans la vraie mer, les embruns émoussent le tranchant des vagues, ce qui se perçoit aussi visuellement.
      Bien sûr, ce modèle élégant, simple et efficace ne contient presque pas de physique ; donc je préférerais qu’on voie ces remarques non pas comme une critique les bras croisés, mais comme des pistes à tester en le poussant un peu dans différentes directions.
    • Aujourd’hui, il y a beaucoup de vidéos sur ce genre de sujet, donc l’ensemble du processus est devenu assez accessible, mais il reste beaucoup de pièges.
      Une de mes vidéos préférées sur le sujet : https://m.youtube.com/watch?v=yPfagLeUa7k
      Celle-ci est bien aussi : https://m.youtube.com/watch?v=kGEqaX4Y4bQ
    • J’ai un projet de jeu, et dès que je vois une techno de jeu impressionnante, je me fais toujours nerd-sniper et j’ai envie de l’implémenter moi-même. Si j’avais utilisé ou acheté des assets existants, l’avancement que j’ai aujourd’hui aurait probablement été possible même lors d’une game jam de 48 heures.
      À la place, je passe mes week-ends à bricoler des shaders d’eau jusqu’à obtenir le rendu que je veux. Sauf que mon jeu est un jeu de puzzle, donc il n’a pas besoin d’eau. Maintenant, j’ai juste un superbe écran de démarrage.
    • Quand j’ai obtenu mon diplôme, faire un moteur de particules ou des marching cubes, c’était encore un projet de mémoire de fin d’études.
      Aujourd’hui, ce n’est plus qu’une case à cocher dans un moteur de jeu, et il y a une infinité de fonctionnalités comme ça. Les gens n’imaginent pas à quel point les moteurs modernes offrent un environnement formidable.
      Je ne veux pas minimiser la valeur de ce travail ; c’est une vraie réussite, et bravo à son auteur. Je voulais seulement souligner à quel point nous vivons une bonne époque.
    • D’après la vidéo seule, je suis d’accord que ça paraît un peu aléatoire.
      Cela dit, le rendu est très bon, et d’après mes recherches rapides récentes, c’est probablement parmi ce qui se fait de mieux.
      Personnellement, j’aimerais voir des vagues de haute mer avec généralement plus de rythme. Je me demande si une simulation d’un vent de 15 nœuds soufflant pendant plusieurs heures sur 1 km de surface d’eau correspondrait à ce qu’on observe réellement : des déferlements relativement ordonnés qui se forment puis se dissipent.
  • C’est ce genre de choses qui m’a attiré vers l’informatique, mais je me suis retrouvé à mener une vie facile et ennuyeuse à assembler des bibliothèques, des endpoints et du bullshit corporate, ce qui m’emmène vers le burn-out.
    J’espère pouvoir y revenir un jour.

    • Je pense qu’on peut faire la transition petit à petit. Trouver le domaine qui vous avait intéressé au départ, que vous voulez approfondir et dans lequel vous aimeriez finir par pratiquer, puis y consacrer quelques heures par semaine, augmenter progressivement, et s’éloigner de son travail actuel.
      Essayez. On est tous derrière vous.
    • Je vois beaucoup d’amis qui gagnent plus que moi en faisant ce genre de travail, mais j’ai suivi mes centres d’intérêt et je suis parti dans la robotique dès que j’en ai eu l’occasion, et je ne le regrette pas. Pour moi en tout cas, rien ne vaut la sensation de voir mon code interagir avec le monde réel.
  • L’approche est différente, mais si les simulations de vagues/d’océan vous intéressent, Acerola a publié, comme toujours, une excellente vidéo sur le sujet. https://youtu.be/PH9q0HNBjT4 et https://youtu.be/yPfagLeUa7k
    Modification : l’une d’elles était déjà liée dans la bibliographie, mais sous son vrai nom et non son pseudo, donc je viens seulement de m’en rendre compte.

  • C’est fascinant de voir à quel point ce problème est difficile. On essaie depuis des décennies, et on reste encore dans la vallée de l’étrange.
    Si on met cette scène en pause, les vagues dressées ressemblent à des montagnes enneigées. Pour que l’eau ait des formes aussi acérées, il faudrait un vent assez fort, mais comme le vent ne va évidemment pas souffler droit vers le haut, ça donne une impression irréaliste. Ces caractéristiques tranchantes devraient avoir une direction.
    Cela dit, le caractère de la houle est assez bien rendu. Le mouvement vertical est plus important que le déplacement horizontal, ce qu’on peut attendre en haute mer.

    • J’ai joué à Nightingale, et son eau de mer est vraiment particulière. Pour être clair, ils semblent garder les vagues calmes afin d’éviter les problèmes comme les embruns, ce qui leur permet de se concentrer sur autre chose.
      Je ne sais pas comment ils simulent la transmission de la lumière, mais ça fonctionne bien. Au lever ou au coucher du soleil, la lumière qui passe entre les vagues est superbe et rend l’effet vraiment crédible.
      On pourrait dire que c’est un peu pictural, mais ça ne paraît pas faux.
  • J’ai vécu plusieurs années au bord de la mer. Quand on habite sur la plage, l’océan est fascinant et agréable sensoriellement, au point qu’on peut le regarder pendant des heures. En voyant ceci, je ne pense pas que j’aurais imaginé une seule seconde que c’était un rendu.

    • Je vis actuellement au bord de la mer, avec une vue située à environ 14 étages au-dessus de la surface de l’eau, et curieusement il est évident pour moi que c’est faux. Il n’y a pas de taches sombres créées par les rafales, et les parties blanches montent droit vers le haut sans s’enrouler ne serait-ce qu’un peu. À part ça, c’est assez réaliste.
    • Avez-vous déjà vraiment observé des vagues et leur mouvement ? Si vous avez vécu plusieurs années sur la plage, vous devriez immédiatement remarquer que la formation de l’écume et le mouvement des vagues ne sont pas naturels.
  • Il y a aussi un bon exemple sur Shadertoy : https://www.shadertoy.com/view/Ms2SD1

  • Fourier a eu l’idée de la transformation des fréquences d’ondes en mesurant des ondes de marée, donc d’une certaine manière, on boucle presque la boucle.
    Très impressionnant.

  • C’est excellent, mais cette approche s’effondrera dans une certaine mesure pour les très grosses vagues à cause des non-linéarités. Les vagues ne sont pas des sinusoïdes, mais pour les petites et moyennes vagues, elles en sont assez proches pour que cette méthode fonctionne très bien.
    Les très grosses vagues s’éloignent beaucoup plus des sinusoïdes, et en plus les vagues commencent à interagir entre elles de façon non linéaire, ce que la superposition linéaire utilisée ici ne peut pas capturer.
    C’est donc fantastique pour la plupart des états de mer. Mais si vous voulez créer de manière réaliste des vagues façon « tempête du siècle », il faut une autre approche.

  • C’est très impressionnant et meilleur que ce que j’ai vu jusqu’ici, mais la houle me semble légèrement décalée. Si je devais l’expliquer, je dirais que les vagues de haute fréquence ne se déplacent pas sur les vagues de basse fréquence comme dans la vidéo.