
单张图片生成3D这个话题在开发圈已经热了很久。以NeRF和3D Gaussian Splatting为代表的重建方案确实能把照片变成可观看、可漫游的体积场景但很多开发者回到 Blender 里想继续编辑时会立刻撞上一堵墙生成出来的东西是“一张立体照片”不是“一个有结构的场景”。没有可控的拓扑、没有规范的对象层级、材质参数磨不动后期改一步都费劲。那如果换一条路呢不让模型直接生成 3D 文件而是让大模型充当“编码 Agent”根据单张图片写出一段 Blender Python 脚本再让 Blender 把这个脚本执行成真正的原生几何体。这就是本文要拆解的技术路线单张图片输入经过多模态理解和编码 Agent 推理输出一份可编辑、可执行的 Blender 程序。先给一个明确判断这条方案的价值不在“生成速度更快”而在“产出物的属性发生了变化”。它把 3D 重建从“生成视觉相似资产”推进到了“生成可进入标准 DCC 工作流的程序资产”。对游戏物件、工业设计、电商建模这类需要反复调整的需求场景这条路可能比直接生成 mesh 更实用。接下来我会从概念、链路、环境、代码实现到排查方法完整梳理这条技术路线。已经跑过类似实验的人可以重点看第 5 节和第 7 节新手建议从头开始看。1. 为什么“可编辑可执行”才是AI 3D重建的真正门槛先说一个很多教程不会点破的真相AI 三维重建早就不是“能不能生成”的问题而是“生成完以后怎么办”的问题。1.1 传统AI 3D方案差在哪从流程上看传统方案可以粗分为两类。第一类是图像生成式重建。输入一张或多张图片模型直接输出 mesh、带纹理的模型文件或体积表示。优点是视觉效果好缺点是拓扑混乱面数不可控UV 接缝自动化程度低模型的各个部件通常被烘焙成一张贴图进入 Blender 后很难拆开修改。你要给模型加一个轮子、调整比例等于重新建模。第二类是体积表示渲染比如 NeRF、3D Gaussian Splatting。它们在渲染和视角合成上效果极强但本质是辐射场或高斯点的集合并不是传统建模工具里的“对象”。开发者拿到这类资产后想放进游戏引擎或动画流程需要先做网格提取、简化、重拓扑、UV 展开等一系列补救操作。这不叫“生成资产完成”这叫“把资产抢救成能用的形状”。换句话说这两类方案解决了“看得像”但没有解决“改得动”。1.2 编码Agent带来的是什么编码 Agent 的路线则不同。它的核心输出不是几何文件而是一段描述如何构建场景的 Python 代码。这段代码运行在 Blender 内部调用 bpy API 创建网格、曲线、灯光、相机和材质。因为执行结果是原生 Blender 对象所以生成后你依然可以使用标准编辑工具在视图中选中对象按 Tab 进入编辑模式修改顶点。在属性面板里调整材质颜色、粗糙度、金属度。给对象套修改器比如倒角、细分、实体化。直接做动画、约束和骨骼绑定。这种资产不再是一次性结果而是“生成即工程文件”。编码 Agent 真正降低的是从 AI 生成结果到 DCC 软件可编辑资产之间的转换成本。下面用一个表格对比三条路线维度传统手工建模图像生成式重建编码Agent生成Blender程序产出物.blend 工程文件mesh/纹理/体积表示Python 脚本 Blender 原生对象可编辑性高差高自动程度低高高拓扑可控性完全可控不可控取决于生成代码的约束后期修改成本低高低上手门槛高低中等所以从工程眼光看“可执行”决定了自动化闭环能不能跑起来“可编辑”决定了生成结果能不能真正进入生产流程。这两点恰好是编码 Agent 方案的强项。2. 核心概念拆解大模型、编码Agent与Blender程序化建模要把这条链路掌握好四个核心概念必须理清大模型的多模态能力、编码 Agent 的工作方式、Blender Python API 的职责、程序化建模的边界。2.1 大模型的“图像理解”到底理解了什么很多初学者会把“输入图片、输出文字”误当成“模型真的看到了图片”。更准确的理解是多模态大模型把图片经过视觉编码器转换成 token 序列再和文本 token 一起送入语言模型进行推理。它理解的是图片中的语义信息比如“这是一个红色茶杯放在木桌上旁边有一把椅子”。在做 3D 场景生成时我们需要的不只是“这有什么物体”还包括物体之间的空间关系茶杯在桌子中间椅子在桌子左侧。大致比例桌子的高度大约是椅子的多少倍。材质暗示桌面看起来像木头茶杯表面有反光。镜头信息图片是从什么角度拍摄的对应 Blender 里的相机方向。大多数多模态大模型在“描述性理解”上很强但在“精确定量理解”上并不稳定。怎么把模糊的理解变成可执行的坐标和参数正是后面要说到的结构化中间表示。2.2 编码Agent从“生成内容”到“生成程序”这里的 Agent 不是指某个具体产品而是一种程序架构让大模型不只做一次生成而是处于一个“理解需求 → 编写代码 → 执行代码 → 查看结果 → 修复错误”的循环中。传统大模型调用一次问答就结束了。编码 Agent 则会获得任务描述。生成一段候选代码。调用执行环境运行代码。读取报错信息或渲染结果。根据失败信息修改代码。重复直到任务完成或达到终止条件。在 3D 场景生成场景中这个循环尤其重要。因为 Blender 脚本一次写对的概率并不高。物体坐标可能重叠、材质命名可能冲突、有些 API 在你的 Blender 版本中已废弃。如果 Agent 有反馈回路就可以把stderr里的错误信息喂回模型继续修复。2.3 Blender Python API 是执行层Blender 内置了完整 Python API模块名是bpy。通过bpy.data访问场景数据通过bpy.ops调用 Blender 内部操作通过bpy.context获取当前上下文。举例来说创建一个立方体只需要三行import bpy bpy.ops.mesh.primitive_cube_add(size2, location(0, 0, 1))创建材质并赋给物体也是常规操作import bpy obj bpy.data.objects[Cube] mat bpy.data.materials.new(nameMyMaterial) mat.use_nodes True mat.node_tree.nodes[Principled BSDF].inputs[0].default_value (0.8, 0.1, 0.1, 1.0) obj.data.materials.append(mat)Blender 还支持命令行执行脚本。你可以让 Agent 生成的代码在完全静默的模式下运行输出渲染图然后自动关闭进程。这让整个流程具备了无人值守的可能性。2.4 程序化建模的意义程序化建模不是新概念。建筑可视化、游戏地图生成、粒子特效里大量使用“用规则生成几何体”的思路。它的优势是可以参数化把半径、高度、段数、偏移量暴露成变量修改参数就可以批量生成变体。当大模型以程序化建模的方式输出场景代码时它对场景的贡献不只是“重建出一个对象”而是“建立了一套可以被调整的生成规则”。比如模型生成了桌子的长宽高参数你后续想让桌子变大改一个变量即可而不需要在 Blender 里手动缩放。这个思维转换是理解整条技术路线的关键。3. 单张图片到Blender程序的技术链路从输入单张图片到最终得到可编辑场景完整链路可以拆成五个环节。3.1 整体流程图片输入用户提供一张照片或渲染图。视觉语义理解多模态大模型读取图片输出场景描述包括物体清单、材质特征、空间关系、相机角度。结构化场景表示把自然语言描述转换成 JSON 或类似编号的数据结构。这一步用来稳定后续代码生成质量。编码 Agent 生成脚本大模型根据结构化描述编写 Blender Python 代码。代码遵循预设模板调用 bpy API 创建对象、材质、灯光和相机。执行与反馈Blender 在命令行模式执行脚本输出渲染图。Agent 对比结果或读取报错判断是否继续修复。3.2 结构化场景描述是承上启下的关键直接让大模型“看图写代码”生成的代码随机性很大。因为它既要理解图片语义又要准确把握 Blender API 的语法两件事同时做成功率必然低。更稳妥的做法是拆成两步第一步让多模态模型输出结构化的场景 JSON。第二步让编码模型基于 JSON 生成代码。结构化 JSON 相当于给大模型画了一条边界。JSON 里没有的物体模型不会擅自创建JSON 里的坐标范围模型不会超出。它把“开放生成”收敛成了“受控生成”。一个最小场景的 JSON 可以长这样{ scene: { objects: [ { name: cup, type: cylinder, radius: 0.5, height: 0.8, position: [0, 0, 0.4] }, { name: table_top, type: cylinder, radius: 2.0, height: 0.1, position: [0, 0, 0.9] } ], materials: [ { name: red_plastic, color: [0.8, 0.1, 0.1, 1.0], roughness: 0.3 } ], camera: { position: [5, -5, 3], look_at: [0, 0, 0.5] } } }这个 JSON 的字段不需要很多。对象名称、几何类型、尺寸、位置、材质颜色足够撑起一个演示场景。项目复杂以后可以增加modifiers、parent、animation等字段。3.3 代码生成与执行反馈循环生成代码只是第一步执行验证才是真正体现 Agent 价值的地方。一个完整的 Agent 循环包含模型生成scene_builder.py。系统调用blender -b -P scene_builder.py执行。若执行失败读取返回的 stderr。将 stderr 追加到对话上下文让模型修复代码。重新执行最多重复若干轮。如果 Agent 支持读取渲染图还可以做更高级的验证比如判断生成结果与输入图片是否在颜色、比例上一致。这个能力目前在很多多模态模型上已经具备但反馈闭环会增加调用成本和延迟建议在工程落地时按需开启。4. 环境准备与前置条件在动手写代码之前先把环境准备这一步做到位。版本问题在 Blender 生态里尤其容易踩坑。4.1 基础环境要求一套可运行的开发环境至少包括Python 3.10 或更高版本用于运行调用大模型的外部脚本。Blender 3.6 LTS 或 Blender 4.xLTS 版本更稳妥4.x 的 API 变化较大。大模型 API 服务多模态能力加代码能力是刚需。网络环境能够访问你选择的模型服务商。如果使用本地部署模型需要额外准备 GPU 与推理服务。Blender 的 Python 是内置的不需要你单独安装。外部脚本只需要处理“把图片转成结构化描述”以及“把代码交给 Blender 执行”这两件事不依赖 Blender 的 Python 环境。4.2 大模型服务选择目前可用的路线有三种。第一种是商业多模态大模型 API。优点是图像理解能力强、代码生成水平高、开箱即用。缺点是按 token 计费反复修复代码会让成本上升。第二种是本地部署的开源模型。优点是数据不出内网、长期成本可控。缺点是需要 GPU且代码生成稳定性和多模态理解能力通常弱于商业模型。开源模型微调出适合 Blender API 的专用模型是完全可行的方向但属于进阶玩法。第三种是“多模态模型 代码模型”组合。让擅长看图的多模态模型输出 JSON再让专门优化过代码生成的模型基于 JSON 编写脚本。两步分离两个模型各司其职整个链路的稳定性会更高。具体选型建议以你手中的算力和预算为准。本文的示例不绑定某个特定服务商只演示通用流程。4.3 版本兼容注意Blender Python API 在不同版本之间有调整。例如旧版本常用bpy.ops.mesh.primitive_uv_sphere_add新版本同样支持。材质节点的节点名称基本稳定但某些节点属性路径会变化。Blender 4.2 引入了新的基础元素工具集部分bpy.ops行为有所变化。所以在让 Agent 生成代码前最好在系统提示词中明确写清楚 Blender 版本。比如“请使用 Blender 4.1 API不要使用实验性功能”。这能显著减少编造 API 的概率。5. 最小可行链路从图片描述到Blender脚本这一节给出一个可以实际跑通的最小链路示例。示例使用“先让大模型输出 JSON再生成代码”的两阶段方式并用命令行把脚本交给 Blender 执行。5.1 第一步写一个调用大模型的生成器假设你已经有一个多模态模型 API可以把图片内容转成场景描述。实践中这个描述既可以来自图片的多模态理解也可以来自人工编写的文字描述。下面的代码演示如何把“图片理解结果”喂给模型并让它输出 Blender 脚本。# demo_generate_scene.py import json import requests # 请替换为你实际接入的大模型服务地址和密钥 API_URL https://your-llm-endpoint/v1/chat/completions API_KEY your-api-key system_prompt 你是 Blender 编程专家。你的任务是根据用户提供的场景描述输出一段可运行的 Blender Python 脚本。 要求 1. 只使用 bpy 标准 API不要引用任何第三方插件。 2. 脚本必须能创建一个基本 3D 场景包括对象、材质、灯光和相机。 3. 输出格式必须是 JSON字段为 {script: 完整Python代码}。 4. 不要输出 JSON 之外的任何内容。 def ask_llm(scene_description: str): headers {Authorization: fBearer {API_KEY}} payload { model: your-multimodal-model, messages: [ {role: system, content: system_prompt}, {role: user, content: scene_description} ], temperature: 0.2 } resp requests.post(API_URL, headersheaders, jsonpayload) resp.raise_for_status() data resp.json() content data[choices][0][message][content] # 大模型输出的 content 是 JSON 字符串这里解析成 dict return json.loads(content)[script] if __name__ __main__: # 实际项目中scene_description 可以来自多模态模型对图片的解析结果 scene_description 一张室内照片红色茶杯放在深色木桌上旁边有一把椅子窗口有柔和光线。 script ask_llm(scene_description) with open(generated_scene.py, w, encodingutf-8) as f: f.write(script) print(已生成 generated_scene.py)这段代码的核心逻辑是系统提示词明确约束了模型的行为范围。模型输出被限定为 JSON避免模型在回复里夹杂解释性文字。生成的脚本保存为generated_scene.py后续交给 Blender 执行。注意不同模型服务商的请求格式可能不同。如果你的模型没有chat/completions接口请按照服务商文档调整请求路径和消息结构。5.2 第二步让输出遵循结构化约束如果你想进一步控制生成结果可以在进入代码生成之前先让多模态模型输出一个场景 JSON。这里演示用 Python 脚本构建议中间层# demo_extract_scene_json.py import json import requests # 与上一步类似的请求封装 def extract_scene_json(image_description: str) - dict: schema_prompt 给定一段图片描述输出一个场景 JSON。 JSON 结构必须包含 objects、materials、camera 三个字段。 objects 中的每个对象包含 name、type、size、position、material 字段。 只输出 JSON不输出解释。 payload { model: your-multimodal-model, messages: [ {role: system, content: schema_prompt}, {role: user, content: image_description} ], temperature: 0.1 } resp requests.post( https://your-llm-endpoint/v1/chat/completions, headers{Authorization: Bearer your-api-key}, jsonpayload ) content resp.json()[choices][0][message][content] return json.loads(content) if __name__ __main__: scene extract_scene_json(图片中有一个人形机器人站在一个圆台上旁边有蓝色背景光。) with open(scene.json, w, encodingutf-8) as f: json.dump(scene, f, ensure_asciiFalse, indent2) print(已生成 scene.json)这个中间 JSON 的价值在于可以人工检查。模型生成的场景描述有没有漏掉物体比例是否明显不对都可以在这个阶段被修正。把问题挡在代码生成之前比让 Agent 反复改代码更省钱。5.3 第三步在Blender中执行与验证接下来是执行环节。可以用 Blender 命令行模式运行脚本blender -b -P generated_scene.py -- --output /tmp/render.png说明-b表示后台模式不打开 Blender 窗口。-P表示执行指定的 Python 脚本。--后面的参数会传递给脚本内部使用的sys.argv可以用于自定义输出路径。也可以直接在 Blender 界面中运行。打开 Blender进入 Scripting 工作区新建一个文本块把generated_scene.py的内容粘贴进去点击 Run Script。这种方式的优点是能立即看到场景结果方便调试。如果脚本中包含渲染输出逻辑你会在/tmp/render.png得到渲染图。打开图片就能直观判断场景是否符合预期。6. 运行结果与效果验证代码写完后如何合理地判断实验结果是否成功这里提供一套可复用的判断指标。6.1 预期结果如果一切正常预期结果包括Blender 后台执行没有报错退出码为 0。场景中出现与描述相符的对象。对象可以在 Blender 的 Outliner 面板中独立选中。材质面板可以编辑颜色和粗糙度。渲染图能看出基本的光影关系。6.2 判断指标判断一个脚本是否“合格”建议按这几个层次检查执行层脚本能否无错运行。语义层场景里是不是确实有“红色茶杯”“木桌”“椅子”这些对象。空间层对象之间是否碰撞、比例是否合理、相机能否拍到所有物体。参数层材质粗糙度有没有设置、灯光强度是否自然。编辑层在 Blender 中选择对象并进入编辑模式能否对网格进行实际修改。对于演示项目达到前四层就足够。如果你要做生产级工具第五层才是真正需要重点关注的。6.3 失败时先看哪里失败最可能出现在两个位置第一个是脚本执行报错。这类问题看 stderr 即可。最常见的错误是调用了不存在的属性或 API比如把bpy.data.materials.new写成了bpy.data.materials.create。把 stderr 回传给编码 Agent让它修复即可。第二个是渲染图“看起来不对”。这通常不是语法问题而是语义问题。比如物体位置重叠、比例失调、材质颜色偏差。这类问题需要把渲染图或结构化的场景 JSON 作为反馈再次交给多模态模型分析。如果脚本内置了渲染输出逻辑建议脚本最后打印渲染图的保存路径方便定位import bpy bpy.context.scene.render.filepath /tmp/render.png bpy.ops.render.render(write_stillTrue) print(Render saved to /tmp/render.png)7. 常见问题与排查思路下面整理了一批在这条链路中最常出现的问题按现象、原因、排查方式、解决方案四个维度给出建议。问题现象可能原因排查方式解决方案脚本执行报错module bpy has no attribute xxx模型编造了不存在的 bpy 属性查看 stderr 中的报错位置对照当前 Blender 版本文档核对在系统提示词中限定 Blender 版本把报错信息返回给模型修复场景中生成了错误的物体多模态模型对图片理解有偏差对比输入图片与输出场景 JSON增加图片描述步骤人工校正 JSON 后再生成代码所有物体挤在一起模型生成坐标时没有考虑物体尺寸检查 JSON 中 position 字段要求模型根据对象尺寸自动计算坐标偏移或增加碰撞检测脚本材质全部是默认灰色模型没有创建 Principled BSDF 节点并赋值打开材质面板查看节点树在系统提示词中明确要求创建材质并设置基础颜色灯光太暗或曝光过度灯光参数不匹配查看渲染图直方图让模型输出灯光类型、强度和位置参数避免全默认Agent 反复修改代码仍失败反馈信息不完整检查喂给模型的是不是完整 stderr把完整错误信息、当前脚本片段一并作为上下文返回执行脚本后 Blender 长时间无响应生成的代码里有高细分网格或死循环查看 CPU 占用检查代码中是否有while True在生成代码中限制网格段数建议外层加超时控制中文描述生成代码偏弱模型训练数据中英文代码占比高尝试将中文描述翻译成英文提示词保持中文场景描述但要求代码注释和对象命名尽量用英文这一批问题覆盖了从模型理解、代码生成到执行验证的主要环节。遇到新问题时排查思路可以固定为先定位是“语法层错误”还是“语义层错误”。语法层错误靠日志修复语义层错误靠反馈循环和人为校验。8. 最佳实践与工程建议如果你决定把这个实验推向更正式的工程阶段以下建议值得认真考虑。8.1 约束输出格式摆脱“代码不稳定”编码 Agent 生成代码时最大的工程风险是输出不可控。同样一句话模型今天输出圆柱体明天可能输出锥体。约束手段很有必要强制 JSON 输出格式。在 JSON Schema 中限定允许的几何体类型。禁止模型使用实验性 API 和第三方扩展。要求模型为每个对象添加name字段避免后续引用混乱。输出越稳定后面的验证、测试、批量生成就越轻松。宁可前期多花一点 prompt 设计时间也不要不断靠“运气生成”。8.2 建立反馈循环而不是一次性生成一次性生成的成功率很难达到生产要求。实际工程中我建议把“生成 → 执行 → 查看结果 → 修复”四步封装成一个可重复执行的任务类。一个简化的 Python 示意如下import subprocess def run_blender_script(script_path: str): result subprocess.run( [blender, -b, -P, script_path], capture_outputTrue, textTrue, timeout60 ) return result.returncode, result.stdout, result.stderr def agent_loop(script_path: str, max_attempts: int 3): for attempt in range(1, max_attempts 1): code, stdout, stderr run_blender_script(script_path) if code 0 and Traceback not in stdout: print(场景生成成功) return True # 在真实项目中这里把 stderr 返回给大模型让模型生成修复后的脚本 print(f第 {attempt} 次尝试失败错误信息已返回给模型) return False if __name__ __main__: agent_loop(generated_scene.py)这套结构的好处是容易扩展。你可以把“渲染结果图片”加入验证条件也可以把“对象数量是否符合 JSON”加入验证条件。8.3 代码执行安全问题这里要非常严肃地提醒Agent 生成的代码不应该在没有沙箱的机器上直接执行。大模型的代码生成质量再高也可能因为训练数据中的模式产生意外行为。生产环境中执行环境需要做到使用独立容器或虚拟机运行 Blender 脚本。限制脚本访问网络和文件系统的权限。设置执行超时时间避免死循环占用资源。对脚本内容做基础过滤禁止明显危险的操作比如删除文件、修改系统路径。如果你是在自己的开发机上做实验至少也应该做到“随时能终止进程、定期备份项目文件”。这一点不是过度谨慎而是在承认当前大模型能力边界的前提下给自己留好退路。8.4 从“生成单一物体”升级到“生成参数化资产”如果只是生成一个杯子、一张桌子这条链路价值有限。真正值得投入的方向是让 Agent 生成参数化资产。举个例子。与其让模型输出一个固定坐标为(1.5, 0.5, 0.3)的杯子不如要求模型生成一个接收参数的函数import bpy def create_cup(radius0.5, height0.8, segments16, location(0, 0, 0.4)): bpy.ops.mesh.primitive_cylinder_add( radiusradius, depthheight, verticessegments, locationlocation ) return bpy.context.object if __name__ __main__: cup create_cup(radius0.5, height0.8) cup.name Generative_Cup参数化之后同一个函数可以生成数十个尺寸变体。这让 Agent 从“搭建一个场景”升级为“建立一套场景生成规则”。在大规模内容生产场景里这个升级能带来数量级的效率提升。8.5 成本与效率控制大模型 API 按 token 计费Agent 的“多轮修复”特性会显著增加成本。控制成本的方式包括尽量用两次单轮调用替代多轮 Agent 循环。第一次调用只提取结构化 JSON第二次调用才生成代码。修复阶段只把错误日志和对应代码段发给模型不要发送完整场景描述。设置最大尝试次数超过上限就转人工。从实际项目经验看先提取 JSON 再生成代码成功率通常高于直接生成代码而且总 token 消耗更低。因为一次结构化的准确描述远好过让模型在错误中反复试错。9. 总结与后续方向这条“大模型编码 Agent Blender”的技术路线本质上是把三维重建问题的定义换掉了。传统重建任务追求“生成一个看得像的 3D 资产”而这个方案追求“生成一段能让 Blender 现场搭出场景的程序”。它不一定在所有场景下都比直接生成 mesh 更好但在需要资产落地、需要调整、需要进入标准美术流程的场景中它的工程价值明显更高。如果你准备自己尝试我建议的最小实践路径是先跑通“文字描述 → 大模型生成脚本 → Blender 执行”这条最简链路。再引入多模态模型实现“图片描述 → 结构化 JSON → 代码生成”。然后加入反馈循环让 Agent 有能力根据报错和渲染图自我修复。最后把脚本包装成可调的参数化函数逐步建立你自己的 3D 资产生成库。后续值得深入的方向包括针对 Blender API 的代码模型微调、开源模型的本地化部署、场景级数据集构建、以及把编码 Agent 与渲染验证步骤合并成一条标准流水线。如果你已经在做类似项目一个很实际的建议是先把“执行验证”这个环节做扎实。因为 Agent 能不能稳定产出可执行代码瓶颈往往不在模型写代码的能力而在你给它的反馈环境是否足够清晰。