blender

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Blender 3D Automation

Blender 3D自动化

Automate Blender 3D modeling, animation, rendering, and scene management using Python's bpy API and command-line rendering. Supports headless operation, batch processing, and procedural generation.
使用Python的bpy API和命令行渲染实现Blender 3D建模、动画、渲染及场景管理的自动化。支持无头运行、批量处理和程序化生成。

Direct Control (CLI / API / Scripting)

直接控制(CLI / API / 脚本)

Command-Line Rendering

命令行渲染

bash
undefined
bash
undefined

Render single frame

Render single frame

blender scene.blend --background --render-frame 1
blender scene.blend --background --render-frame 1

Render animation range

Render animation range

blender scene.blend --background --render-anim --frame-start 1 --frame-end 120
blender scene.blend --background --render-anim --frame-start 1 --frame-end 120

Render with custom output path

Render with custom output path

blender scene.blend --background --render-output /tmp/render_#### --render-anim
blender scene.blend --background --render-output /tmp/render_#### --render-anim

Render specific scene

Render specific scene

blender file.blend --background --scene "Scene.001" --render-frame 1
blender file.blend --background --scene "Scene.001" --render-frame 1

Set render engine

Set render engine

blender scene.blend --background --engine CYCLES --render-frame 1 blender scene.blend --background --engine BLENDER_EEVEE --render-frame 1
blender scene.blend --background --engine CYCLES --render-frame 1 blender scene.blend --background --engine BLENDER_EEVEE --render-frame 1

Use GPU for rendering

Use GPU for rendering

blender scene.blend --background --python-expr "import bpy; bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'CUDA'; bpy.context.scene.cycles.device = 'GPU'" --render-frame 1
undefined
blender scene.blend --background --python-expr "import bpy; bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'CUDA'; bpy.context.scene.cycles.device = 'GPU'" --render-frame 1
undefined

Python bpy Scripting

Python bpy脚本开发

python
import bpy
import math
python
import bpy
import math

Create new cube

Create new cube

bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0)) cube = bpy.context.active_object cube.name = "MyCube"
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0)) cube = bpy.context.active_object cube.name = "MyCube"

Set material

Set material

mat = bpy.data.materials.new(name="RedMaterial") mat.use_nodes = True mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (1, 0, 0, 1) cube.data.materials.append(mat)
mat = bpy.data.materials.new(name="RedMaterial") mat.use_nodes = True mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (1, 0, 0, 1) cube.data.materials.append(mat)

Add keyframe animation

Add keyframe animation

cube.location = (0, 0, 0) cube.keyframe_insert(data_path="location", frame=1) cube.location = (5, 0, 0) cube.keyframe_insert(data_path="location", frame=120)
cube.location = (0, 0, 0) cube.keyframe_insert(data_path="location", frame=1) cube.location = (5, 0, 0) cube.keyframe_insert(data_path="location", frame=120)

Set render settings

Set render settings

scene = bpy.context.scene scene.render.engine = 'CYCLES' scene.cycles.device = 'GPU' scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 scene.render.fps = 24 scene.frame_start = 1 scene.frame_end = 120
scene = bpy.context.scene scene.render.engine = 'CYCLES' scene.cycles.device = 'GPU' scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 scene.render.fps = 24 scene.frame_start = 1 scene.frame_end = 120

Render current frame

Render current frame

bpy.ops.render.render(write_still=True)
bpy.ops.render.render(write_still=True)

Save blend file

Save blend file

bpy.ops.wm.save_as_mainfile(filepath="/path/to/output.blend")
undefined
bpy.ops.wm.save_as_mainfile(filepath="/path/to/output.blend")
undefined

Execute Python Script in Blender

在Blender中执行Python脚本

bash
undefined
bash
undefined

Run Python script

Run Python script

blender --background --python script.py
blender --background --python script.py

Run script with arguments

Run script with arguments

blender --background --python script.py -- arg1 arg2
blender --background --python script.py -- arg1 arg2

Run inline Python

Run inline Python

blender --background --python-expr "import bpy; bpy.ops.mesh.primitive_cube_add()"
blender --background --python-expr "import bpy; bpy.ops.mesh.primitive_cube_add()"

Run script and save

Run script and save

blender scene.blend --background --python modify_scene.py --save
undefined
blender scene.blend --background --python modify_scene.py --save
undefined

Scene Manipulation

场景操作

python
import bpy
python
import bpy

List all objects

List all objects

for obj in bpy.data.objects: print(f"{obj.name}: {obj.type}")
for obj in bpy.data.objects: print(f"{obj.name}: {obj.type}")

Delete object by name

Delete object by name

obj = bpy.data.objects.get("Cube") if obj: bpy.data.objects.remove(obj, do_unlink=True)
obj = bpy.data.objects.get("Cube") if obj: bpy.data.objects.remove(obj, do_unlink=True)

Import FBX/OBJ

Import FBX/OBJ

bpy.ops.import_scene.fbx(filepath="/path/to/model.fbx") bpy.ops.import_scene.obj(filepath="/path/to/model.obj")
bpy.ops.import_scene.fbx(filepath="/path/to/model.fbx") bpy.ops.import_scene.obj(filepath="/path/to/model.obj")

Export FBX/OBJ

Export FBX/OBJ

bpy.ops.export_scene.fbx(filepath="/path/to/output.fbx", use_selection=False) bpy.ops.export_scene.obj(filepath="/path/to/output.obj")
bpy.ops.export_scene.fbx(filepath="/path/to/output.fbx", use_selection=False) bpy.ops.export_scene.obj(filepath="/path/to/output.obj")

Camera setup

Camera setup

camera_data = bpy.data.cameras.new(name="Camera") camera_object = bpy.data.objects.new("Camera", camera_data) bpy.context.scene.collection.objects.link(camera_object) camera_object.location = (7.5, -6.5, 5.4) camera_object.rotation_euler = (math.radians(63), 0, math.radians(46)) bpy.context.scene.camera = camera_object
camera_data = bpy.data.cameras.new(name="Camera") camera_object = bpy.data.objects.new("Camera", camera_data) bpy.context.scene.collection.objects.link(camera_object) camera_object.location = (7.5, -6.5, 5.4) camera_object.rotation_euler = (math.radians(63), 0, math.radians(46)) bpy.context.scene.camera = camera_object

Lighting

Lighting

light_data = bpy.data.lights.new(name="Light", type='SUN') light_object = bpy.data.objects.new(name="Sun", object_data=light_data) bpy.context.collection.objects.link(light_object) light_object.location = (5, 5, 10) light_data.energy = 2.0
undefined
light_data = bpy.data.lights.new(name="Light", type='SUN') light_object = bpy.data.objects.new(name="Sun", object_data=light_data) bpy.context.collection.objects.link(light_object) light_object.location = (5, 5, 10) light_data.energy = 2.0
undefined

Geometry Nodes (Procedural)

几何节点(程序化)

python
import bpy
python
import bpy

Add geometry nodes modifier

Add geometry nodes modifier

obj = bpy.context.active_object modifier = obj.modifiers.new(name="GeometryNodes", type='NODES')
obj = bpy.context.active_object modifier = obj.modifiers.new(name="GeometryNodes", type='NODES')

Create node group

Create node group

node_group = bpy.data.node_groups.new('MyNodeTree', 'GeometryNodeTree') modifier.node_group = node_group
node_group = bpy.data.node_groups.new('MyNodeTree', 'GeometryNodeTree') modifier.node_group = node_group

Add input/output nodes

Add input/output nodes

input_node = node_group.nodes.new('NodeGroupInput') output_node = node_group.nodes.new('NodeGroupOutput')
input_node = node_group.nodes.new('NodeGroupInput') output_node = node_group.nodes.new('NodeGroupOutput')

Add geometry nodes (e.g., subdivide)

Add geometry nodes (e.g., subdivide)

subdivide_node = node_group.nodes.new('GeometryNodeSubdivisionSurface') node_group.links.new(input_node.outputs[0], subdivide_node.inputs[0]) node_group.links.new(subdivide_node.outputs[0], output_node.inputs[0])
undefined
subdivide_node = node_group.nodes.new('GeometryNodeSubdivisionSurface') node_group.links.new(input_node.outputs[0], subdivide_node.inputs[0]) node_group.links.new(subdivide_node.outputs[0], output_node.inputs[0])
undefined

MCP Server Integration

MCP服务器集成

Add to
.codebuddy/mcp.json
:
json
{
  "mcpServers": {
    "blender": {
      "command": "npx",
      "args": ["-y", "@ahujasid/blender-mcp"],
      "env": {
        "BLENDER_PATH": "/usr/bin/blender"
      }
    }
  }
}
添加至
.codebuddy/mcp.json
json
{
  "mcpServers": {
    "blender": {
      "command": "npx",
      "args": ["-y", "@ahujasid/blender-mcp"],
      "env": {
        "BLENDER_PATH": "/usr/bin/blender"
      }
    }
  }
}

Available MCP Tools

可用的MCP工具

  • blender_execute_script
    - Execute Python bpy script in Blender
  • blender_render_frame
    - Render single frame or animation
  • blender_create_object
    - Create primitive objects (cube, sphere, plane, etc.)
  • blender_modify_object
    - Transform, scale, rotate objects
  • blender_set_material
    - Apply materials and shaders
  • blender_add_keyframe
    - Create animation keyframes
  • blender_import_model
    - Import FBX, OBJ, STL, GLTF
  • blender_export_model
    - Export to various formats
  • blender_list_objects
    - Get scene object hierarchy
  • blender_get_scene_info
    - Get render settings and scene data
  • blender_execute_script
    - 在Blender中执行Python bpy脚本
  • blender_render_frame
    - 渲染单帧或动画
  • blender_create_object
    - 创建基础几何体(立方体、球体、平面等)
  • blender_modify_object
    - 变换、缩放、旋转对象
  • blender_set_material
    - 应用材质与着色器
  • blender_add_keyframe
    - 创建动画关键帧
  • blender_import_model
    - 导入FBX、OBJ、STL、GLTF格式模型
  • blender_export_model
    - 导出至多种格式
  • blender_list_objects
    - 获取场景对象层级
  • blender_get_scene_info
    - 获取渲染设置与场景数据

Common Workflows

常见工作流

1. Batch Render Multiple Scenes

1. 批量渲染多个场景

bash
undefined
bash
undefined

Render all scenes in a blend file

Render all scenes in a blend file

for scene in $(blender file.blend --background --python-expr "import bpy; print(','.join([s.name for s in bpy.data.scenes]))" | tail -1 | tr ',' '\n'); do blender file.blend --background --scene "$scene" --render-output "/renders/${scene}_####" --render-anim done

```python
for scene in $(blender file.blend --background --python-expr "import bpy; print(','.join([s.name for s in bpy.data.scenes]))" | tail -1 | tr ',' '\n'); do blender file.blend --background --scene "$scene" --render-output "/renders/${scene}_####" --render-anim done

```python

Python version with progress

Python version with progress

import bpy import os
output_dir = "/renders" os.makedirs(output_dir, exist_ok=True)
for scene in bpy.data.scenes: print(f"Rendering scene: {scene.name}") bpy.context.window.scene = scene scene.render.filepath = os.path.join(output_dir, f"{scene.name}_") bpy.ops.render.render(animation=True)
undefined
import bpy import os
output_dir = "/renders" os.makedirs(output_dir, exist_ok=True)
for scene in bpy.data.scenes: print(f"Rendering scene: {scene.name}") bpy.context.window.scene = scene scene.render.filepath = os.path.join(output_dir, f"{scene.name}_") bpy.ops.render.render(animation=True)
undefined

2. Procedural Asset Generation

2. 程序化资产生成

python
import bpy
import random
python
import bpy
import random

Clear scene

Clear scene

bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()
bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()

Generate random cubes

Generate random cubes

for i in range(10): x = random.uniform(-5, 5) y = random.uniform(-5, 5) z = random.uniform(0, 3) scale = random.uniform(0.5, 2.0)
bpy.ops.mesh.primitive_cube_add(location=(x, y, z), scale=(scale, scale, scale))
obj = bpy.context.active_object
obj.name = f"Cube_{i:03d}"

# Random color material
mat = bpy.data.materials.new(name=f"Mat_{i}")
mat.use_nodes = True
mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (
    random.random(), random.random(), random.random(), 1
)
obj.data.materials.append(mat)
for i in range(10): x = random.uniform(-5, 5) y = random.uniform(-5, 5) z = random.uniform(0, 3) scale = random.uniform(0.5, 2.0)
bpy.ops.mesh.primitive_cube_add(location=(x, y, z), scale=(scale, scale, scale))
obj = bpy.context.active_object
obj.name = f"Cube_{i:03d}"

# Random color material
mat = bpy.data.materials.new(name=f"Mat_{i}")
mat.use_nodes = True
mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (
    random.random(), random.random(), random.random(), 1
)
obj.data.materials.append(mat)

Save

Save

bpy.ops.wm.save_as_mainfile(filepath="/tmp/procedural_scene.blend")
undefined
bpy.ops.wm.save_as_mainfile(filepath="/tmp/procedural_scene.blend")
undefined

3. Camera Animation Sequence

3. 相机动画序列

python
import bpy
import math

scene = bpy.context.scene
camera = scene.camera
python
import bpy
import math

scene = bpy.context.scene
camera = scene.camera

Circular camera path

Circular camera path

center = (0, 0, 0) radius = 10 height = 5 num_frames = 240
for frame in range(1, num_frames + 1): angle = (frame / num_frames) * 2 * math.pi x = center[0] + radius * math.cos(angle) y = center[1] + radius * math.sin(angle) z = center[2] + height
camera.location = (x, y, z)
camera.keyframe_insert(data_path="location", frame=frame)

# Look at center
direction = (center[0] - x, center[1] - y, center[2] - z)
rot_quat = direction.to_track_quat('-Z', 'Y')
camera.rotation_euler = rot_quat.to_euler()
camera.keyframe_insert(data_path="rotation_euler", frame=frame)
scene.frame_end = num_frames
undefined
center = (0, 0, 0) radius = 10 height = 5 num_frames = 240
for frame in range(1, num_frames + 1): angle = (frame / num_frames) * 2 * math.pi x = center[0] + radius * math.cos(angle) y = center[1] + radius * math.sin(angle) z = center[2] + height
camera.location = (x, y, z)
camera.keyframe_insert(data_path="location", frame=frame)

# Look at center
direction = (center[0] - x, center[1] - y, center[2] - z)
rot_quat = direction.to_track_quat('-Z', 'Y')
camera.rotation_euler = rot_quat.to_euler()
camera.keyframe_insert(data_path="rotation_euler", frame=frame)
scene.frame_end = num_frames
undefined

4. Batch Model Import and Render

4. 批量模型导入与渲染

python
import bpy
import os
import glob

model_dir = "/path/to/models"
output_dir = "/path/to/renders"
os.makedirs(output_dir, exist_ok=True)
python
import bpy
import os
import glob

model_dir = "/path/to/models"
output_dir = "/path/to/renders"
os.makedirs(output_dir, exist_ok=True)

Setup scene once

Setup scene once

scene = bpy.context.scene scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 scene.render.engine = 'CYCLES'
scene = bpy.context.scene scene.render.resolution_x = 1920 scene.render.resolution_y = 1080 scene.render.engine = 'CYCLES'

Import and render each model

Import and render each model

for model_path in glob.glob(os.path.join(model_dir, "*.fbx")): # Clear scene bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()
# Import model
bpy.ops.import_scene.fbx(filepath=model_path)

# Center camera on object
obj = bpy.context.selected_objects[0]
bpy.ops.view3d.camera_to_view_selected()

# Render
model_name = os.path.splitext(os.path.basename(model_path))[0]
scene.render.filepath = os.path.join(output_dir, f"{model_name}.png")
bpy.ops.render.render(write_still=True)

print(f"Rendered: {model_name}")
undefined
for model_path in glob.glob(os.path.join(model_dir, "*.fbx")): # Clear scene bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete()
# Import model
bpy.ops.import_scene.fbx(filepath=model_path)

# Center camera on object
obj = bpy.context.selected_objects[0]
bpy.ops.view3d.camera_to_view_selected()

# Render
model_name = os.path.splitext(os.path.basename(model_path))[0]
scene.render.filepath = os.path.join(output_dir, f"{model_name}.png")
bpy.ops.render.render(write_still=True)

print(f"Rendered: {model_name}")
undefined

5. Material Library Application

5. 材质库应用

python
import bpy
python
import bpy

Load material library

Load material library

with bpy.data.libraries.load("/path/to/materials.blend") as (data_from, data_to): data_to.materials = data_from.materials
with bpy.data.libraries.load("/path/to/materials.blend") as (data_from, data_to): data_to.materials = data_from.materials

Apply material to selected objects

Apply material to selected objects

material_name = "GoldMetal" mat = bpy.data.materials.get(material_name)
if mat: for obj in bpy.context.selected_objects: if obj.type == 'MESH': if len(obj.data.materials) > 0: obj.data.materials[0] = mat else: obj.data.materials.append(mat) print(f"Applied {material_name} to {obj.name}")
undefined
material_name = "GoldMetal" mat = bpy.data.materials.get(material_name)
if mat: for obj in bpy.context.selected_objects: if obj.type == 'MESH': if len(obj.data.materials) > 0: obj.data.materials[0] = mat else: obj.data.materials.append(mat) print(f"Applied {material_name} to {obj.name}")
undefined