Glassmorphism✨ Premium

Glass Caustics (WebGL)

Des caustiques de piscine calculées en temps réel par un shader WebGL — cinq itérations par pixel, netteté doublée sur écran Retina — vues à travers une vitre floutée à 7 px et saturée à 160 % ; dégradé de repli si WebGL manque, image fixe si l'utilisateur réduit les animations.

WebGLShaderCaustics

Mis à jour le

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

3 exemples d'usage

Fiche d'une piscine naturelle — site d'un pisciniste — Glass Caustics (WebGL) exemple 1

① Fiche d'une piscine naturelle — site d'un pisciniste

QuandPage d'une réalisation : les reflets d'eau bougent sous la fiche technique (dimensions, profondeur, filtration par les plantes, eau sans chlore), entre la margelle et les roseaux.
PourquoiLes caustiques montrent la clarté de l'eau, l'argument principal d'un bassin naturel ; le shader reste fluide même plein cadre, là où une vidéo pèserait plusieurs mégaoctets.
RéglagesVitre de 258 px en haut à gauche, texte aligné à gauche, fiche en <dl> deux colonnes ; margelle en bordure de 16 px à joints, roseaux en dégradés obliques posés entre le canvas et la vitre.
Accueil d'un centre de plongée — site d'un club en Bretagne — Glass Caustics (WebGL) exemple 2

② Accueil d'un centre de plongée — site d'un club en Bretagne

QuandPage d'accueil du club : la lumière sous l'eau ondule derrière la liste des prochaines sorties, avec niveau, profondeur et places restantes.
PourquoiLes caustiques sont ce que voit un plongeur en regardant le fond : l'ambiance est immédiate, sans photo à charger, et la vitre garde les dates lisibles.
RéglagesVitre de 250 px sur toute la hauteur à droite ; dates en pastilles sombres ; voile dégradé vers le bas au-dessus du canvas pour asseoir le nom du club et le bouton « Faire un baptême ».
Cartel du bassin des méduses — écran d'un aquarium public — Glass Caustics (WebGL) exemple 3

③ Cartel du bassin des méduses — écran d'un aquarium public

QuandÉcran à côté du bassin : nom de l'espèce, nom latin, taille, durée de vie et habitat, sur une lumière d'eau où flottent des méduses.
PourquoiLa lumière d'eau sur l'écran prolonge le bassin réel ; et sur une borne ancienne sans WebGL, le repli en dégradé garantit un affichage au lieu d'un écran noir.
RéglagesCartel de 300 px en bas à gauche ; méduses translucides en CSS (ombrelle, gonades, tentacules masqués en fondu) qui montent et descendent en 5 s, arrêtées sous mouvement réduit ; voile radial pour assombrir les bords.

Comment ça marche

Une scène en 16/10 (.gc-scene, coins de 14 px, fond #04101c) avec deux couches : un <canvas class="gc-canvas"> plein cadre, et la vitre .gc-glass — min(72%, 330px) de large, coins de 22 px, dégradé blanc de 16 % à 5 %, liseré à 28 %, backdrop-filter: blur(var(--gc-blur, 7px)) saturate(160%), texte centré à ombres portées. Le flou de 7 px est volontairement léger : les lignes de lumière restent devinables sous la vitre, comme à travers un verre épais.

Le script crée un contexte WebGL par canvas, compile un shader de sommets qui couvre l'écran d'un seul triangle, et un shader de fragments qui calcule chaque pixel : il ramène la position dans une tuile de 2π, puis fait cinq itérations où la position est déformée par des sinus et cosinus du temps ; l'intensité cumulée, passée à la puissance 8, donne des filaments lumineux très fins, ajoutés à un bleu de piscine (0.04, 0.32, 0.52). Le temps avance à 0,4 × les secondes. La taille du canvas suit la scène à la densité de l'écran, plafonnée à 2 (mesuré : 784 × 490 px de canvas pour une scène de 784 px à densité 1), recalculée à chaque redimensionnement de fenêtre. Chaque canvas a sa boucle : plusieurs vitres par page fonctionnent. Mesuré dans Firefox et dans Chromium avec la carte graphique : filaments nets, ondulation continue.

Trois replis sont prévus dans le script. Si l'utilisateur demande moins de transparence, ou si le navigateur ne connaît pas backdrop-filter, la scène reçoit .gc-solid ; le préfixe -webkit- couvre Safari 17 et antérieurs. Sans WebGL, elle reçoit .gc-nogl : mesuré en retirant WebGL au navigateur, le canvas est masqué et un dégradé radial bleu prend sa place. En mouvement réduit, une seule image est dessinée — et redessinée à chaque redimensionnement, puisque changer la taille du canvas vide le tampon WebGL : mesuré dans Firefox, l'image reste en place après un passage de 900 à 700 px de large. Une variante plus ancienne de ces caustiques existe aussi dans la catégorie.

Accessibilité

  • Mouvement réduit : sous prefers-reduced-motion, le script dessine une seule image (temps 8) et ne lance pas la boucle — mesuré, l'image ne change plus. Les caustiques restent visibles, figées, même après un redimensionnement de la fenêtre : resize() redessine alors l'image fixe.
  • Transparence réduite et absence de flou : le script pose .gc-solid quand prefers-reduced-transparency: reduce répond ou quand ni backdrop-filter ni sa forme préfixée ne sont connus. Mesuré sous émulation dans Chromium : vitre pleine #08182a, caustiques baissées à 30 %. Firefox 153 et WebKit 26 ne connaissent pas encore ce réglage de transparence.
  • Contraste : c'est le point faible. Les filaments sont presque blancs et passent sous le texte. Sans les ombres portées du code, mesuré sur la vitre à six instants : 3,54:1 en valeur médiane, 1,31:1 quand un filament traverse. Les ombres (text-shadow noir à 45 et 60 %) sauvent la lecture d'un titre court ; pour un texte long ou petit, montez le voile de la vitre (premier arrêt du dégradé à 30 % de noir) ou augmentez --gc-blur à 14 px pour noyer les filaments.
  • Sémantique : le canvas est décoratif — ajoutez aria-hidden="true". La lumière qui ondule plein cadre peut gêner les personnes sensibles au mouvement même si elle est lente : le respect de prefers-reduced-motion est déjà dans le script.

Compatibilité navigateur

WebGL 1 + CSS (backdrop-filter) + 3,3 Ko de JavaScript, aucune dépendance. WebGL 1 existe dans tous les navigateurs actuels, y compris Safari 8 et plus. Mesuré dans Firefox 153 et dans Chromium 151 avec la carte graphique (Metal) : caustiques complètes. Les machines sans accélération reçoivent un rendu logiciel ; mesuré en forçant le moteur logiciel ancien de Chromium dans un outil de capture, le canvas sortait parfois blanc ou vide d'une prise à l'autre — c'est ce moteur de test, pas un navigateur d'acheteur, mais c'est la raison du repli. Le shader demande la précision haute (highp) : un appareil qui ne l'a pas fait échouer la compilation, et le script bascule sur le dégradé. La vitre floute dans les trois moteurs (capture d'écran réelle pour Firefox et WebKit, dont les captures automatiques n'affichent jamais backdrop-filter).

Chrome 76+✓ Complet
Firefox 103+✓ Complet
Safari 13+✓ Complet (préfixe -webkit-)
Edge 79+✓ Complet
Mobile iOS 13+✓ Complet
Android Chrome 76+✓ Complet (dégradé sur appareil sans précision haute)

Sans WebGL ou si le shader ne compile pas, la scène reçoit .gc-nogl : canvas masqué, dégradé radial du bleu #0a6f8c au bleu nuit, vitre et texte intacts. La seconde couche de ce fond, des rayons en dégradé conique, est déclarée sous le dégradé radial opaque et ne se voit pas : placez-la en premier si vous voulez les rayons. Sans backdrop-filter, .gc-solid rend la vitre pleine. Sans JavaScript, le canvas reste vide sur le fond #04101c.

Le code

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

index.html — structure
<div class="demo-preview">
  <div class="gc-scene">
    <canvas class="gc-canvas" data-caustics></canvas>
    <div class="gc-glass">
      <h3>…</h3>
      <p>…</p>
    </div>
  </div>
</div>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Glass Caustics (WebGL), prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

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

Option / propriétéDéfautEffet
Vitesse (JS — var speed = 1) 1 (le shader avance à 0,4 × les secondes) 0,5 pour une eau calme de bassin, 2 pour une eau agitée. Le temps de l'image fixe sous mouvement réduit est 8 (render(8.0)).
Couleur de l'eau (shader — vec3(0.04, 0.32, 0.52)) bleu piscine Rouge, vert, bleu de 0 à 1 : vec3(0.02, 0.35, 0.30) pour un lagon vert, vec3(0.02, 0.08, 0.20) pour une eau de nuit.
Finesse des filaments (shader — pow(abs(c), 8.0)) 8 4 donne des nappes de lumière larges, 12 des fils très fins et plus rares.
Taille des cellules (shader — uv * 6.28318) une tuile de caustiques par scène, étirée au format de la scène Multipliez par 2 (uv * 12.566) pour des cellules deux fois plus petites. Pour des cellules rondes quel que soit le format, divisez par la hauteur seule : gl_FragCoord.xy / u_res.y.
Flou de la vitre (CSS — --gc-blur) 7px 14 px noie les filaments derrière le texte (meilleur contraste), 3 px les laisse presque nets.
Fond de repli (CSS — .gc-scene.gc-nogl) dégradé radial bleu (rayons coniques masqués dessous) Mettez une image de piscine en url(…) center / cover : c'est elle que verront les appareils sans WebGL.
Netteté (JS — Math.min(window.devicePixelRatio || 1, 2)) densité de l'écran, plafonnée à 2 Plafonnez à 1 sur une grande scène pour diviser par quatre le nombre de pixels calculés sur écran Retina ; le flou de la vitre masque la perte de netteté.

FAQ

Il calcule chaque pixel à chaque image : sur une scène de 1 280 × 800 px à densité 2, cela fait 4 millions de pixels, cinq itérations chacun, soixante fois par seconde. Une carte graphique récente le fait sans peine ; un ordinateur portable ancien chauffe. La boucle tourne aussi quand la scène est hors de l'écran. Deux leviers : plafonner la densité à 1, et suspendre la boucle avec un IntersectionObserver quand la scène sort de l'écran.
Le script tente getContext('webgl') puis experimental-webgl ; si aucun ne répond, ou si un des deux shaders ne compile pas, ou si le programme ne se lie pas, il pose .gc-nogl sur la scène et s'arrête. Mesuré en retirant WebGL au navigateur : canvas masqué, dégradé radial bleu à la place, vitre et texte intacts, aucune erreur. Le contexte perdu en cours de route (onglet en veille longue sur mobile) n'est pas géré : le canvas reste figé sur sa dernière image.
Oui : le script parcourt tous les .gc-canvas et crée un contexte WebGL par canvas, chacun avec sa boucle. Les navigateurs limitent le nombre de contextes WebGL actifs (autour de seize) : au-delà, les plus anciens sont perdus. Pour une grille de cartes, préférez un seul canvas derrière toute la grille.