Communitygithub.com

pisakhov/x-motion-sumi

À utiliser avec le skill cœur x-motion lorsqu'un film doit ressembler et sonner comme une peinture à l'encre en mouvement (papier, encre de carbone, eau, brume, souffle, un seul accent vermillon).

Qu'est-ce que x-motion-sumi ?

X Motion : Sumi est un thème visuel et sonore qui traduit la logique matérielle de la peinture à l'encre de Chine (sumi-e) dans le temps et l'espace d'une animation. Il est conçu comme une extension du skill `x-motion` de Claude Code, qui gère les étapes de développement (brief, thèse, storyboard, boucle de critique). Ce thème impose des contraintes précises : un seul geste par scène, des plages d'absence (60 à 80 % de vide), une palette restreinte (noir de carbone, gris dilués, papier chaud, un seul accent vermillon), des recettes de rendu (composition Beer-Lambert pour l'encre, champs de curl pour l'encre dans l'eau, SDF pour les petits éléments comme un oiseau ou un sceau), et une conception sonore minimale (souffle, goutte d'eau, flûte, corde pincée, gong grave) avec mixage bit-exact. Le tout est pensé pour un rendu déterministe, reproductible et performant sur WebGL logiciel, avec des checklists précises pour le débogage et la cohérence temporelle.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pisakhov/x-motion/tree/HEAD/skills/x-motion-sumi

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

X Motion : Sumi

Encre, papier, souffle. Ce thème traduit la logique matérielle de la peinture à l'encre de Chine en temps : encre de carbone diluée dans une multitude de gris, papier fibreux chaud, bords humides qui baveront, brosses sèches qui sautent, et le vide comme matière principale. Il étend x-motion ; exécutez cette méthode d'abord (boucle brief, thèse, storyboard, critique) et utilisez ce fichier pour la direction artistique et les recettes.

Thèse visuelle

Faire en sorte qu'un geste à la fois paraisse inévitable grâce à une encre qui se comporte comme de l'encre (diffusion, baver, s'assécher) sur un grand espace de papier silencieux, afin que le spectateur ressente l'immobilité avant et après le moment décisif.

  • Un geste par temps. Une goutte, un trait, une crête, un oiseau. Jamais deux événements focaux en même temps.
  • Le vide porte du poids. 60 à 80 % du cadre reste du papier non touché, brume ou eau. L'espace vide est composé, pas un reste.
  • Vérité matérielle plutôt qu'illustration. Le rendu vient de la simulation de la façon dont l'encre absorbe la lumière et le papier absorbe l'encre, pas de contours ou de remplissages plats.
  • Respect et originalité. Pas de calligraphie, pas de pseudo-écriture, pas de caractères réels ou faux, pas de costumes, temples, lanternes, pas d'emblème soleil-rouge-et-grue. Les sceaux sont des marques géométriques abstraites.

Palette

Travaillez en lumière linéaire ; ce sont des ancres hex sRGB.

RôleHexNotes
Papier (éclairé)#f1e9d8Washi chaud ; jamais blanc pur
Papier (ombre)#e0d3baVignette, pli de lumière, marbrure
Papier (profond)#cbbb9cUniquement aux bords du cadre ou dans les ombres de brume
Encre, plein#14120fCarbone chaud ; jamais #000
Encre, lavis moyen#5d5b57Légèrement froid contre le papier chaud
Encre, lavis pâle#a9a69fMontagnes lointaines, nuages diffus
Vermillon#c8372dLa seule couleur. Au maximum une marque, au maximum environ 1,5 % des pixels
Vermillon dans la brume#d7735fVermillon mélangé vers le papier par l'atmosphère

L'encre n'est pas une couleur que l'on applique ; c'est une absorption. Composez avec Beer-Lambert : rgb = papier * exp(-densité * absorb), avec absorb légèrement plus grand dans le bleu (par exemple vec3(1.0, 1.04, 1.1)) de sorte que les lavis fins paraissent légèrement froids et l'encre dense lise un noir chaud.

Lumière et matière

  • Le papier est éclairé doucement d'un côté : marbrure basse fréquence (plus ou moins 3 %), fibres de kozo visibles (longs filaments translucides, larges de 1 à 2 px), et une dent fine sur laquelle l'encre sèche s'accroche. Cuisez-le une fois ; il est statique.
  • L'encre humide a un bord plus foncé là où le pigment a migré vers le bord, un baver plumeux dans les fibres, et un léger reflet qui s'estompe en séchant.
  • L'encre sèche se brise en bandes de poils parallèles et saute les points bas du papier (seuillez la dent).
  • L'encre dans l'eau est un volume rétro-éclairé : noyaux denses, nappes laminaires vues de côté sous forme de fines lignes sombres, et un voile doux autour de tout.
  • L'atmosphère est de la couleur du papier. La distance et la brume remontent les valeurs vers le papier, jamais vers le bleu ou le blanc.

Composition

  • Placez le sujet sur un tiers asymétrique ; laissez une grande zone calme (en haut ou sur un côté) comme contrepoids.
  • Gardez une hiérarchie de valeurs claire : un presque noir, quelques gris moyens, tout le reste papier.
  • Les bords du cadre restent calmes. Une vignette douce vers #e0d3ba retient l'œil à l'intérieur.
  • L'accent vermillon se situe loin de la masse principale, petit, bas et tardif. Il répond au geste ; il ne rivalise pas.
  • Vérifiez la vignette : la silhouette de l'unique geste doit être lisible à 320 px de large.

Vocabulaire du mouvement et timing

VerbeCaractèreCourbe typique
Respirer (tenir)Rien ne bouge sauf la lumière ou la brume0,8 à 1,5 s d'immobilité avant le geste
Tomber / frapperDécisif, rapide, pas de dépassementease-in, 0,3 à 0,6 s
DessinerLa brosse accélère puis relâchepression lente, milieu rapide, levée légère
Fleurir / diffuserRapide puis ralentissement exponentiel1 - exp(-t / tau), tau 1 à 2 s
Baver / s'installerPetite croissance après l'événementsqrt du temps depuis le contact, plafonné
DériverCaméra ou brume, constant et lentlinéaire ou ease très long, sous 2 % du cadre par seconde
DissoudreLe contraste chute, les bords s'élargissent2 à 3 s à la fin, jamais une coupe au noir
  • Le rythme est un souffle : immobilité, un événement décisif, un long établissement. Ne remplissez pas l'établissement de nouveaux événements.
  • La caméra ne bouge que pour suivre le geste (s'enfonçant avec l'encre, glissant dans la brume). Les push-ins restent sous 8 %.
  • Les champs de graines et de bruit évoluent lentement : décalages de champ sous 0,05 unité par seconde, sinon ils lisent comme de l'ébullition.

Palette sonore et mixage

Le son est aussi épars que l'image. Le silence est un indice.

  • Matières : souffle (bruit filtré passe-bande avec un balayage lent du filtre), eau (un chirp sinusoïdal montant pour une goutte, bulles étouffées), papier et brosse (bruit passe-bande avec de rares clics granuleux qui augmentent à mesure que la brosse s'assèche), vent (deux lits de bruit décorrélés avec des courbes de rafale ensemencées).
  • Instruments : flûte à bec soufflée (sinus plus un peu de 2e et 3e harmonique, hauteur relevée depuis le bas, bruit de souffle verrouillé en bande sur la note), corde pincée (Karplus-Strong rendu dans un buffer, glissando de hauteur optionnel après le pincement), gong grave (partiels inharmoniques avec paires battantes, partiels graves les plus longs).
  • Harmonie : quelques notes avec des intervalles ouverts (quartes, quintes, neuvièmes). Évitez les riffs pentatoniques « orientaux » de stock ; laissez les notes uniques parler.
  • Espace : une longue réverbération synthétique (3 à 5 s, queue foncée, 20 à 40 ms de prédélai). Instruments humides, textures plus sèches.
  • Sync : le son de la goutte rencontre l'impact ; le souffle précède un geste de 0,3 à 0,8 s ; le gong rencontre le sceau ; les notes mélodiques suivent les événements visuels de 0,1 à 0,3 s.
  • Cibles : environ -18 LUFS intégré, pic vrai à ou en dessous de -1,5 dBFS, queue sous -60 dBFS à la dernière image, pas de clics (chaque changement de gain s'adoucit sur au moins 5 ms).

Recettes techniques

1. Cuire le bruit et le papier une fois. Téléchargez une texture tuilable RGBA16F de 256x256 : RG contient un champ de curl (le gradient rotatif d'un bruit de gradient périodique), BA contient deux bruits indépendants. Cuisez le papier avec JS ensemencé (grain plus traits de fibre Canvas 2D) dans une texture RGBA8 avec mipmaps ; échantillonnez-la à chaque image au lieu de calculer fbm par pixel.

2. Composition d'encre (lumière linéaire).

vec3 lin(vec3 c){ return pow(c, vec3(2.2)); }
vec3 inkOver(vec3 paperLin, float density){
  return paperLin * exp(-density * vec3(3.4, 3.55, 3.75));
}

3. Encre dans l'eau par advection inverse. Ne simulez pas. Décrivez l'encre comme quelques primitives analytiques (goutte, tige, anneau vortex, lobes pétales) dont les positions sont des fonctions en forme fermée du temps, puis évaluez-les à une coordonnée déformée. La déformation est de quelques pas le long d'un champ de curl dont l'amplitude croît avec le temps depuis l'impact, ce qui étire les primitives en vrilles ondulantes.

vec2 q = p;
for (int i = 0; i < 4; i++) {
  vec2 c = texture(uNoise, q * freq[i] + drift * t).rg;   // champ de curl
  q += amp[i] * growth * c;
}
float dens = primitives(q, t);              // noyaux gaussiens + voile large
dens += sheet(q) * veil;                     // bruit cranté : nappes de côté
  • Gardez la déformation basse fréquence (échelle de base 1 à 3 cycles par hauteur de cadre, une faible troisième octave). Une déformation haute fréquence transforme l'encre en vers qui se tortillent.
  • L'enroulement vient d'un tourbillon local (faites tourner q autour de chaque noyau vortex par un angle qui décroît comme une gaussienne), pas de plus de bruit.
  • Les pétales, lobes et voiles ont besoin de bords doux (gaussien, largeur 0,2 à 0,3 du rayon). De fines lignes de contour sombres à l'intérieur d'une forme lisent comme une carte topographique.
  • Jugez la silhouette, pas le détail : une forme radiale à cinq lobes vue de face lit comme une méduse ou une étoile de mer. Inclinez-la (projetez des lobes 3D pour une caméra regardant vers le bas à environ 30 degrés) avant qu'elle ne lise comme une fleur.
  • Une traînée qui reste fine, nette et opaque lit comme une corde ou une tige. Traitez-la comme un sillage : élargissez-la, adoucissez-la, enroulez-la et estompez-la en environ une seconde, le haut en premier, pour que la forme se tienne seule.
  • Absorbez les noyaux d'encre avec un coefficient chaud (plus de bleu que de rouge, par exemple vec3(3.2, 3.6, 4.2)) et les bords dilués avec un coefficient neutre. Alors les noyaux lisent comme du noir sumi, pas du gris plat.

4. Coup de pinceau comme un champ polaire. Pour un ensō, utilisez r(theta) = R + wobble(theta). Par pixel, prenez l'angle, convertissez-le en progression du trait u et la distance signée à travers le trait d / width(u). Révélez où u < brushHead(t). L'humidité, la largeur et la sécheresse sont des fonctions de u ; le baver est une fonction de t - timeTheBrushPassed(u).

float lanes = texture(uNoise, vec2(across * 5.0, u * 0.35)).b;   // bandes de poils
float dryInk = step(dryness(u), lanes * 0.6 + tooth * 0.5);         // saute les points bas du papier
float rim = smoothstep(0.75, 1.0, abs(across)) * wet(u);            // assombrissement du bord

5. Profondeur en couches pour les paysages. Chaque crête est un profil de hauteur 1D à la profondeur z. Par pixel, projetez sur le monde x, cherchez la hauteur, comparez avec l'écran y de cette hauteur sous perspective. L'encre est la plus forte à la ligne de crête et décroît vers le bas dans la brume. Composez loin vers proche, en mélangeant vers le papier par 1 - exp(-profondeur * k). Les nappes de brume se trouvent dans les vallées entre les crêtes et dérivent avec le temps. Estompez une crête lorsque la caméra s'apprête à la traverser.

  • Composez proche vers loin avec transmittance (acc += T * a * layer; T *= 1.0 - a;) et arrêtez une fois que T est presque nul. C'est exact, et cela réduit de moitié le coût car la couche inférieure s'arrête après une ou deux couches.
  • Calculez les lignes de crête avec un bruit de gradient 1D analytique (hash plus fondu quintique), pas des recherches de texture : les texels bilinéaires apparaissent comme des plis le long d'une longue crête.
  • L'atmosphère a besoin d'une courbe pentue (exp(-0.45 * profondeur)) avant que la portée la plus lointaine ne lise comme un fantôme pâle plutôt qu'un gris de plus.

6. Petites silhouettes (un oiseau, un sceau) en capsules et boîtes SDF à l'intérieur d'un test de boîte englobante, avec un bord anti-crénelé de 1,5 px. Animer les ailes avec une fonction de phase, pas avec de la physique.

7. Blocs de construction audio.

// Pincement Karplus-Strong avec glissando optionnel, rendu déterministe dans un buffer
for (let n = 0; n < len; n++) {
  const d = sr / freqAt(n) - 0.5, r = w - d;
  const a = read(r), b = read(r - 1);
  y = exc[n] + g * 0.5 * (a + b); write(y); out[n] = y;
}

Impulsion de réverbération : bruit stéréo ensemencé multiplié par exp(-t / decay) à travers un filtre passe-bas unipolaire dont la fréquence de coupure chute dans le temps. Chaîne de mastering : un compresseur doux (ratio 2 à 3), puis un compresseur rapide à ratio élevé comme limiteur, puis un gain de rattrapage mesuré, puis un fondu linéaire de master qui atteint zéro environ 0,15 s avant la fin pour que la queue de réverbération soit partie.

  • Mixage bit-exact. Chromium additionne les entrées d'un nœud dans un ordre non spécifié. L'addition flottante ne donne les mêmes bits que pour deux opérandes, et les compresseurs amplifient l'arrondi de 1e-7 en différences de niveau audibles entre les appels. Donnez à chaque point de mixage au plus deux entrées en chaînant des nœuds de gain :
function summer(ctx, target) {        // retourne add(node) ; chaque point de mixage reçoit <= 2 entrées
  let open = target, count = 0;
  return node => { if (count === 1) { const j = ctx.createGain(); j.connect(open); open = j; count = 0; } node.connect(open); count++; };
}
  • DynamicsCompressorNode applique son propre gain de rattrapage automatique, donc baisser le seuil rend le mixage plus fort. Réglez la puissance avec le gain de sortie à la place.
  • Vérifiez l'équilibre des stems : faites le rendu une fois sans la mélodie. Si le lit seul est à moins de 2 dB du mix complet, la mélodie est enterrée.

Liste de contrôle de rendu déterministe

  • renderFrame(t) définit chaque uniform à partir de t seul ; pas d'accumulation, de Date, performance.now ou Math.random.
  • Toute l'aléatoire vient d'un PRNG ensemencé (mulberry32) ou de hachages de texture cuits au chargement.
  • Le papier, le bruit et l'IR sont construits de manière synchrone au chargement et ne changent jamais.
  • Un défilement arrière donne des pixels identiques ; testez t = 0 après une image tardive.
  • Le coût par image mesuré à 1920x1080 en WebGL logiciel ; restez sous 1,5 s. Utilisez des boîtes englobantes pour les petits détails et gardez les boucles de déformation à quatre étapes.
  • Le grain est statique, sous 2 % ; pas de bruit plein écran par image.
  • Les lignes et filaments ont au moins un adoucissement doux de 1,5 px.
  • L'audio utilise des tampons de bruit ensemencés, et chaque point de mixage a au plus deux entrées ; deux appels doivent retourner des tampons identiques octet par octet.
  • Le mode prévisualisation boucle avec requestAnimationFrame ; le mode rendu ne dessine rien par lui-même.

Éviter

  • Papier blanc pur, encre noire pure, couleur saturée au-delà de la seule marque vermillon.
  • Traits ressemblant à de l'écriture, caractères, fausse calligraphie, signatures, accessoires culturels de stock.
  • Plusieurs gestes en compétition ; arrière-plans chargés ; encre qui bouge constamment à la même vitesse.
  • Lueur, flares, aberration chromatique, bokeh ; l'encre est mate.
  • Flou uniforme se faisant passer pour de la diffusion ; la vraie diffusion a à la fois des noyaux nets et des voiles doux.
  • Carillons éoliens, cloches à chaque coupe, nappes constantes, whooshes, riffs pentatoniques de stock.
  • Terminer sur une coupe au noir ; laissez l'image s'installer ou se dissoudre dans le papier ou le gris.

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills associés