Niveau 3

Creative Coding — Niveau 3 : Avancé

Suivre ce cours — GRATUITFormation encadrée — PAYANTEn accès libre : lecture + exercices. Pour un accompagnement (atelier / masterclass), passez au format encadré.
Résumé EN (abstract): This advanced creative coding course takes designers and developers to production-level skills for exhibition-grade generative works. Students write GLSL shaders (fragment and vertex), build real-time systems in TouchDesigner, integrate complex simulations (cellular automata, evolutionary algorithms, reaction-diffusion), and apply performance optimization. The capstone is an exhibition-ready generative installation — interactive or autonomous — tested and documented. Outline: GLSL shaders (fragment) → WebGL in p5.js → TouchDesigner node architecture → Advanced audio-reactive systems → Cellular automata & reaction-diffusion → Evolutionary & generative systems → Performance optimization → Exhibition work.

Objectifs d'apprentissage

À la fin de ce cours, l'étudiant·e sera capable de :

  1. Écrire (Bloom : creating) un fragment shader GLSL produisant un effet visuel intentionnel.
  2. Intégrer (applying) des shaders dans un sketch p5.js via WEBGL et dans Shadertoy.
  3. Construire (creating) un réseau node-based dans TouchDesigner pour une installation temps réel.
  4. Implémenter (applying) une simulation de réaction-diffusion ou un automate cellulaire exposable.
  5. Optimiser (evaluating/applying) un sketch pour maintenir 60 fps sur du matériel d'exposition standard.
  6. Produire (creating) une œuvre de niveau exposition documentée avec fiche technique + intention artistique.

Module 1 — Fragment shaders GLSL (2.5h)

Concept

Un shader est un programme exécuté sur le GPU pour chaque pixel (fragment shader) ou chaque sommet de mesh (vertex shader). Infiniment plus rapides que le CPU pour les opérations visuelles — ils calculent des millions de pixels en parallèle.

Structure d'un fragment shader minimal : `glsl // Fragment shader GLSL precision mediump float;

uniform vec2 u_resolution; // taille du canvas en pixels uniform float u_time; // temps en secondes

void main() { // gl_FragCoord = position du pixel courant vec2 uv = gl_FragCoord.xy / u_resolution; // uv.x = 0 (gauche) → 1 (droite), uv.y = 0 (bas) → 1 (haut)

// Couleur : gradient horizontal vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time)); gl_FragColor = vec4(color, 1.0); } `

Fonctions GLSL fondamentales :

FonctionDescription
sin(x), cos(x)Oscillation — même sémantique qu'en JS
abs(x)Valeur absolue
fract(x)Partie fractionnaire — fract(3.7) = 0.7
floor(x)Partie entière
mod(x, y)Modulo
step(edge, x)0 si x < edge, 1 sinon
smoothstep(e0, e1, x)Interpolation douce entre 0 et 1
mix(a, b, t)Interpolation linéaire entre a et b
length(v)Longueur d'un vecteur
dot(a, b)Produit scalaire
normalize(v)Vecteur unitaire

Ressource indispensable :

Gonzalez Vivo, P., & Lowe, J. The Book of Shaders. https://thebookofshaders.com

Lab 1.1 — Shader dans Shadertoy

Étapes :

  1. Ouvrir https://shadertoy.com → "New Shader"
  2. Reproduire le gradient minimal ci-dessus (adapter les noms de variables Shadertoy : iResolution, iTime)
  3. Ajouter : un dégradé radial (length(uv - 0.5))
  4. Ajouter : une animation sin(iTime) sur la couleur
  5. Publier le shader avec un titre descriptif + lien vers le sketch

Module 2 — Shaders dans p5.js (WebGL mode) (2.5h)

Pièce interactiveData Rug 3DOuvrir ↗

Concept

p5.js peut utiliser le GPU en mode WEBGL. Les shaders s'écrivent en GLSL et s'appliquent à un plan (createGraphics en WEBGL).

`javascript let shaderProg;

function preload() { shaderProg = loadShader('vert.glsl', 'frag.glsl'); }

function setup() { createCanvas(800, 800, WEBGL); // WEBGL = mode GPU }

function draw() { shader(shaderProg); // Passer les uniforms au shader shaderProg.setUniform('u_resolution', [width, height]); shaderProg.setUniform('u_time', millis() / 1000.0); shaderProg.setUniform('u_mouse', [mouseX, mouseY]); // Dessiner le plan sur lequel le shader s'applique rect(-width/2, -height/2, width, height); resetShader(); } `

Vertex shader minimal (requis en WEBGL) : `glsl // vert.glsl attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord;

void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * 2.0 - 1.0; gl_Position = positionVec4; } `

Combiner shaders et p5.js :

Lab 2.1 — Shader + p5.js interaction

Étapes :

  1. Créer les fichiers vert.glsl et frag.glsl
  2. Fragment shader : dessiner des cercles Voronoi ou un motif répété
  3. Passer la position souris comme uniform → le pattern réagit à la souris
  4. Bonus : passer une texture p5.js (createGraphics → shader)

Module 3 — TouchDesigner : architecture temps réel (2.5h)

Concept

TouchDesigner est un environnement de programmation visuelle node-based développé par Derivative (Toronto, 2000). Il est la référence pour les installations, mapping vidéo, VJing et performances audiovisuelles.

Documentation : https://docs.derivative.ca · Téléchargement gratuit (usage non-commercial) : https://derivative.ca/download

Quatre familles d'opérateurs (nodes) :

FamilleSuffixeUsage
TOP (Texture Operators)moviefilein, noise, level, blur, compositeImage/vidéo 2D
CHOP (Channel Operators)audioin, math, lag, lfo, nullSignaux continus (audio, données)
SOP (Surface Operators)box, sphere, noise, transformGéométrie 3D
DAT (Data Operators)text, table, script, nullDonnées tabulaires, scripts

Flux de données dans un réseau TD : [audioin CHOP] → [analyze CHOP] → [math CHOP] → [null CHOP] ↓ [noise TOP] → [level TOP] → [transform TOP] ← amplitude channel ↓ [out TOP] → Sortie finale

Lab 3.1 — Installation audio-réactive dans TouchDesigner

Étapes :

  1. Ouvrir TouchDesigner → nouveau projet
  2. Créer un moviefilein TOP ou noise TOP comme source visuelle
  3. Connecter un audioin CHOPanalyze CHOP (amplitude) → null CHOP
  4. Connecter l'amplitude à un paramètre visuel (ex. level du level TOP)
  5. Ajouter un blur TOP modulé par les basses fréquences
  6. Exporter vers un écran secondaire ou une fenêtre de projection

Module 4 — Audio-réactif avancé : fréquences et rythme (2.5h)

Concept

Au-delà de l'amplitude globale, l'audio-réactif avancé discrimine les fréquences (basses, médiums, aigus) et détecte les temps rythmiques (beat detection).

FFT en p5.js — bandes de fréquences : `javascript let fft;

function setup() { fft = new p5.FFT(0.8, 1024); mic = new p5.AudioIn(); mic.start(); fft.setInput(mic); }

function draw() { let bass = fft.getEnergy('bass'); // 20–140 Hz let lowMid = fft.getEnergy('lowMid'); // 140–400 Hz let mid = fft.getEnergy('mid'); // 400–2600 Hz let highMid = fft.getEnergy('highMid'); // 2600–5200 Hz let treble = fft.getEnergy('treble'); // 5200–14000 Hz

// Mapping sur des paramètres visuels distincts let tailleFormes = map(bass, 0, 255, 10, 200); let vitesseFond = map(highMid, 0, 255, 0, 5); } `

Beat detection simplifié : `javascript let prevAmplitude = 0;

function draw() { let amp = amplitude.getLevel(); // Peak detection : hausse soudaine > seuil = beat if (amp > prevAmplitude + 0.15 && amp > 0.2) { onBeat(); } prevAmplitude = lerp(prevAmplitude, amp, 0.1); // suivi lisse }

function onBeat() { // flash, spawn de particules, changement de couleur... } `

Lab 4.1 — Visualiseur fréquences multiples

Étapes :

  1. Diviser le canvas en 5 zones (une par bande de fréquence)
  2. Chaque zone réagit à sa fréquence (basses → grandes formes, aigus → détails)
  3. Ajouter une détection de beat → flash ou explosion de particules
  4. Tester avec différents genres musicaux — est-ce que le visuel "colle" à la musique ?

Module 5 — Systèmes complexes : réaction-diffusion (2.5h)

Concept

La réaction-diffusion est un modèle mathématique décrivant comment deux substances chimiques interagissent et diffusent dans l'espace. Proposé par Alan Turing (1952) pour expliquer les motifs biologiques (léopard, zèbre, coraux), il génère des textures organiques d'une grande richesse.

Turing, A. M. (1952). The Chemical Basis of Morphogenesis. Philosophical Transactions of the Royal Society B, 237(641), 37–72. https://doi.org/10.1098/rstb.1952.0012

Deux substances, A et B :

Implémentation GPU (shader) — la plus performante : `glsl // Fragment shader reaction-diffusion (Gray-Scott) uniform sampler2D u_prevState; // état de la frame précédente uniform vec2 u_resolution; uniform float dA; // taux de diffusion de A (typ. 1.0) uniform float dB; // taux de diffusion de B (typ. 0.5) uniform float feed; // taux d'alimentation en A uniform float k; // taux de mort de B

void main() { vec2 uv = gl_FragCoord.xy / u_resolution; vec2 texel = 1.0 / u_resolution;

// État courant vec2 state = texture2D(u_prevState, uv).rg; float a = state.r; float b = state.g;

// Laplacien (diffusion par convolution 3×3) vec2 sum = vec2(0.0); sum += texture2D(u_prevState, uv + vec2(-texel.x, 0)).rg; sum += texture2D(u_prevState, uv + vec2( texel.x, 0)).rg; sum += texture2D(u_prevState, uv + vec2(0, -texel.y)).rg; sum += texture2D(u_prevState, uv + vec2(0, texel.y)).rg; sum -= 4.0 * state; // centre du Laplacien

// Gray-Scott equations float reaction = a b b; float newA = a + (dA sum.r - reaction + feed (1.0 - a)); float newB = b + (dB sum.g + reaction - (k + feed) b);

gl_FragColor = vec4(clamp(newA, 0.0, 1.0), clamp(newB, 0.0, 1.0), 0.0, 1.0); } `

Lab 5.1 — Simulation réaction-diffusion

Étapes :

  1. Implémenter le shader Gray-Scott ci-dessus dans Shadertoy ou p5.js WEBGL
  2. Commencer avec une tache de B au centre (seed), laisser évoluer 200 frames
  3. Faire varier k et feed — cartographier la "phase diagram" des motifs (spots, spirales, labyrinthes)
  4. Ajouter l'interactivité : clic souris → injecter de B à la position

Module 6 — Algorithmes évolutifs et agents (2.5h)

Concept

Les algorithmes génétiques s'inspirent de la sélection naturelle pour optimiser une solution : une population d'individus (solutions candidates) évolue par sélection, croisement et mutation vers des configurations qui maximisent une fonction de fitness.

Architecture en creative coding :

  1. Population initiale : N "organismes" avec des gènes (paramètres visuels)
  2. Évaluation : calculer le "fitness" de chaque organisme (distance à une cible, complexité, esthétique)
  3. Sélection : les meilleurs survivent
  4. Reproduction : croisement + mutation des gènes
  5. Nouvelle génération → retour à 2

Systèmes multi-agents (Boids — Craig Reynolds, 1986) : Trois règles simples génèrent un comportement émergent de groupe (murmuration d'étourneaux) :

Reynolds, C. W. (1987). Flocks, herds and schools: A distributed behavioral model. SIGGRAPH '87. https://doi.org/10.1145/37401.37406

`javascript class Boid { constructor() { this.pos = createVector(random(width), random(height)); this.vel = p5.Vector.random2D().setMag(2); this.acc = createVector(0, 0); }

flock(voisins) { let sep = this.separation(voisins).mult(1.5); let ali = this.alignment(voisins); let coh = this.cohesion(voisins); this.acc.add(sep).add(ali).add(coh); }

update() { this.vel.add(this.acc).limit(3); this.pos.add(this.vel); this.acc.mult(0); this.pos.x = (this.pos.x + width) % width; // wrap edges this.pos.y = (this.pos.y + height) % height; } //... méthodes separation, alignment, cohesion } `

Lab 6.1 — Simulation boids

Étapes :

  1. Implémenter la classe Boid avec les 3 règles
  2. Population de 200 boids, visualisation simple (triangle orienté selon vitesse)
  3. Paramétrer les 3 forces (sliders) — trouver les valeurs qui créent des comportements intéressants
  4. Enregistrer 3 seeds de paramètres produisant 3 comportements distincts (nuée, explosion, tourbillon)
  5. Ajouter un prédateur (attraceur/répulseur selon la distance)

Module 7 — Performance et optimisation (2.5h)

Concept

Une œuvre exposée doit tourner à 60 fps pendant des heures sans dégradation. L'optimisation est une discipline créative à part entière.

Règles d'or :

Techniques concrètes p5.js : `javascript // ✗ Mauvais : createVector dans draw() à chaque frame function draw() { let v = createVector(mouseX, mouseY); // allocation à chaque frame }

// ✓ Bon : déclarer une fois, modifier let mouseVec; function setup() { mouseVec = createVector(0, 0); } function draw() { mouseVec.set(mouseX, mouseY); } `

`javascript // ✗ Mauvais : redessiner une texture statique function draw() { for (let i = 0; i < 10000; i++) ellipse(random(width), random(height), 5); }

// ✓ Bon : pré-calculer dans un buffer hors-écran let buffer; function setup() { buffer = createGraphics(width, height); for (let i = 0; i < 10000; i++) buffer.ellipse(...); } function draw() { image(buffer, 0, 0); // 1 seule opération GPU } `

Profiling TouchDesigner : Performance Monitor (F7) → identifier les TOPs les plus coûteux → réduire la résolution des buffers intermédiaires.

Lab 7.1 — Audit et optimisation

Étapes :

  1. Reprendre votre projet de simulation le plus lourd (boids ou réaction-diffusion)
  2. Mesurer le framerate de base
  3. Identifier les 3 opérations les plus coûtées (Profiler Chrome ou performance.now())
  4. Appliquer 2 optimisations concrètes
  5. Mesurer le gain : documenter avant/après

Module 8 — Œuvre exposable : production et scénographie (2.5h)

Concept

Passer du sketch au dispositif exposé requiert des compétences qui vont au-delà du code.

Checklist production exposition :

Technique :

Scénographie :

Documentation :

`javascript // Exemple : setup exposition function setup() { createCanvas(displayWidth, displayHeight, WEBGL); // fullscreen frameRate(60); noCursor(); randomSeed(SEED); noiseSeed(SEED); }

let idleTimer = 0; function draw() { idleTimer++; if (idleTimer > 60 60 10) { // reset après 10 min d'inactivité idleTimer = 0; reset(); } }

function mouseMoved() { idleTimer = 0; } `

Lab 8.1 — Préparation exposition

Étapes :

  1. Choisir votre meilleur sketch du cours
  2. Appliquer la checklist production
  3. Rédiger la fiche technique (1 page)
  4. Rédiger la note d'intention (1 page) — pas de description technique, seulement l'intention
  5. Simuler 15 minutes d'exposition : l'œuvre tourne-t-elle sans intervention ?

Projet fil rouge — "Œuvre de niveau exposition"

Brief

Créer une œuvre générative de niveau exposition — un travail qui pourrait être présenté dans un festival d'art numérique, une galerie ou un espace culturel. L'œuvre doit être à la fois techniquement solide et artistiquement cohérente.

Contraintes

Livrables

  1. Code source (p5.js + shaders et/ou fichier.toe TouchDesigner)
  2. Export vidéo de 2–5 min de l'œuvre en fonctionnement
  3. Fiche technique : hardware, logiciel, résolution, fps, espace requis
  4. Note d'intention (1 page) : concept, références artistiques, positionnement
  5. README opérateur (≤ 1 page)
  6. Présentation (10 min) : contexte artistique + démo live + réflexion sur le processus

Rubrique d'évaluation

CritèreInsuffisant (1)Satisfaisant (2)Bon (3)Excellent (4)
Maîtrise shaderPas de shader ou shader copié sans compréhensionShader fonctionnel, 1 effetShader intentionnel, paramétréShader sophistiqué, combiné avec d'autres systèmes
Complexité du systèmeSketch de base1 système avancé (flocking, RD, TD)2 systèmes combinésSystèmes qui s'enrichissent mutuellement
Qualité temps réel< 30 fps ou crashes60 fps stable 15 min60 fps stable 1h, pas de leak mémoireOptimisé, reset auto, production-ready
Intention artistiqueAbsent ou décoratifIntention présenteCohérence conception/intentionDialogue fort technique/sens, références citées
DocumentationAbsenteFiche technique seuleFiche + note intention + READMEDossier complet, exportable tel quel vers un commissaire

Lectures & ressources


Continuer : Hub — Creative CodingProjet d'exposition ? Prendre rendez-vous — 30 min, gratuit

Formation sur mesure

Workshop intensif (1–2 j) pour écoles, studios, musées — théorie condensée, labs guidés, accompagnement projet.

Prendre rendez-vous (30 min, gratuit) →