Blender 3D Automation Enhanced
/install blender-bpy-enhanced
Blender Python Automation (bpy) — v2.0.0
When to Use This Skill
Invoke when the user wants to:
- Create 3D objects procedurally (gears, mechanical parts, architectural elements)
- Set up materials with node-based textures (metal, brushed, procedural)
- Configure 3-point lighting and camera
- Render still images or animations in headless mode
- Batch process or automate Blender workflows
- Export to GLB/glTF for web or game engines
Prerequisites
# Install Blender
apt-get install blender # Linux (Debian/Ubuntu)
# Or: brew install blender # macOS
# Verify
blender --version
Core Patterns
1. Headless Execution
blender --background --python script.py
2. Scene Setup
import bpy, math
# Clear scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for mat in list(bpy.data.materials):
bpy.data.materials.remove(mat)
3. Procedural Gear Creation
def create_gear(name, radius=2.0, teeth=16, thickness=0.8):
"""Create a gear with teeth and center hole"""
# Base cylinder
bpy.ops.mesh.primitive_cylinder_add(
vertices=teeth * 4,
radius=radius,
depth=thickness,
location=(0, 0, 0)
)
gear = bpy.context.object
gear.name = name
# Edit mode: select vertices at tooth positions
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='DESELECT')
for v in gear.data.vertices:
angle = math.atan2(v.co.y, v.co.x)
tooth_angle = 2 * math.pi / teeth
angle_diff = abs((angle % tooth_angle) - tooth_angle / 2)
if angle_diff \x3C tooth_angle * 0.35:
v.select = True
# Extrude and scale for teeth
bpy.ops.mesh.extrude_region_move(
TRANSFORM_OT_translate={"value": (0, 0, 0)}
)
bpy.ops.transform.resize(
value=((radius + 0.4) / radius,) * 2 + (1,),
orient_type='GLOBAL'
)
bpy.ops.object.mode_set(mode='OBJECT')
# Center hole via Boolean
bpy.ops.mesh.primitive_cylinder_add(
vertices=32, radius=0.5,
depth=thickness * 1.5, location=(0, 0, 0)
)
cutter = bpy.context.object
bool_mod = gear.modifiers.new(name="Hole", type='BOOLEAN')
bool_mod.operation = 'DIFFERENCE'
bool_mod.object = cutter
bpy.context.view_layer.objects.active = gear
gear.select_set(True)
bpy.ops.object.modifier_apply(modifier="Hole")
bpy.data.objects.remove(cutter, do_unlink=True)
# Modifier stack
bevel = gear.modifiers.new(name="Bevel", type='BEVEL')
bevel.width = 0.05; bevel.segments = 2; bevel.limit_method = 'ANGLE'
subdiv = gear.modifiers.new(name="Subdivision", type='SUBSURF')
subdiv.levels = 1; subdiv.render_levels = 2
return gear
4. Procedural Metal Material (Node-based)
def create_metal_material(name, base_color, metallic=0.85, roughness=0.25,
noise_scale=30.0, use_brushed=True):
"""Create a procedural metal material with optional brushed effect"""
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
nodes.clear()
output = nodes.new(type='ShaderNodeOutputMaterial')
output.location = (400, 0)
bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
bsdf.location = (0, 0)
bsdf.inputs['Base Color'].default_value = base_color
bsdf.inputs['Metallic'].default_value = metallic
bsdf.inputs['Roughness'].default_value = roughness
if use_brushed:
tex = nodes.new(type='ShaderNodeTexCoord')
tex.location = (-400, 100)
noise = nodes.new(type='ShaderNodeTexNoise')
noise.location = (-200, 0)
noise.inputs['Scale'].default_value = noise_scale
noise.inputs['Detail'].default_value = 2.0
ramp = nodes.new(type='ShaderNodeValToRGB')
ramp.location = (0, 100)
ramp.color_ramp.elements[0].color = (
base_color[0]*0.8, base_color[1]*0.8, base_color[2]*0.8, 1.0)
ramp.color_ramp.elements[1].color = (
base_color[0]*1.1, base_color[1]*1.1, base_color[2]*1.1, 1.0)
links.new(tex.outputs['Object'], noise.inputs['Vector'])
links.new(noise.outputs['Fac'], ramp.inputs['Fac'])
links.new(ramp.outputs['Color'], bsdf.inputs['Base Color'])
links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])
return mat
5. 3-Point Lighting Setup
def setup_lighting(base_intensity=600):
"""Standard 3-point lighting: key, fill, rim"""
# Key light (main)
key = bpy.ops.object.light_add(
type='AREA', location=(5, -4, 6),
rotation=(0.8, 0, 0.7))
key = bpy.context.object
key.data.energy = base_intensity
key.data.size = 4
# Fill light
fill = bpy.ops.object.light_add(
type='AREA', location=(-4, 3, 3),
rotation=(0.5, 0, -1.0))
fill = bpy.context.object
fill.data.energy = base_intensity * 0.5
fill.data.size = 3
# Rim/back light
rim = bpy.ops.object.light_add(
type='AREA', location=(0, 5, 5),
rotation=(0.5, 0, 1.57))
rim = bpy.context.object
rim.data.energy = base_intensity * 0.4
rim.data.size = 2
6. Camera Setup
def setup_camera(location=(5.5, -4.5, 3.5), target=(0, 0, 0)):
bpy.ops.object.camera_add(location=location)
cam = bpy.context.object
# Point camera at target
direction = (target[0] - location[0],
target[1] - location[1],
target[2] - location[2])
cam.rotation_euler = (
math.asin(direction[2] / math.sqrt(sum(d**2 for d in direction))),
0,
math.atan2(direction[1], direction[0]) + math.pi/2
)
bpy.context.scene.camera = cam
return cam
7. Rendering
def render(output_path="/tmp/render.png", engine='BLENDER_EEVEE',
width=1920, height=1080, percentage=50):
scene = bpy.context.scene
scene.render.engine = engine
scene.render.resolution_x = width
scene.render.resolution_y = height
scene.render.resolution_percentage = percentage
scene.render.filepath = output_path
scene.render.image_settings.file_format = 'PNG'
bpy.ops.render.render(write_still=True)
print(f"✅ Rendered: {scene.render.filepath}")
Complete Demo: Procedural Gear
See scripts/demo_gear.py for the full working demo.
blender --background --python scripts/demo_gear.py
Output: /tmp/blender_demo_gear.png and /tmp/blender_demo_gear.blend
Render Engines
| Engine | Best For | Notes |
|---|---|---|
BLENDER_EEVEE |
Fast preview, real-time | No denoiser needed, good for demos |
CYCLES |
Photorealistic | Needs OpenImageDenoiser; use samples=128 for quick tests |
Common Pitfalls
- Render fails with "Build without OpenImageDenoiser" → Switch to Eevee:
scene.render.engine = 'BLENDER_EEVEE' - Boolean modifier not applying → Set
gear.select_set(True)andbpy.context.view_layer.objects.active = gearfirst - Bmesh edit mode errors → Always call
bpy.ops.object.mode_set(mode='EDIT')beforebmesh.from_edit_mesh() - Material not showing on export → Must assign to object's face data:
obj.data.materials.append(mat) - Grid primitive fails → In Blender 4.0+, use
x_subdivisions=Nandy_subdivisions=Ninstead ofsubdivisions=N - Headless EGL warnings → These are harmless; Eevee falls back to surfaceless rendering automatically
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install blender-bpy-enhanced - After installation, invoke the skill by name or use
/blender-bpy-enhanced - Provide required inputs per the skill's parameter spec and get structured output
What is Blender 3D Automation Enhanced?
Comprehensive Blender automation via Python bpy API. Procedural modeling, material nodes, lighting, rendering, and asset generation. Includes verified gear/m... It is an AI Agent Skill for Claude Code / OpenClaw, with 35 downloads so far.
How do I install Blender 3D Automation Enhanced?
Run "/install blender-bpy-enhanced" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Blender 3D Automation Enhanced free?
Yes, Blender 3D Automation Enhanced is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does Blender 3D Automation Enhanced support?
Blender 3D Automation Enhanced is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Blender 3D Automation Enhanced?
It is built and maintained by emergencescience (@emergencescience); the current version is v2.0.0.