Liquid✨ Premium

WebGL Fluid Simulation

Une vraie simulation de fluide sur la carte graphique : l'encre néon suit le curseur, tourbillonne, s'estompe, un clic fait éclater une couleur et une main invisible continue de remuer quand personne ne touche — WebGL2 avec repli WebGL1, net sur écran Retina, en pause hors écran, image fixe si l'utilisateur réduit les animations.

WebGLShaderFluidInteractiveBloom

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Liquid comprend 31 effets, dont 6 gratuits. Découvrir la catégorie →

3 exemples d'usage

Papier marbré à la cuve — page d'un relieur d'art — WebGL Fluid Simulation exemple 1

① Papier marbré à la cuve — page d'un relieur d'art

QuandLe titre « L'atelier de marbrure » en haut à gauche, sur un fond d'encres qui tourbillonnent ; la souris trace des volutes comme le peigne du marbreur, un clic dépose une nouvelle couleur.
PourquoiL'encre est vraiment entraînée par le geste et forme des volutes qui restent un moment, comme sur la cuve ; un dégradé animé bougerait tout seul sans répondre à la main.
Réglagesdata-wfl-palette="aurora", data-wfl-keep="0.8" (encre plus persistante), data-wfl-swirl="14" (volutes plus douces), data-wfl-bloom="0" (pas de halo, aspect encre) ; scène plein cadre, voile .wfl-scrim du gabarit derrière le titre en Georgia 30 px.
Mur tactile de la salle sensorielle — institut médico-éducatif — WebGL Fluid Simulation exemple 2

② Mur tactile de la salle sensorielle — institut médico-éducatif

QuandSur le grand écran mural à hauteur d'enfant, chaque geste laisse une traînée lumineuse et chaque tape un éclat de couleur ; entre deux enfants, l'écran continue de bouger doucement.
PourquoiRéponse immédiate et douce, sans son ni texte ; la main invisible garde l'écran vivant entre deux enfants, et le réglage « mouvement réduit » de l'appareil donne une image fixe pour un enfant que le mouvement agite.
RéglagesRéglages par défaut : data-wfl-palette="neon", data-wfl-bloom="1", data-wfl-idle="1", classe .wfl-paint pour peindre au doigt ; écran encadré d'un bord de 6 px et de coins de 18 px, plaque « Salle Arc-en-ciel » dessous.
Visuels pilotés par le VJ — soirée d'un collectif électro dans une friche — WebGL Fluid Simulation exemple 3

③ Visuels pilotés par le VJ — soirée d'un collectif électro dans une friche

QuandProjection plein écran derrière le DJ : le VJ peint à la souris au rythme de la musique, et ses clics sur les temps forts font éclater les couleurs ; la cabine se découpe en ombre chinoise devant.
PourquoiLe calcul sur carte graphique tient la cadence en grand format (120 images par seconde mesurées jusqu'à 1 789 × 1 006) ; un canvas 2D calculé pixel par pixel ne suivrait pas.
Réglagesdata-wfl-swirl="34" (tourbillons plus forts), data-wfl-keep="0.42" (encre plus brève, le cadre se renouvelle), data-wfl-bloom="1" ; cabine et public en SVG noir posé par-dessus en pointer-events: none.

Comment ça marche

Le bloc .fx-0841-root contient une scène .wfl-scene au format 16/9 (coins de 14 px, fond #0a0a0f, curseur en croix) avec un <canvas class="wfl-canvas"> qui la remplit, et une étiquette de démonstration qui s'efface au survol. Le script crée un fluide par .wfl-scene de la page et le règle par attributs : data-wfl-palette (neon, aurora ou mono avec data-wfl-hue), data-wfl-keep (part d'encre gardée chaque seconde, 0,55), data-wfl-swirl (force des tourbillons, 22), data-wfl-bloom (halo lumineux, 1), data-wfl-idle (main invisible, 1) et data-wfl-ink (quantité d'encre, 1). Chaque scène expose aussi scene.wfl.set(), burst(x, y), clear() et state().

La simulation suit la méthode « stable fluids » de Jos Stam (1999), entièrement en shaders. À chaque image : le pointeur injecte de la vitesse et de l'encre le long de son trajet ; le confinement de vorticité ravive les petits tourbillons ; la pression est résolue par 18 itérations de Jacobi (12 sur un cadre de moins de 700 px) pour que le fluide ne se comprime pas ; puis vitesse et encre sont transportées par le flux. La vitesse se calcule sur une grille de 128 cases sur le petit côté, l'encre sur 512 (384 sous 700 px), l'affichage à la densité de l'écran (jusqu'à 2, dans la limite de 1,8 million de pixels). Les mélanges ternes s'effacent plus vite que les couleurs franches, et chaque nouvelle couleur reste voisine de la précédente sur le cercle des teintes : l'encre ne vire ni au brun ni au gris. L'affichage ajoute un léger relief éclairé du haut à gauche, un halo sur 4 niveaux pour les zones les plus claires et un grain d'une demi-teinte qui évite les marches dans les dégradés. Les pas de temps suivent l'horloge réelle : même vitesse à 60 et à 120 Hz.

Un clic fait éclater une tache de 6 à 8 jets qui tournent sur eux-mêmes. Après 2,5 s sans pointeur, la main invisible reprend : un trait qui dérive lentement dans le cadre et un éclat toutes les 2,5 à 5 s, pour que le fond reste vivant. Le calcul s'arrête hors écran (IntersectionObserver) et quand l'onglet est caché. Un bloc caché au chargement (onglet, accordéon fermé) crée ses buffers dès qu'il prend une taille. Si le navigateur reprend le contexte WebGL, le script attend sa restauration et repart. Sans WebGL, la scène reçoit .wfl-nogl : quatre taches néon fixes en dégradés CSS, jamais un cadre vide. Mesuré avec la carte graphique dans Chromium et Firefox : 120 images par seconde jusqu'à un canvas de 1 789 × 1 006, moins de 0,1 ms de JavaScript par image ; en rendu logiciel (sans accélération), 49 images par seconde à 640 × 360 et 25 à 1 789 × 1 006.

Accessibilité

  • Mouvement réduit : sous prefers-reduced-motion: reduce, le script peint une image fixe (cinq taches d'encre mises en volutes d'un coup) et ne lance ni boucle ni main invisible ; mesuré dans Chromium, Firefox et WebKit, 0 % de pixels qui changent au repos. Un geste du visiteur fait bouger le fluide pendant 1,5 s, puis tout s'arrête : le mouvement ne vient que de lui. Un bloc caché au chargement garde ce comportement quand il s'affiche.
  • Lecteurs d'écran : le canvas porte role="img" et un aria-label qui décrit ce qu'on voit ; l'étiquette de démonstration est en aria-hidden="true". En fond décoratif sous un titre, remplacez le libellé par une description courte ou passez le canvas en aria-hidden="true".
  • Toucher et clavier : sur une scène .wfl-paint, le doigt peint et la page ne défile pas dans le cadre (touch-action: none) ; sans cette classe, le doigt fait défiler la page et ne peint qu'en touchant. Au clavier, rien ne se passe : l'effet n'est qu'un décor, aucune information ne doit en dépendre.
  • Texte posé dessus : le CSS fournit un gabarit de bandeau (.wfl-scrim, .wfl-hero-content, .wfl-title, .wfl-btn) avec un voile dégradé derrière le texte ; sous prefers-contrast: more ou prefers-reduced-transparency: reduce, le texte passe sur un panneau opaque et le fluide est atténué.

Compatibilité navigateur

WebGL2 (textures RGBA16F) avec repli WebGL1 (demi-flottants, puis flottants, puis 8 bits encodés), filtrage linéaire refait à la main si la carte graphique ne filtre pas les flottants : 38 Ko de JavaScript, aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26 : WebGL2 actif, canvas à 1 280 × 720 pour une scène de 640 × 360 sur écran Retina, pause hors écran, image fixe sous mouvement réduit, scène cachée au chargement qui démarre à l'affichage, 0 erreur. Le repli WebGL1, forcé dans les trois moteurs, tourne à l'identique. Sans WebGL (testé dans Chromium), la scène affiche son dégradé fixe.

Chrome 56+✓ Complet (WebGL2)
Firefox 51+✓ Complet (WebGL2)
Safari 15+✓ Complet (WebGL2) ; avant, repli WebGL1
Edge 79+✓ Complet (WebGL2)
Mobile iOS 15+✓ Complet, au doigt
Android Chrome 56+✓ Complet, au doigt (grilles réduites sous 700 px)

Sans WebGL (navigateur ancien, accélération désactivée), la scène reçoit .wfl-nogl : quatre taches néon fixes en dégradés CSS. Sans JavaScript, le cadre reste noir avec son étiquette. Sans ResizeObserver, le script suit l'événement resize de la fenêtre.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :

index.html — structure
<div class="fx-0841-root">
  <div class="wfl-scene wfl-paint" data-wfl-palette="neon" data-wfl-keep="0.55">
    <canvas class="wfl-canvas" role="img" aria-label="…"></canvas>
    <div class="wfl-hint" aria-hidden="true">
      <span>WebGL Fluid Simulation</span>
      <span class="wfl-hint-sub">…</span>
    </div>
  </div>
</div>

Paiement unique, sans abonnement — le code est à toi pour toujours

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Palette (HTML — data-wfl-palette, data-wfl-hue) neon neon va du vert citron au rose vif sans jamais passer par le rouge ni le jaune ; aurora fait l'aller-retour vert, cyan, bleu, violet ; mono décline une seule teinte, choisie par data-wfl-hue de 0 à 1 (0,55 : bleu cyan, 0,8 : violet).
Persistance de l'encre (HTML — data-wfl-keep) 0,55 : l'encre garde 55 % de son intensité chaque seconde 0,8 laisse des volutes qui restent plusieurs secondes ; 0,3 efface vite, pour un fond qui se renouvelle sous le texte. De 0,05 à 0,98.
Tourbillons (HTML — data-wfl-swirl) 22 10 à 15 pour des volutes lentes et larges ; 30 à 40 pour un fluide nerveux plein de petits remous.
Halo lumineux (HTML — data-wfl-bloom) 1 0 retire le halo : aspect d'encre mate, un peu moins de calcul sur la carte graphique.
Main invisible (HTML — data-wfl-idle) 1 : reprise après 2,5 s sans pointeur 0 laisse le fluide se calmer et s'éteindre quand personne ne touche. Le délai se règle dans le JS (IDLE_AFTER = 2500, en ms).
Quantité d'encre (HTML — data-wfl-ink) 1 0,6 pour un fond discret derrière un texte ; 1,5 pour des traits plus denses et plus lumineux.
Pilotage par script (JS — scene.wfl) set, burst, clear, state scene.wfl.set({ palette: 'aurora', keep: 0.7 }) change les réglages à chaud ; scene.wfl.burst(0.5, 0.5) fait éclater une couleur au centre (coordonnées de 0 à 1, origine en bas à gauche) ; scene.wfl.clear() vide le cadre.

FAQ

Chaque .wfl-scene ouvre son propre contexte WebGL, et les navigateurs en limitent le nombre (autour de 16 dans Chrome) ; seuls les fluides visibles calculent. Trois scènes sur une même page tournent sans difficulté (mesuré dans les exemples). Si le navigateur reprend un contexte faute de mémoire, le script attend qu'il soit rendu et reconstruit le fluide, y compris dans un bloc caché à ce moment-là.
Fluid Gradient est un fond CSS : quatre taches floutées qui tournent toutes seules en 15 s, sans script et sans réaction au pointeur. WebGL Fluid Simulation calcule un vrai fluide : l'encre est poussée par le geste, tourbillonne, se mélange et s'efface. Choisissez Fluid Gradient pour un fond discret et léger ; la simulation quand le geste du visiteur fait partie de l'expérience.
Le script réduit lui-même la charge : densité d'affichage plafonnée à 1,8 million de pixels, grilles d'encre et de pression réduites sous 700 px de large. Mesuré en rendu logiciel, le cas le plus défavorable : 49 images par seconde à 640 × 360 et 25 en très grand format. Pour un fond plein écran sur des machines modestes, passez data-wfl-bloom="0". Sans WebGL du tout, la scène affiche son dégradé néon fixe.