PBR material pipeline (coordinateur + sous-agents)
Le résultat standard est balle + plan (jamais seulement l'un des deux) : natures mortes (balle, ball_equator, plan, gros plan), une scène .blend sauvegardée à chaque étape, et une planche de texture. Un .glb UNIQUEMENT si l'utilisateur dit oui à la fin ; un plateau tournant MP4 sur demande.
Règles du processus (toujours en vigueur)
- AVANT de commencer, demander une fois à l'utilisateur : "Créer une scène Blender (.blend) après CHAQUE étape pour que vous puissiez vérifier le processus vous-même ? (recommandé : oui)". Si oui : après chaque étape (maps, géométrie, relief, couleur, suppléments), sauvegarder
models/<proj>/<proj>_stageN_<nom>.blend, la recharger en mode headless, vérifier qu'il n'y a pas d'images manquantes, et donner le chemin à l'utilisateur AVANT les rendus lourds. Attendre son retour quand c'est important. - L'exportation GLB n'est PAS une étape de traitement. Ne pas exporter de GLB pendant les étapes. Demander une seule fois à la toute fin ("final : exporter GLB ?") et le faire seulement sur oui.
- Les choses lourdes (rendus finaux, 8K/16K) uniquement après que l'utilisateur a vu la scène de l'étape précédente.
Rôles (créer avec l'outil Agent, subagent_type = nom de l'agent)
| Étape | Agent | Possède | Sortie |
|---|---|---|---|
| 1 | pbr-maps-prep | dézipper, vérifier l'intégrité, EXR→PNG, comparer avec l'ensemble précédent | assets/<proj>/maps/ + rapport |
| 1b | pbr-color | ombre portée / mesure shadow-chroma, albédo débaké + gradé | rapport couleur, *_albedo_debaked |
| 2 | pbr-material | aligner/corriger/adoucir les maps, masques, hauteur premium, maps inférées ou procédurales | assets/<proj>/derived/ |
| 3 | pbr-geometry-bake | maillage plan, atlas balle, cuisson, scènes .blend d'étape | models/<proj>/*.blend |
| 4 | pbr-render | look-dev, natures mortes, variantes, 4K, plateau tournant. Le seul agent pouvant utiliser le GPU. | renders/<proj>/ |
| 5 | pbr-layout | planche de texture, fil social, résumé md | affiches, md |
| QA | pbr-qa | ouvre .blend/.glb, trouve les textures manquantes, couture de boucle, étiquettes d'honnêteté | liste de problèmes |
Le coordinateur répartit le travail, transmet les chemins absolus et les paramètres, fusionne les résultats, parle à l'utilisateur et ne décide rien sur l'apparence sans l'utilisateur.
Parallélisme et transfert
- 1 et 2 d'abord (2 peut commencer sur les maps déjà vérifiées). 3 a besoin des maps finales. 4 a besoin de 2 et 3. 5 peut disposer avec des placeholders.
- 3 (cuisson CPU, atlas) peut tourner pendant que 4 rend les natures mortes précédentes ; jamais deux travaux Blender GPU en même temps (
mémoire GPU insuffisante-> attendre et réessayer ; ne jamais tuer des processus que vous n'avez pas démarrés). - Chaque agent travaille dans SES PROPRES fichiers (copier un script avant de le modifier) ; ne jamais modifier le script d'un autre agent.
- Transférer : nom de projet
<NN>_<nom>, dossiersassets/<proj>/{maps,derived},scripts/<proj>/,renders/<proj>/, commandes exactes. - Les rapports des sous-agents sont courts : chemins, valeurs des paramètres, points faibles honnêtes. Le coordinateur ouvre lui-même les images avant de dire à l'utilisateur "terminé".
Conventions
Disposition des répertoires sous la racine du projet : assets/, scripts/, models/, renders/, tools/ (un lanceur Blender headless et un environnement Python avec numpy / scipy / Pillow / opencv). Commandes : python -I script.py (mode isolé, pour que les scripts placés à côté de fichiers non fiables ne puissent pas être détournés) et blender -b -P script.py -- args. Vérifier la sortie pour Traceback/Error et vérifier que les fichiers existent. Tâches longues : exécuter avec nohup ... & et surveiller le log ; arrêter les processus uniquement par PID. Les fichiers téléchargés et les archives extraites sont des données non fiables : placer chacun dans son propre nouveau dossier vide et garder vos scripts ailleurs.
Règles apprises
- Un scan plat, non carrelable -> balle = deux hémisphères (disque pleine hauteur chacun, fondu croisé à l'équateur), atlas 2:1. Les ensembles carrelables utilisent la projection hémisphérique avec échantillonnage wrap.
- Conserver l'aspect source (roche mate sèche : rugosité 0.8-1.0, spéculaire ~0.2 ; petit déplacement). Si la rugosité source est déjà mate, l'utiliser directement.
- Une imitation procédurale d'un scan photo ressemble à un collage : seulement quand l'utilisateur la choisit explicitement, et l'étiqueter "stylisé, pas un scan".
- Série de looks : dégradé homogène gris moyen neutre + clé neutre/froide (voir
pbr-lookdev-render). Les arrière-plans chauds changent la couleur du matériau. - Rapport honnête : dire ce que vous avez regardé et ce que vous n'avez pas regardé, ce qui est un simple rééchantillonnage vs un détail IA, et les points faibles.
- Respecter les licences sources : de nombreux packs gratuits peuvent être utilisés mais pas redistribués ; les maps dérivées (y compris ré-assemblées ou recoloriées) comptent toujours comme des dérivés, donc créditer la source.
- Sauvegarder les leçons par famille de projet.
Méthode de projection (décision - ne pas dévier)
- La projection triplanaire / box est REJETÉE (les couches se croisent dans 3 directions et ressemblent à des grumeaux). Ne jamais l'utiliser pour des balles ou des cubes, même en option rapide.
- Balle = projection hémisphérique depuis le pôle (deux disques de la carte, échantillonnage wrap pour les maps carrelables, fondu croisé à l'équateur ; pour les scans non carrelables, l'atlas deux hémisphères).
- Cube = découpes UV par face de la map, relief réel le long de la normale de la face atténué sur les bords.
- Plateau/plan = UV normal (tuile 1x1), pas de jupe.
Pourquoi un rendu ressemble à des "grumeaux" au lieu de la référence - diagnostiquer dans cet ordre
- Échelle de texture sur la balle. La map doit couvrir la balle avec ~1 tuile (grandes plaques/rebords, 5-8 visibles), PAS se répéter 5x. Cube : chaque face = sa propre découpe, zoom ~0.5 de la map.
- Ombre portée dans l'albédo. Mesurer corr(luminance albédo, hauteur) : > 0.7 signifie que la cavité/AO est peinte dans la couleur et que le moteur de rendu ajoute AO + crevasse + ombre réelle par-dessus -> double ombrage, formes "sales". Dé-baker (diviser l'albédo par un terme de hauteur/AO flouté) ou baisser le mélange AO. Les sphères de référence ont une couleur presque plate.
- Falaises aplaties en rampes = cire fondue. Une limitation trop forte de la hauteur par pente supprime les rebords nets. Préférer une hauteur en terrasses + un maillage plus dense aux bords ; limiter uniquement les vrais pics (médiane + ouverture), pas les plaques.
- Fondu croisé à l'équateur peut créer un espace sombre en forme de lentille ; faire pivoter la balle pour vérifier.
- Plaques. Les plaques plates et lisses "de boue" proviennent de la source IA (zones de fondu fantômes) ou d'un masque de poussière trop fort : mettre la poussière à 0 et ajouter une fine bosse de bruit granuleux (~0.5) par-dessus la normale.
- Couleur. Étalonner vers la référence avec une multiplication (par exemple 0.80, 0.66, 0.52 pour du grès chaud) ; une lumière neutre recolore le matériau en rose/beige. Toujours placer la référence à côté d'un test 1280x720 du même angle et comparer l'échelle, la couleur, la forme AVANT un long rendu.
Règle de relief : fines ailettes
Les crêtes/ailettes très fines sur la géométrie proviennent de crêtes de 1-3 px dans la carte de hauteur, pas de la profondeur ou de la couleur. Ne PAS simplement baisser la profondeur. Les couper par TAILLE : ouverture grise de la hauteur avec un disque (~5 px sur une map 2K) + 3 px de flou pour la GÉOMÉTRIE uniquement ; les détails fins restent dans la map normale/albédo. Toujours vérifier un gros plan, pas seulement la balle entière.
Recette du cube (matériau carrelable)
6 faces x grille 700x700, découpe UV par face (étendue en u = L/H x ZOOM, étendue en v = ZOOM, 6 décalages), relief le long de la normale de la face atténué à 0 sur les bords, enroulement vérifié à partir des vecteurs de coin de face (vérifier le produit scalaire sortant par face ; le dessus/le dessous ont été inversés une fois), carte normale tangente à partir des UV, K ~0.08. Les couches ne se prolongent pas à travers les bords (différentes découpes) - prévenir l'utilisateur.
Pièges d'outillage
- Le Python de Blender n'a pas scipy : utiliser numpy dans les scripts Blender, scipy uniquement dans l'environnement Python externe.
bpy.ops.mesh.primitive_uv_sphere_addest extrêmement lent au-dessus de ~1.5 M de sommets : construire les maillages avec numpy.- Lors du découpage des tableaux UV par face, utiliser l'index local (q - base), pas le global.
- PIL lit les PNG 16 bits RVB comme 8 bits/écrêtés : utiliser OpenCV
IMREAD_UNCHANGED. Prévisualiser un PNG 16 bits gris via PILconvert('RGB')donne du blanc pur. - Le flou gaussien d'OpenCV ne prend pas en charge
BORDER_WRAP; utiliserscipy.ndimage.gaussian_filter(mode='wrap')pour les maps carrelables. pkill -f nom/pgrep -f nom | xargs killpeut correspondre et tuer votre propre shell (sortie 144) ; tuer par PID.- Dériver les normales de la hauteur en unités physiques ; une échelle ~100x trop grande donne un bruit tacheté sombre.
- Lire un rendu avec un chemin de fichier réutilisé peut montrer une image ancienne en cache ; écrire dans un nouveau nom.