blender · diff
git:20260911.25436b5 to git:20261005.2bc0998
84 added, 93 removed. Audit A to A.
---
name: blender
description: "Automate Blender scenes with the bpy Python API, build Geometry Nodes workflows, configure Cycles or EEVEE renders, and troubleshoot headless batch jobs."
category: 3d
risk: safe
source: self
source_type: self
date_added: "2026-08-26"
- tags: ["blender", "bpy", "python-api", "cycles", "eevee", "geometry-nodes", "claude"]
+ tags: ["blender", "bpy", "python-api", "cycles", "eevee", "geometry-nodes", "headless", "batch-render"]
tools: ["claude", "cursor", "gemini", "codex"]
---
# Blender 4.x 3D Creation Suite AI Skill Guide (Claude)
## Overview & Engine Architecture
- Blender 4.x is an open-source 3D creation suite covering modeling, sculpting, animation, simulation, compositing, and rendering. Its core automation surface is the **`bpy` Python API** embedded in every Blender build, plus **Geometry Nodes** (node-based procedural mesh/instance graphs), **Shader Nodes**, and two primary renderers: **EEVEE** (real-time) and **Cycles** (path-traced). Claude operates as a Principal Technical Artist and Pipeline TD, specializing in **headless `blender --background --python` batch jobs**, **idempotent scene setup scripts**, **addon packaging (`bl_info`)**, and **render farm-ready CLI flags**.
- ### Blender Runtime & Automation Stack
+ Blender 4.2 LTS / 4.3+ / 5.x is an open-source DCC suite. Agent automation runs through **`bpy` (Python)**, **CLI background mode**, and optional **Geometry Nodes** procedural graphs. Render engines: **Cycles** (path-traced, farm-friendly) and **EEVEE** (real-time; identifier changed across 4.2→5.0 — resolve at runtime, do not hardcode `BLENDER_EEVEE_NEXT`).
+ Claude acts as a Principal Technical Artist / Pipeline TD: **headless `blender --background`**, **deterministic stills**, **idempotent scene scripts**, **addon packaging (`bl_info`)**, and **export validation** (glTF/FBX/USD).
+
```
┌─────────────────────────────────────────────────────────────┐
- │ Blender 4.x Engine Architecture │
- │ │
- │ Data Model (DNA / RNA) │
- │ ├── bpy.data (meshes, materials, objects, scenes, images) │
- │ ├── bpy.context (active object, mode, selected, view_layer)│
- │ └── bpy.ops (operator layer; prefer data API for scripts) │
- │ │
- │ Evaluation & Nodes │
- │ ├── Geometry Nodes / Shader Nodes / Compositor │
- │ ├── Dependency Graph (depsgraph) evaluation │
- │ └── Animation / Drivers / Constraints │
- │ │
- │ Render & CLI │
- │ ├── EEVEE / Cycles / Workbench │
- │ ├── blender -b file.blend -P script.py -o //out -a │
- │ └── Addon system (scripts/addons, bl_info, register()) │
+ │ Blender automation stack │
+ │ bpy.data / RNA → depsgraph → Cycles|EEVEE → files │
+ │ CLI: -b blend -P script.py | -E CYCLES -f N -a (last!) │
+ │ Determinism: cycles.seed, fixed samples, no animated seed │
└─────────────────────────────────────────────────────────────┘
```
+ **Version pins (document in every pipeline README):** pin Blender **minor** (e.g. 4.2.11 LTS). GPU backends: CUDA / OPTIX / HIP / ONEAPI / METAL after `--` (see [CLI render docs](https://docs.blender.org/manual/en/latest/advanced/command_line/render.html)).
+
---
+ ## When to use / when not to
+
+ **Use when**
+
+ - Batch stills/animations, asset conversion, procedural scene generation, CI smoke renders.
+ - Geometry Nodes or modifier stacks must be evaluated headlessly.
+ - You need reproducible Cycles output (golden frames, A/B materials).
+
+ **Do not use when**
+
+ - Real-time game runtime (use Unity/Godot/Unreal skills).
+ - Legal/commercial work requires Autodesk-only formats without conversion — validate export importers downstream.
+ - Host has no GPU and Cycles GPU is mandatory without CPU fallback plan.
+
+ ---
+
## Operational Capabilities & Agent Directives
- 1. **Prefer Data API over Operators**: For production scripts, mutate `bpy.data` / object properties directly; reserve `bpy.ops` for interactive or mode-dependent actions only.
- 2. **Headless Batch Pipelines**: Author scripts that run under `blender --background --python` with zero UI assumptions (`bpy.context.view_layer` still valid).
- 3. **Deterministic Scene Setup**: Create collections, materials, cameras, and lights idempotently (delete-or-reuse by name before creating).
- 4. **Render Configuration**: Set Cycles samples, denoiser, resolution, filepath, and file format before calling `bpy.ops.render.render()`.
- 5. **Addon Hygiene**: Ship `bl_info`, `register()` / `unregister()`, and avoid writing outside Blender's user scripts path without explicit user consent.
+ 1. **Data API first**: Mutate `bpy.data`, `scene`, object properties; use `bpy.ops` only with explicit context overrides in `--background`.
+ 2. **CLI argument order**: Put `-o`, `-F`, `-E`, frame range **before** `-f`/`-a`; render flags must be **last** or Blender ignores them.
+ 3. **Deterministic Cycles**: Set `scene.cycles.seed`, disable animated seed, fix sample count (turn off adaptive sampling for golden tests); document OIDN availability — headless Linux builds often lack OpenImageDenoise and abort if denoise stays enabled.
+ 4. **Color management**: Set `scene.view_settings.view_transform`, `look`, and export color space explicitly; linear EXR for comp, sRGB/Rec.709 for web stills — never assume default OCIO matches farm workers.
+ 5. **Engine resolution**: `scene.render.engine = bpy.context.preferences.addons['cycles'].preferences...` or iterate `bpy.types.RenderEngine` — EEVEE enum names differ by version.
+ 6. **Exit codes**: Wrap `main()`; on failure `sys.exit(1)` so CI fails; log `blender --version` at job start.
---
- ## Production Python: Headless Mesh + Cycles Still Render
+ ## Headless batch: deterministic Cycles still
- Save as `batch_setup_and_render.py` and run:
- `blender --background --python batch_setup_and_render.py`
+ `render_still.py` — run: `blender -b scene.blend --python render_still.py -- --cycles-device OPTIX`
```python
- # ==============================================================================
- # Blender 4.x bpy: create a lit scene and render a Cycles still
- # ==============================================================================
import bpy
- from mathutils import Euler
- from math import radians
-
- # Reset to empty scene
- bpy.ops.wm.read_factory_settings(use_empty=True)
+ import sys
- scene = bpy.context.scene
- scene.render.engine = "CYCLES"
- scene.cycles.samples = 64
- scene.cycles.use_denoising = True
- scene.render.resolution_x = 1920
- scene.render.resolution_y = 1080
- scene.render.filepath = "//render_out/hero_still"
- scene.render.image_settings.file_format = "PNG"
+ def main():
+ scene = bpy.context.scene
+ scene.render.engine = "CYCLES"
+ scene.cycles.device = "GPU" # or CPU-only farm
+ scene.cycles.samples = 128
+ scene.cycles.use_adaptive_sampling = False
+ scene.cycles.seed = 42
+ scene.cycles.use_animated_seed = False
+ # Disable denoise if OIDN missing on worker
+ scene.cycles.use_denoising = False
+ scene.render.image_settings.file_format = "OPEN_EXR"
+ scene.render.image_settings.color_mode = "RGBA"
+ scene.render.filepath = "//out/frame_####"
+ bpy.ops.render.render(write_still=True)
- # Geometry
- bpy.ops.mesh.primitive_uv_sphere_add(radius=1.0, location=(0, 0, 1))
- sphere = bpy.context.active_object
- sphere.name = "HeroSphere"
+ if __name__ == "__main__":
+ try:
+ main()
+ except Exception as e:
+ print("BLENDER_PIPELINE_FAIL", e, file=sys.stderr)
+ sys.exit(1)
+ ```
- bpy.ops.mesh.primitive_plane_add(size=8, location=(0, 0, 0))
- bpy.context.active_object.name = "Ground"
+ **Animation farm split**: render frame ranges per worker (`-s` / `-e`), merge with `bpy.ops.cycles.merge_images` or FFmpeg concat of EXR/PNG sequences.
- # Material
- mat = bpy.data.materials.new(name="HeroMat")
- mat.use_nodes = True
- nodes = mat.node_tree.nodes
- bsdf = nodes.get("Principled BSDF")
- if bsdf:
- bsdf.inputs["Base Color"].default_value = (0.15, 0.45, 0.85, 1.0)
- bsdf.inputs["Roughness"].default_value = 0.35
- sphere.data.materials.append(mat)
+ ---
- # Camera + light
- cam_data = bpy.data.cameras.new("HeroCam")
- cam_obj = bpy.data.objects.new("HeroCam", cam_data)
- bpy.context.collection.objects.link(cam_obj)
- cam_obj.location = (4.5, -4.5, 3.2)
- cam_obj.rotation_euler = Euler((radians(65), 0, radians(45)), "XYZ")
- scene.camera = cam_obj
+ ## Export pipelines
- light_data = bpy.data.lights.new(name="KeyLight", type="AREA")
- light_data.energy = 400
- light_obj = bpy.data.objects.new("KeyLight", light_data)
- bpy.context.collection.objects.link(light_obj)
- light_obj.location = (2.5, -2.0, 4.0)
+ | Target | Operator / notes | Pitfalls |
+ | :--- | :--- | :--- |
+ | **glTF 2.0** | `bpy.ops.export_scene.gltf` | Apply scale; Draco optional; check NLA vs active action |
+ | **FBX** | `export_scene.fbx` | Unit scale 0.01 vs 1.0; bone roll |
+ | **USD** | Blender USD exporter | Instance paths, material binding |
+ | **Alembic** | Cache transforms/deforms | Frame range, subframe sampling |
- bpy.ops.render.render(write_still=True)
- print("Render complete:", scene.render.filepath)
- ```
+ Always **apply scale** (or document non-uniform scale) before export; validate in target engine (Unity/Unreal importers).
---
- ## Technical Troubleshooting Matrix
+ ## Failure taxonomy
- | Issue & Failure Signature | Root Cause Analysis | Diagnostic & Resolution Pathway |
+ | Symptom | Likely cause | Fix |
| :--- | :--- | :--- |
- | **`AttributeError` on bpy context in background** | Script assumed UI-only context fields or active 3D View. | Use `bpy.data` / `scene` explicitly; pass `override` dicts only when required. |
- | **Operators fail with "context is incorrect"** | Wrong mode, no active object, or wrong area type. | Switch modes via data API where possible, or set `bpy.context.view_layer.objects.active`. |
- | **Cycles render is black** | Missing camera, lights, or wrong world/shader setup. | Assert `scene.camera`, add Area/Sun light, check material node links. |
- | **Addon not listed after install** | Missing/invalid `bl_info` or `register()` exception. | Check System Console / terminal traceback; verify Blender version tuple. |
+ | Black render | No camera/lights/world | Assert `scene.camera`; add key light |
+ | `context is incorrect` | `bpy.ops` in wrong mode | Data API or `temp_override` |
+ | `Failed to denoise` | OIDN absent on server | `use_denoising = False` or install OIDN build |
+ | EEVEE enum not found | Version drift | Query available engines at runtime |
+ | Non-deterministic noise | Animated seed / adaptive sampling | Fixed seed + fixed samples |
+ | Washed stills vs viewport | Wrong view transform / display device | Match `view_settings` + file format color space |
+ Practitioner pattern (r/blenderhelp): background jobs fail silently when `-a` precedes `-o` — reorder CLI.
+
---
- ## Essential CLI Patterns
+ ## Essential CLI
```bash
- # Background script (no UI)
- blender --background project.blend --python pipeline/export_fbx.py
-
- # Frame range animation render
- blender -b project.blend -o //renders/frame_#### -F PNG -s 1 -e 120 -a
-
- # Factory reset + script (CI-safe)
- blender --factory-startup --background --python tests/smoke_bpy.py
+ blender --version
+ blender -b file.blend -E CYCLES -o //renders/frame_#### -F PNG -f 1 -- --cycles-device CPU
+ blender --factory-startup -b --python tests/smoke_bpy.py
+ blender -b file.blend -P pipeline/export_gltf.py
```
- ### Essential Paths
- - **User addons**: `~/AppData/Roaming/Blender Foundation/Blender/<version>/scripts/addons` (Windows)
- - **Preferences**: Blender Preferences → File Paths / System
- - **Python console**: Scripting workspace → Interactive Console
+ **Paths (Windows):** `%APPDATA%\Blender Foundation\Blender\<ver>\scripts\addons`
---
## Agent Operational Directive
- > **MANDATORY**: Prefer `bpy.data` mutations over `bpy.ops` in automation. Always set `scene.camera`, output path, and engine before rendering. Never assume an interactive 3D Viewport exists in `--background` mode.
+
+ > **MANDATORY**: Pin Blender version in CI. Set Cycles seed + fixed samples for deterministic output. Put `-f`/`-a` last on CLI. Prefer EXR + documented OCIO for color-critical pipelines. Exit non-zero on pipeline failure.