Animation Blender — Travail 3D piloté par Python
Pilotez Blender via bpy, en mode arrière-plan, à partir d'un script réexécutable. Considérez le fichier .blend comme un artefact de construction du script : le script est la source de vérité, le fichier est le livrable.
Lisez references/BLENDER-PLAYBOOK.md pour l'architecture et les bonnes pratiques, et references/BLENDER-RECIPES.md pour des modèles de code prêts à l'emploi. Vérifiez chaque détail de l'API dans la documentation de la version de Blender installée ; l'API Python change entre les versions.
1. Vérifier d'abord l'environnement
blender --version
blender --background --factory-startup --python-expr \
"import bpy, sys; print('BLENDER', bpy.app.version_string); print('PY', sys.version.split()[0]); print('ENGINES', [e.bl_idname for e in bpy.types.RenderEngine.__subclasses__()][:5])"
Règles :
bpyappartient au Python intégré de Blender. N'utilisez jamaispip install bpyet n'exécutez jamais de scripts de scène avec le Python système.- Utilisez
--python-exit-code 1pour qu'une exception Python fasse échouer la commande shell au lieu de produire un succès silencieux. - Utilisez
--factory-startuppour des builds propres ; ne l'utilisez jamais pour effacer le projet ouvert d'un utilisateur. - Enregistrez la version de Blender, le moteur, la plage d'images, la résolution, les FPS et le chemin de sortie au début de chaque rendu.
2. Invocations canoniques
# Construire une scène à partir de zéro et enregistrer le .blend
blender --background --factory-startup --python-exit-code 1 --python blender/scripts/build_scene.py
# Modifier un projet existant
blender --background project.blend --python-exit-code 1 --python blender/scripts/update_scene.py
# Rendre l'animation enregistrée
blender --background project.blend --render-anim
# Rendre une image
blender --background project.blend --render-frame 120
# Rendre une plage en toute sécurité (séquence d'images)
blender --background project.blend --python-exit-code 1 --python blender/scripts/render_frames.py
Exécutez les longs travaux avec la sortie redirigée vers logs/, et préférez toujours une séquence d'images pour tout ce que vous pourriez devoir reprendre.
3. Architecture du script
Commencez avec un fichier pour une petite scène. Divisez lorsque la scène dépasse environ 300 lignes ou comporte plusieurs plans :
blender/
config.py # fps, frame range, resolution, palette, paths, seed
build.py # point d'entrée : reset → setup → build shots → save
scene_setup.py # monde, unités, collections, paramètres de rendu
geometry.py # primitives, courbes, maillages paramétriques
materials.py # constructeurs de nœuds, usine de matériaux réutilisable
animation.py # keyframes, drivers, mouvement procédural
camera.py # rigs, orbite/dolly, profondeur de champ, vérifications de cadrage
lighting.py # éclairage principal/secondaire/contre-jour, HDRI, accents émissifs
simulation.py # particules, corps rigide, tissu — configuration du cache
render.py # moteur, échantillons, sortie, planche contact, encodage
shots/ # un module par plan : shot_01.py, shot_02.py
Non-négociables :
- Idempotent. Réexécuter le build ne met à jour que vos collections/objets nommés ; cela ne duplique jamais la géométrie et n'efface pas le contenu utilisateur non lié.
- Nommé.
Main_Logo,Cam_Orbit,Light_Key,Emitter_Particles. Ne livrez jamaisCube.003. - Configuré. Chaque valeur réglable se trouve dans
config.pyou une dataclass, de sorte qu'une révision soit une modification d'une ligne. - Vérifié. Échouez bruyamment si un objet, une caméra, une police ou un répertoire de sortie est manquant.
- Limité. Le nettoyage ne supprime que les collections dont vous possédez les noms, préfixés par ex.
MS_.
4. Construction de la scène
- Préférez l'API de données (
bpy.data.objects.new,bpy.data.meshes.new,collection.objects.link) auxbpy.opssensibles au contexte, qui dépendent de la sélection, du mode et de la zone. - Lorsqu'un opérateur est réellement nécessaire, fournissez une substitution de contexte appropriée pour cette version, et documentez pourquoi.
- Construisez les matériaux via des nœuds et une petite fonction d'usine ; ne copiez-collez pas des arbres de 20 nœuds par objet.
- Utilisez une échelle réaliste et définissez le système d'unités de la scène ; une échelle incorrecte casse la profondeur de champ, la physique et l'éclairage.
- Gardez l'arbre de nœuds du Monde explicite (couleur, force, HDRI) pour que les rendus soient reproductibles sur une autre machine.
- Empaquetez ou relativisez les actifs. Les chemins
//assets/...avec un dossier de package battent les chemins absolus vers les Téléchargements de quelqu'un.
5. Animation
Choisissez le mécanisme délibérément :
| Besoin | Utilisation |
|---|---|
| Changement de position/rotation/échelle/matériau créé | Keyframes avec interpolation explicite |
| Propriété suivant une autre propriété ou expression | Drivers (expressions simples et documentées) |
| Mouvement répété/paramétrique (orbites, vagues, grilles, spirales) | Mathématiques dépendantes de l'image, évaluées sans état |
| Des milliers d'instances, motifs, dispersion | Nœuds de géométrie |
| Mouvement physiquement émergent | Simulations (cache, vérification de la plage complète) |
| Trajectoire de caméra dans l'espace | Courbe + contrainte Follow Path, ou rig avec keyframes |
Hygiène des keyframes :
obj.location = (0, 0, 0)
obj.keyframe_insert("location", frame=1)
obj.location = (4, 0, 0)
obj.keyframe_insert("location", frame=48)
for fc in obj.animation_data.action.fcurves:
for kp in fc.keyframe_points:
kp.interpolation = 'BEZIER'
kp.easing = 'EASE_IN_OUT'
kp.handle_left_type = kp.handle_right_type = 'AUTO_CLAMPED'
- Définissez l'interpolation intentionnellement. Bezier par défaut est bien pour les mouvements organiques ; utilisez
LINEARpour une vitesse constante et un mouvement mécanique ; utilisezCONSTANTpour les looks en pas à pas/pixel. - Ne laissez jamais une atténuation non désirée sur un cycle de boucle — cela produit un à-coup au point de boucle.
- Pour les boucles : rendez l'image 1 et l'image N+1 identiques, puis rendez
[1, N]. - Tout ce qui est procédural doit être une fonction pure de l'image :
f(frame). Pas d'état cumulé, pas derandomnon ensemencé.
6. Nœuds de géométrie et instanciation
Utilisez les nœuds de géométrie lorsque vous avez besoin d'échelle, de variation ou de contrôle non destructif :
- Dispersion/instanciation (arbres, débris, étoiles, foules).
- Réseaux paramétriques, grilles, motifs radiaux, carrelages géométriques islamiques.
- Déplacement animé, champs, et rotation/échelle par instance.
- Conversion d'une lourde boucle Python de 10 000 objets en un seul arbre de nœuds.
Construisez les nœuds par nom avec nodes.new(...) et links.new(...), pas par index fragile. Exposez les réglages que l'utilisateur demandera (nombre, rayon, graine, vitesse) comme entrées du modificateur afin qu'une révision ne nécessite aucune modification de code.
7. Matériaux, éclairage, caméra
- Matériaux : base Principled BSDF ; rugosité/métallique explicite ; émission pour les accents (gardez-la retenue — le bloom ne peut pas réparer une image plate). Transparence réelle uniquement lorsque nécessaire, et vérifiez-la dans le moteur final.
- Éclairage : principale → secondaire → contre-jour → environnement. La forme et la profondeur passent avant la décoration. Vérifiez l'exposition et l'écrêtage des hautes lumières, pas seulement la fenêtre.
- Caméra : choisissez la distance focale et le cadrage pour le sujet. Orbite, dolly, grue ou fixe — chacun doit avoir une raison. Vérifiez le cadrage aux images extrêmes, pas seulement à l'image 1. Préférez des poignées Bezier lisses ; ajoutez un léger amorti plutôt qu'un arrêt brusque.
- Profondeur de champ : faites la mise au point sur le point narratif ; ne floutez jamais un petit texte.
8. Moteurs et paramètres de rendu
| Moteur | Utilisation pour | Coût |
|---|---|---|
| EEVEE | Motion design, travail stylisé, itération rapide, aperçus | Faible |
| Cycles | Lumière photoréaliste, reflets, GI, verre, beauté finale | Élevé |
| Workbench | Blocage, silhouettes, animatiques | Très faible |
Testez les deux en cas de doute ; la vitesse du moteur dépend de la scène, pas du marketing. Le GPU dépend du build, du pilote et de l'OS — gardez toujours un chemin CPU.
Définissez explicitement et enregistrez :
scene.render.engine = 'BLENDER_EEVEE_NEXT' # 4.2+ ; les versions antérieures peuvent utiliser 'BLENDER_EEVEE'
scene.render.resolution_x, scene.render.resolution_y = 1920, 1080
scene.render.resolution_percentage = 100
scene.render.fps, scene.render.fps_base = 30, 1.0
scene.frame_start, scene.frame_end = 1, 300
scene.render.image_settings.file_format = 'PNG'
scene.render.image_settings.color_mode = 'RGBA'
scene.render.filepath = "//renders/shot_01/frame_"
- Aperçu : résolution 25–50 %, échantillons faibles, EEVEE ou Workbench.
- Final : résolution complète, moteur choisi pour le rendu, débruitage si utile, transformation de vue correcte.
- Couleur : décidez de la transformation de vue (AgX/Filmic/Standard) une fois, appliquez-la à toutes les passes, et harmonisez-la en aval dans Remotion/FFmpeg. Les transformations non harmonisées sont la cause la plus fréquente du « le compositing semble délavé ».
- Rendu long → séquence PNG (ou EXR pour HDR), puis encodage. La sortie vidéo directe est réservée aux révisions rapides.
9. Échelle de prévisualisation
- Une image fixe à une image représentative.
- Images clés : première, révélation, pic, chaque transition, dernière.
- Segment à faibles échantillons et basse résolution contenant le mouvement le plus difficile.
- Aperçu complet à échelle réduite, FPS réels.
- Final uniquement après que 1–4 semblent corrects.
Inspectez avec une planche contact plus des images ciblées :
ffmpeg -i preview.mp4 -vf "fps=2,scale=320:-1,tile=4x4" -frames:v 1 previews/contact.jpg
Recherchez le scintillement, le z-fighting, les sauts, les intersections, la nage des textures, le clipping de la caméra, les changements d'exposition et le texte illisible.
10. Texte, multilingue et travail de logo
- Convertissez le texte en maillage uniquement après avoir confirmé le texte et la licence de la police ; conservez un objet texte modifiable dans la source.
- Vérifiez la couverture des glyphes avant d'animer. Pour le persan/arabe, vérifiez le façonnage, la liaison, l'ordre RTL, les diacritiques et la ponctuation mixte dans l'image rendue — une chaîne correcte peut toujours mal s'afficher si le chemin du texte ne façonne pas.
- Pour le travail de marque/logo, obtenez une source vectorielle si possible ; s'il s'agit d'une image matricielle, vectorisez délibérément et vérifiez les bords en 4K.
- Biseautez/pondérez le type pour qu'il survive à la lumière ; évitez les bords pur noirs sur fond noir ou pur blancs sur fond blanc.
11. Performances et fiabilité
- Instanciez, ne dupliquez pas. Abaissez la subdivision avant d'abaisser les échantillons.
- Limitez les couches transparentes et les volumétries ; ce sont les tueurs habituels du temps de rendu.
- Mettez en cache les simulations et confirmez que le cache est à l'intérieur du projet ou documenté.
- Rendez par lots d'images pour les travaux fragiles ; vérifiez le nombre d'images et détectez les images manquantes avant l'encodage.
- Surveillez la RAM/VRAM/disque. Les séquences EXR 4K sont volumineuses ; vérifiez l'espace libre avant un long rendu.
- Sauvegardez un
.blendavant de l'ouvrir/de l'enregistrer avec une version majeure plus récente de Blender — les fichiers plus récents peuvent ne pas s'ouvrir dans les versions antérieures.
12. Exemple minimal fonctionnel
# build.py — exécutez avec :
# blender --background --factory-startup --python-exit-code 1 --python build.py
import bpy, bmesh, math, os
scene = bpy.context.scene
scene.frame_start, scene.frame_end = 1, 120
scene.render.fps = 30
scene.render.resolution_x, scene.render.resolution_y = 1920, 1080
scene.render.engine = 'BLENDER_EEVEE_NEXT'
scene.render.filepath = "//renders/frame_"
# nettoyer la collection possédée
col = bpy.data.collections.get("MS_Main") or bpy.data.collections.new("MS_Main")
if col.name not in scene.collection.children:
scene.collection.children.link(col)
def add_sphere(name, loc, radius, mat):
"""Sphère via l'API de données : pas d'opérateurs, pas de dépendance au contexte."""
mesh = bpy.data.meshes.new(name)
bm = bmesh.new()
bmesh.ops.create_uvsphere(bm, u_segments=32, v_segments=16, radius=radius)
bm.to_mesh(mesh)
bm.free()
obj = bpy.data.objects.new(name, mesh)
obj.location = loc
col.objects.link(obj)
obj.data.materials.append(mat)
return obj
mat = bpy.data.materials.new("MS_Emission")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (0.05, 0.6, 0.55, 1)
bsdf.inputs["Emission Color"].default_value = (0.1, 0.9, 0.8, 1)
bsdf.inputs["Emission Strength"].default_value = 3.0
bsdf.inputs["Roughness"].default_value = 0.3
core = add_sphere("MS_Core", (0, 0, 1), 0.8, mat)
core.keyframe_insert("scale", frame=1)
core.scale = (1.15, 1.15, 1.15)
core.keyframe_insert("scale", frame=40)
core.scale = (1.0, 1.0, 1.0)
core.keyframe_insert("scale", frame=90)
# caméra
cam_data = bpy.data.cameras.new("MS_Cam")
cam = bpy.data.objects.new("MS_Cam", cam_data)
col.objects.link(cam)
scene.camera = cam
cam.location = (6, -6, 3)
cam.rotation_euler = (math.radians(75), 0, math.radians(45))
# enregistrer
os.makedirs(bpy.path.abspath("//renders"), exist_ok=True)
bpy.ops.wm.save_as_mainfile(filepath=bpy.path.abspath("//scene.blend"))
print("BUILD OK", len(col.objects), "objects")
Plus dans references/BLENDER-RECIPES.md : rigs d'orbite, atténuations, dispersion par nœuds de géométrie, particules, texte, passes alpha, scripts pour ferme de rendu et commandes d'encodage.
13. Blender MCP (commodité optionnelle)
Les scripts en mode arrière-plan sont la voie de production : reproductibles, différentiables, débogables, compatibles CI. MCP est utile pour l'inspection interactive de la scène et les ajustements en direct dans une session déjà ouverte. Il s'agit d'une intégration tierce, non d'un composant de Blender.
Si l'utilisateur le souhaite : examinez le dépôt et la licence, vérifiez la compatibilité avec la version de Blender installée, comprenez qu'il accorde une exécution Python arbitraire dans Blender, gardez-le lié à loopback et ne l'exposez jamais à un réseau non fiable. Le nom actuel du paquet est mcp-for-blender ; suivez les instructions de configuration actuelles du dépôt plutôt que les anciens extraits blender-mcp. N'en faites pas une dépendance d'un projet livré.
14. Livrables
Un travail Blender est terminé lorsque vous avez :
output/final.mp4(ou le format demandé), validé avecffprobe.blender/scripts/*.py— la source de construction.scene.blend— le projet modifiable, actifs empaquetés ou relatifs.renders/séquence d'images (ou master documenté) conservée lorsque utile.README.md— version exacte de Blender, installation, construction, aperçu, rendu final et commandes de révision.- Un court rapport : outils, résolution, FPS, durée, nombre d'images, ce qui a été vérifié visuellement.
Ne livrez jamais seulement le MP4 lorsque l'utilisateur a demandé une animation qu'il pourrait vouloir modifier.