The Future’s So Bright

We Gotta Wear Shade(r)s

Un seul PNG, un seul fragment shader, dix-huit uniforms.
Déplacez n’importe quel curseur et regardez le JavaScript vanille se réécrire.

Démo — WebGL2 + @paper-design/shaders

Heatmap : une image fixe devenue chaleur


Le shader heatmap de Paper prend une image fixe et la lit comme une source de chaleur. Des vagues de couleur montent à travers la silhouette, débordent de ses contours et se logent dans son intérieur. L’image source utilisée ici est un simple mockup produit — rien n’y est animé. Chaque image du mouvement est de l’arithmétique dans le fragment shader, pilotée par les uniforms ci-dessous.

Heatmap n’est qu’un shader parmi les vingt-neuf de la bibliothèque, et c’est justement celui qui accepte une image. Tous les autres génèrent leur contenu à partir de rien : dégradés maillés et radiaux, metaballs, bruits de Voronoï, simplex et Perlin, anneaux de fumée, rayons divins, tourbillons, spirales, vagues, distorsions, tramage et similigravure, métal liquide, verre cannelé, eau et texture papier. Vous pouvez les parcourir en direct sur shaders.paper.design , où chacun dispose du même panneau de contrôles et vous remet son code. Les sources, le GLSL et les liaisons React sont sur github.com/paper-design/shaders sous licence Apache-2.0. Tous se montent exactement comme le fait cette page — changez le fragment shader, changez les uniforms.

Préréglages
heatmap.js — généré en direct
Compilation…
Chaleur
Cadrage
Couleurs (dégradé, du plus froid)
#000000
7 / 10

Sous le capot

Trois flous rangés dans une seule texture


Un GPU ne peut pas se permettre un flou large par pixel et par image, alors le travail se fait une seule fois, sur le CPU, avant tout rendu. toProcessedHeatmap() charge le PNG dans un canvas 2D, l’entoure d’une marge, le convertit en niveaux de gris, puis applique trois flous de rayons différents et range chaque résultat dans un canal de couleur distinct :

  • R — un flou serré de 5px : le contour, le tracé net de la forme.
  • V — un flou de 150px : le large halo sur lequel s’appuie la lueur externe.
  • B — un flou de 18px : le remplissage doux de l’intérieur.

Le shader échantillonne ensuite cette texture unique et lit chaque canal comme un champ de distance séparé. u_contour, u_outerGlow et u_innerGlow ne font que doser la part de chaque canal mélangée dans la valeur de chaleur — laquelle sert finalement de position le long de votre dégradé de couleurs. Les pixels sombres de l’image d’origine sont lus comme les plus chauds : voilà pourquoi le corps du téléphone s’illumine tandis que l’écran blanc reste froid.

heatmap.frag — extrait
// une texture, trois champs
float shape     = img[0];
float outerBlur = 1. - mix(1., img[1], shape);
float innerBlur = mix(img[1], 0., shape);
float contour   = mix(img[2], 0., shape);

// vos curseurs pondèrent chacun d'eux
inner *= mix(0., 2., u_innerGlow);
inner += (u_contour * 2.) * contour;
outer *= mix(0., 5., pow(u_outerGlow, 2.));

// la chaleur devient une position
float heat  = clamp(inner + outer, 0., 1.);
float mixer = heat * u_colorsCount;

Envie que votre visuel produit bouge comme ceci ? Nous intégrons des shaders dans de vrais sites.