Si on veut animer beaucoup de particules (1 million ?), il faut déléguer le plus de travail possible à la carte graphique (GPU). Idéalement, il faudrait que tous les calculs de trajectoire soient exécutés via un vertex-shader en GLSL.
La simulation ci-dessous, avec 800000 particules, met en oeuvre une technique prévue dans webGL prévue pour parvenir à une telle chose.
Les particules sont représentées par une liste de points (vertexArray), sous la forme de buffers de positions et vitesses, qu'on initialise ou pas avec des valeurs initiales. Ce remplissage peut-être fait en javascript (CPU) une fois.
On peut imaginer plusieurs situations :
Animation "triviale"
On donne au shader une variable "uniform" de temps, mise à jour à chaque rendu
Le shader de vertex calcule exactement et analytiquement la position en fonction du temps et des paramètres initiaux. (trajectoire en chute libre par exemple).
Ce n'est pas une simulation pas-à-pas, on a la "formule" : on peut jouer l'animation à l'endroit ou à l'envers, aller à l'instant "t", etc.
le CPU n'est presque plus concerné une fois l'initialisation passée, il ne donne que le temps au shader à chaque rendu.
Réservé aux cas où l'on possède bel et bien une solution mathématique complète du problème.
Difficile a priori de rajouter des interventions extérieures imprévisibles (gravité à la souris par exemple)
On ne "connaît pas" (du point de vue du cpu) les positions et vitesses instantanées.
Simulation rendue avec le GPU mais positions et vitesses re-calculée par le CPU
À chaque rendu : récupération des buffers de positions et vitesses dans javascript (CPU)
Calcul des nouvelles positions et vitesses à partir des valeurs précédentes.
On peut alors faire un petit peu ce qu'on veut comme algorithme ...
Mise à jour des buffers dans la carte graphique.
le CPU est très concerné pendant l'animation.
Il y a beaucoup de transit de données entre CPU et GPU, ce qu'il faut éviter.
Le nombre maxi de particules avec rendu fluide sera limité.
Simulation "complexe" calculée et rendue par le GPU via les "transform feedback"
Nécessité du transform feedback : les coordonnées et vitesses transformées dans le shader sont conservées dans le GPU.
Elles deviennent les valeurs d'entrée pour la prochaine exécution. (cela n'est pas sans rappeler de texture ping-pong du précédent article)
Ainsi, le shader peut contenir et appliquer les équations du mouvement, dans une simulation pas-à-pas.
C'est la solution implémentée ci-dessous, elle contient 800 000 particules soumises à divers champs de forces (plus interaction souris).
Demande WebGL2 qui n'est pas encore disponible dans tous les navigateurs.
Simulation "complexe" calculée et rendue par le GPU via un FB ping-pong
On peut se passer du transform feedback en engrammant les positions et vitesses des particules dans les pixels d'une texture au lieu de vertexArrays.
Par exemple, 4096 particules pourront être suivies efficacement avec 2 textures (positions, vitesses) 64x64px.
Ces textures sont constamment updatées et ré-employée par des shaders dans le cadre du FBO ping-pong décrit dans le précédent article.