← 返回技能列表
已验证
emergence-blender-bpy
Blender 3D 自动化控制与建模渲染技能。使用 Python 脚本进行程序化建模、材质、灯光与 Cycles/EEVEE 渲染,并支持 3D 打印 STL 导出。由涌现科学出品。
作者
Emergence Science
版本
2.2.0
发布日期
2026年6月3日
最近更新
2026年6月3日
blender3dmodelingrenderingbpyproceduralautomation3d-printingchinese
安装
复制到 OpenClaw
请从 https://gitee.com/bubble-universe/emergence-blender-bpy 安装智能体技能
文档
Technical Manifest
slug
emergence-blender-bpy
title
Blender 3D 自动化 — Python bpy 脚本控制
description
使用 Blender Python bpy API 进行全面的 3D 自动化控制。包括程序化建模、着色器节点材质、影棚灯光、摄像机控制、照片级 Cycles/EEVEE 渲染及 3D 打印准备。内含齿轮及结晶雪花等代码范例。
version
2.2.0
homepage
https://emergence.science/skills/emergence-blender-bpy
repository
https://gitee.com/bubble-universe/emergence-blender-bpy
tags
blender3dmodelingrenderingbpyproceduralautomation3d-printing
requires
{"bins":["blender"]}
Blender Python 自动化控制与设计 (bpy) — v2.2.0
何时使用此技能
当用户或 Agent 需要通过代码来执行以下操作时,调用此技能:
- 程序化网格建模:生成参数化 3D 物体(例如齿轮、规律结构、建筑构件、分形雪花)。
- 着色器节点材质:使用节点连接来创建精细的材质纹理(金属、拉丝纹理、透明玻璃、磨砂冰晶)。
- 影棚三点布光与摄像机设置:搭建三点灯光,配置摄像机并对其进行动态朝向约束。
- 命令行照片级渲染:无头模式下批量渲染高分辨率静止帧或序列帧。
- Blender 工作流批处理:导入/导出资产并执行自动化几何清理。
- 3D 打印导出:应用 Solidify 与 Decimate 等修改器,并导出适合切片的 watertight (紧密闭合) STL 模型。
前提条件
# 安装 Blender 4.0 或更高版本
apt-get install blender # Linux (Debian/Ubuntu)
# 或: brew install blender # macOS
# 验证安装
blender --version
核心开发模式
1. 无头(后台)命令行运行
在没有图形界面的服务器或后台任务中执行脚本:
blender --background --python script.py
2. 场景初始化与清理
在新建任何模型前,清空场景中所有默认的物体、相机、灯光和旧材质:
import bpy
# 选择所有物体并删除
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. 程序化齿轮网格创建
通过选定角度上的面进行挤出(Extrude)和缩放,程序化创建规则齿轮:
import bpy
import math
def create_gear(name, radius=2.0, teeth=16, thickness=0.8):
"""创建带轴孔的齿轮网格"""
# 添加基础圆柱体
bpy.ops.mesh.primitive_cylinder_add(
vertices=teeth * 4,
radius=radius,
depth=thickness,
location=(0, 0, 0)
)
gear = bpy.context.object
gear.name = name
# 进入编辑模式以选择特定齿顶面进行挤出
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 < tooth_angle * 0.35:
v.select = True
# 挤出并向外缩放生成齿牙
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')
# 使用布尔(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)
# 追加倒角 (Bevel) 和表面细分 (Subdivision) 修改器以圆滑边缘
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. 程序化金属材质(节点着色器)
使用着色器节点树动态生成带拉丝纹理的金属材质:
def create_metal_material(name, base_color, metallic=0.85, roughness=0.25,
noise_scale=30.0, use_brushed=True):
"""创建带噪波拉丝金属质感材质"""
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)
# Principled BSDF(原理化 BSDF)节点
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_coord = nodes.new(type='ShaderNodeTexCoord')
tex_coord.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_coord.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. 三点影棚光源设置
通过主光(Key Light)、辅光(Fill Light)和轮廓光(Rim Light)突出主体的反射与物理轮廓:
def setup_lighting(base_intensity=600):
"""标准的影棚三点光源搭建"""
# 主光源(前侧方,强度最大,决定阴影方向)
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 = 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 = 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. 摄像机设置与动态 Target 朝向追踪
根据目标位置,通过四元数数学公式自动调整摄像机俯仰和偏航角,对齐拍摄中心:
import mathutils
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
# 根据朝向向量计算四元数轨道,自动调整旋转角
direction = mathutils.Vector(target) - cam.location
rot_quat = direction.to_track_quat('-Z', 'Y')
cam.rotation_euler = rot_quat.to_euler()
bpy.context.scene.camera = cam
return cam
7. Cycles & EEVEE 图像渲染与 Mac Metal GPU 加速
配置底层物理渲染引擎属性,并对 macOS 上的 Apple Silicon 芯片进行 Metal 加速优化:
def render(output_path="/tmp/render.png", engine='CYCLES',
width=1080, height=1080, samples=64):
scene = bpy.context.scene
scene.render.engine = engine
scene.render.resolution_x = width
scene.render.resolution_y = height
scene.render.filepath = output_path
scene.render.image_settings.file_format = 'PNG'
if engine == 'CYCLES':
scene.cycles.samples = samples
scene.cycles.use_denoising = True
# 激活 macOS Metal GPU 并检测可用核心
try:
bpy.context.preferences.addons['cycles'].preferences.compute_device_type = 'METAL'
bpy.context.preferences.addons['cycles'].preferences.get_devices()
for d in bpy.context.preferences.addons['cycles'].preferences.devices:
if d.type == 'METAL':
d.use = True
except Exception:
pass
bpy.ops.render.render(write_still=True)
8. 折射玻璃/冰晶节点材质(Transmission/IOR)
创建支持高物理精确度的折射玻璃和冰雪材质(通过 Transmission 穿透属性):
def create_glass_material(name="Glass", color=(0.9, 0.95, 1.0, 1.0), roughness=0.1, ior=1.309):
"""创建物理折射玻璃或冰晶材质。IOR 折射率:1.309(冰),1.5(玻璃)"""
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
nodes.clear()
bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
output = nodes.new(type='ShaderNodeOutputMaterial')
links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])
bsdf.inputs['Base Color'].default_value = color
bsdf.inputs['Roughness'].default_value = roughness
bsdf.inputs['IOR'].default_value = ior
# 启用光线穿透 (Transmission Weight)
if 'Transmission Weight' in bsdf.inputs:
bsdf.inputs['Transmission Weight'].default_value = 1.0
elif 'Transmission' in bsdf.inputs:
bsdf.inputs['Transmission'].default_value = 1.0
return mat
9. 进阶布尔建模(逐一雕刻与多余溢出边界)
在网格上用其他复杂几何体(如管道、环线)雕刻缝隙时:
- 避免一次性整体剪切:如果一次性差集减去一个自身有重叠的复杂网格(例如相互交叉的细管),会导致 EXACT 布尔求解器异常,把整个主网格完全删掉(网格顶点数变为 0)。应该对多条环线进行逐一应用布尔削减。
- 边界必须多余溢出:切割体(Cutter)在切出缝隙时,尺寸边缘一定要超出被切割物的边界外(即更大、更深),切面重合会导致浮点数精度重合,进而导致 EXACT 求解器求解失效而无法切出缝隙。
- 端点加盖:在将样条曲线(Curves)转为网格切割前,必须声明
curve_data.use_fill_caps = True对管道端点加盖,结合细分修改器(Subdivision)可以在端部刻出圆滑过渡。
10. 100% 程序化纹理空间着色器缝隙(免网格切割)
对于球体等规则几何体,为避免切割引起的网格破损和拓扑混乱,优先推荐直接在着色器节点(Shader Nodes)中用物体空间坐标(Object Coordinates)数学公式计算并贴图混合出接缝:
- 篮球缝隙线计算几何公式: $$|x| = \sqrt{1 - z^2} \cos\left(\theta \sqrt{1 - z^2}\right)$$
- 贴图映射与渐变蒙版:将以上距离公式输出映射至
SMOOTHERSTEP差值节点,设定宽度范围得到平滑渐变蒙版。用此蒙版分别去混合基础底色(橘红与黑色接缝)和高度图输入(送入 Bump 节点产生法线凹陷)。
11. 3D 打印准备与闭合流形导出(Solidify与Decimate修改器)
为 3D 打印(如 FDM/SLA)建模时:
- 设定物理比例尺:显式指定系统单位 scale,一般以 1 个 Blender 单位代表 1 cm 或 1 mm:
scene = bpy.context.scene scene.unit_settings.system = 'METRIC' scene.unit_settings.scale_length = 0.01 # 1个单位 = 1 cm - 外壳固化与壁厚:3D 打印无法打印厚度为 0 的数学面片。使用
Solidify修改器赋予壁厚(例如 FDM 打印机最低要求 1.2mm 至 2.0mm 壁厚):solid = obj.modifiers.new(name="Solidify", type='SOLIDIFY') solid.thickness = 0.12 # 如果 1 个单位 = 1 cm,这里代表 1.2 mm 壁厚 solid.offset = -1.0 # 向内收缩固化 - 多边形面数精简:顶点数过高会导致切片软件卡死。在导出前,必须使用
Decimate修改器按百分比削减多边形面数:decimate = obj.modifiers.new(name="Decimate", type='DECIMATE') decimate.ratio = 0.15 # 仅保留原本 15% 的面 - Watertight STL 导出:确保网格闭合流形后,使用标准命令导出 STL:
# Blender 4.0+ bpy.ops.wm.stl_export(filepath="model.stl", export_selected=True) # 旧版本 Blender: # bpy.ops.export_mesh.stl(filepath="model.stl", use_selection=True)
12. 程序化导入三视图背景参考图
若要根据角色原画或三视图进行对齐手工程序建模,可以通过脚本将前视、侧视、顶视图片载入为空背景图(Empty Image Object):
def load_reference_image(filepath, name="ReferenceImage", location=(0, 0, 0), rotation=(1.5708, 0, 0)):
# 添加一个 IMAGE 类型的 Empty 空物体
bpy.ops.object.empty_add(type='IMAGE', location=location, rotation=rotation)
empty = bpy.context.object
empty.name = name
# 加载图片并将其分配给空物体
try:
img = bpy.data.images.load(filepath)
empty.data = img
empty.empty_display_size = 5.0
empty.use_empty_image_alpha = True
empty.empty_image_depth = 'BACK' # 保证参考图显示在模型后面
except Exception as e:
print(f"载入参考图失败: {e}")
渲染引擎对比选择
| 引擎 | 适用场景 | 说明 |
|---|---|---|
BLENDER_EEVEE | 快速预览、实时动画 | 渲染耗时只需 <1 秒,不支持物理折射,适合几何框架的快速核验。 |
CYCLES | 照片级真实感渲染 | 折射玻璃、冰晶、反射重合等的唯一选择。建议配置 samples=64 并开启降噪 (Denoising)。 |
常见问题与排错排坑
- 布尔差集操作后整个模型消失(顶点数 vertices 变为 0)
- 原由:切割体(Cutter)存在自相交,或者切割面的边界和被切模型表面刚好完全重合(Co-incident surface)。
- 解决:检查切割体的网格自交,将布尔解算器(Solver)从
'EXACT'切换至'FLOAT'(旧版叫'FAST'),或者微调切割体位置使其完全溢出重叠。
- 样条曲线 (Curve) 转化为网格后变为了空心细管
- 原由:曲线数据在转换前未进行端点加盖。
- 解决:在运行 convert 转化前,将曲线数据的加盖参数置为真:
curve_data.use_fill_caps = True。
- 透明玻璃或冰晶材质渲染出来一片漆黑或扁平
- 原由:折射材质非常依赖背景光照与反光的面。
- 解决:必须使用 Cycles 渲染器。在模型下方放置一底面板(如 Roughness=0.2, Metallic=0.9 的暗色反射面),并在模型正后上方设置一高强度的轮廓区域背光(Rim Light),光线穿透折射后边缘才会闪闪发光。
- 脚本在不同 Blender 版本之间运行时报错
- 原由:Blender 版本的 bpy API 时常有破坏性更新(例如材质
use_nodes弃用、STL 导出指令修改)。 - 解决:在脚本中优先加入 Python
try-except或版本属性检测(如bpy.app.version)来做兼容适配。
- 原由:Blender 版本的 bpy API 时常有破坏性更新(例如材质
可验证性证明
该技能已通过涌现科学结算中心的分析和验证。它遵循通用惊奇协议(Surprisal Protocol),确保确定性的智能体执行和安全的数据处理。