最近在折腾用 Codex 辅助 Blender 做 Tiny Glade 风格的小树,前前后后改了五六版,树冠从“一堆土豆”进化到“勉强能发朋友圈”,过程里最大的感受是:问题不在 Codex 不会写代码,而是我不知道该怎么跟它提需求。如果你也卡在“生成的树怎么看都不像”这个环节,这篇内容应该能帮你省下不少时间。
先说结论:Codex 不是美术,它不知道 Tiny Glade 的树应该长什么样。它擅长的是把“描述清楚的命令”变成可运行的 Blender Python 脚本,但“描述清楚”这件事,恰恰是大多数人的盲区。所以这篇文章我不会只甩一个脚本给你,而是会把整件事拆成三个部分:先让你看懂 Tiny Glade 风格的核心视觉特征,再讲怎么用 Codex 高效拆任务、改代码,最后给一套完整的排查方法和三轮修改复盘。适合正在用 Codex 或其他 AI 编程工具做 Blender 小项目的朋友,也适合那些连 Blender 都没装但想知道“AI 辅助建模到底怎么落地”的人。
1. 别急着让 Codex 写树,先拆解 Tiny Glade 风格到底长什么样
1.1 童话树木的五个视觉特征
Tiny Glade 里的树,第一眼给人的感觉是“精致但不写实”。如果你把参考图放到最大,会发现它的树冠并不是由密密麻麻的叶片组成的,而是由好几个大小不一的“团块”拼在一起的。这些团块有点像棉花糖,也有点像儿童绘本里的简笔画树,排布得看上去很随意,但又有一个明确的整体轮廓。
我把这种风格拆成五个可量化的特征,方便后面写提示词和调参数时对照:
- 树干短粗,有明显锥度,底部比顶部粗很多,和真实树木细长的比例完全不同
- 树干通常带一点弯曲,但幅度很小,像被风吹歪了一点,不是那种夸张的 S 形
- 树冠由 5 到 15 个球状或椭球状团块组成,团块之间相互重叠,而不是彼此分离悬浮
- 整体树冠轮廓偏扁,接近横椭圆,而不是圆球,因为很多参考图里树冠水平方向明显大于垂直方向
- 材质是低饱和度的莫兰迪色系,绿色偏灰偏黄,没有高光,也没有明显的纹理细节
这几点就是“像不像 Tiny Glade”的底层标准。你拿这个标准和自己的模型逐条对照,很快就能定位是哪一步出了问题。比如你说“树冠太碎”,本质上是团块数量太多或大小分布太均匀;你说“树干像电线杆”,本质上是没有锥度,也没有弯曲。
这个拆解过程不能省。因为 AI 写代码是按“特征”来的,不是按“感觉”来的。你如果只说“帮我做一棵 Tiny Glade 风格的树”,Codex 只能猜,猜出来的结果自然随机性很大。
1.2 为什么写实树的生成逻辑在这里完全失效
Blender 里常见的树生成方案,比如自带的 Sapling Tree Gen 插件,或者 MTree,目标都是生成写实树木:枝干要分叉,细枝要多,叶片要小,整体要符合植物学规律。这套逻辑在 Tiny Glade 风格这里几乎全部作废。
Tiny Glade 的树冠不需要枝条细节,你如果把枝干暴露出来太多,反而会显得“太真”;叶片也不能是细碎的小面片,否则渲染出来就是一片噪点,完全没有童话感。也就是说,如果你从一开始就走“先生成真树,再改造风格”的思路,后面所有轮次的修改都是在跟默认参数较劲,怎么改都别扭。
这也是我反复跟 Codex 强调“不要使用任何树生成插件”的原因。我们需要的不是植物学模拟,而是“一坨球体 + 一个锥形树干”的最低配组合。想通了这一点,整个生成逻辑就清晰了:树干用一个锥台,树冠用一组随机分布但相互重叠的球体,材质和光照负责氛围。就这么简单。
2. 和 Codex 正确协作的第一课:把大需求拆成“可修改的小任务”
2.1 一句话需求是灾难的起点
我见过很多人第一次用 Codex 时会直接输入:“用 Python 在 Blender 里生成一棵 Tiny Glade 风格的树。”然后 Codex 会返回一个看起来很完整、实际跑起来漏洞百出的脚本。不是 Codex 能力不行,而是这个问题太大了,大到它必须替你做出无数个你认为“不需要交代”的决定。
比如它可能会默认树干是直的,默认树冠用 20 个均匀分布的球体,默认球体之间互不重叠,默认颜色是纯绿色。这些默认值每一个单独拿出来都能改,但合在一起就离 Tiny Glade 十万八千里。等你看到结果再说“不像”的时候,Codex 也搞不清你具体指的是哪个地方不像。
正确做法是:把整棵树拆成几个可以独立验证的小任务,分别让 Codex 生成代码,然后拼装起来。我通常拆成四份:
- 树干生成:包含高度、底部半径、顶部半径、弯曲量
- 树冠分布:包含球体数量、大小范围、重叠程度、整体轮廓形状
- 材质创建:包含基础颜色、粗糙度、高光强度
- 随机控制:包含全局随机种子,保证每次生成的版本可复现
这样做的好处是,当某一轮调整后树变得不像了,你能很清楚地知道是哪个子任务出了问题,而不是面对一坨 300 行的代码无从下手。
2.2 用“参数脚本”代替“成品脚本”
核心心态转变在这里:不要让 Codex 给你一个“一次成型”的脚本,而要让 Codex 给你一个“满是旋钮”的脚本。
所谓参数脚本,就是把所有关键数值都暴露到文件顶部,像这样:
# 树干参数 trunk_height = 2.0 trunk_radius_bottom = 0.18 trunk_radius_top = 0.09 trunk_bend = 0.2 # 树冠参数 crown_radius = 1.4 cluster_count = 24 cluster_min_r = 0.35 cluster_max_r = 0.7 overlap = 0.6 seed = 42之后你不是在“重新写代码”,而是在“调节旋钮”。Tiny Glade 风格本来就是一种感觉,感觉这种东西只能靠一遍遍调节逼近,不可能一步到位。参数脚本的意义就是让你把调参成本降到最低,改一个数字、点一次运行,马上看到结果。
我一般会先让 Codex 生成一个最基础的版本,然后把自己在 Blender 里看到的问题反馈给它,比如“树冠团块间距太大,请让它们互相重叠多一点”,这样每一轮修改都在前一轮基础上做局部变化,比反复推翻重来高效得多。
2.3 给 Codex 的提示词模板
如果你不知道怎么开口,可以参考我常用的模板。这个模板遵循“背景 + 目标 + 参数 + 约束”的结构,尽量消除歧义:
你是 Blender Python 脚本专家。我想在 Blender 4.0 中用 bpy 生成一棵 Tiny Glade 风格的卡通树。 暂时不要使用任何树生成插件,只用基础网格。 请实现: 1. 一棵树干,使用八边形锥台,底部半径 0.18,顶部半径 0.09,高度 2.0。 2. 树干使用 Bezier 曲线做轻微弯曲,偏移量控制在 0.2 左右。 3. 树冠由 24 个球体组成,球体中心随机分布在以树干顶部为中心、半径 1.4 的扁球体内。 4. 球体半径范围 0.35 到 0.7,越靠近边缘越小。 5. 球体之间需要明显重叠,不要悬浮分离。 6. 使用参数 seed = 42,保证每次运行生成结果一致。 7. 把所有参数放在脚本顶部,方便我手动调节。这段提示词里没有出现“像 Tiny Glade”这种主观描述,而是把风格翻译成了具体的数值和规则。Codex 对这类提示词的完成质量会高很多。如果你有 Tiny Glade 的参考图,并且用的是多模态版本的 Codex,可以在提示词里附上参考图,然后补充一句“参考图的树冠是横向扁椭圆,颜色是低饱和度的灰绿色”,效果还会更好。
3. 手把手做一棵可调参的 Tiny Glade 树
3.1 环境与工作流
先说环境。我用的是 Blender 4.0 和 Codex 桌面版。Codex 负责根据对话生成和修改 Python 脚本,Blender 负责运行脚本、实时查看结果。两者不需要有任何插件联动,你只需要把 Codex 生成的代码复制到 Blender 的 Scripting 工作区,点一下运行按钮就行。
有一点必须提醒:不要在正在做项目的文件里直接跑生成脚本。新建一个空白文件,专门用于测试树。因为脚本一旦清了场景,很可能把你原本的模型也一起删掉,这种事故我至少碰到过两次。把测试文件和正式文件分开,是零成本但极其有效的习惯。
运行环境确认无误后,工作流通常是这样的:
- 在 Codex 里描述当前想要的效果,让它生成或修改代码
- 把代码粘贴到 Blender 脚本编辑器,运行
- 在 3D 视口中旋转观察,截图或直接描述问题
- 把问题反馈给 Codex,重复第一到第三步
3.2 树干:锥度比弯曲重要
很多人觉得“树干不像”,第一反应是加弯曲,其实锥度才是关键。Tiny Glade 的树干看上去是那种稳稳戳在地里的感觉,底部明显比顶部粗,而不是一根均匀的圆柱。所以在代码里我用的不是圆柱,而是锥台:
bpy.ops.mesh.primitive_cone_add( vertices=8, radius1=0.18, radius2=0.09, depth=2.0, location=(0, 0, 1.0), ) bpy.context.active_object.name = "TinyTree_Trunk"注意 Blender 里锥台的原点在几何中心,所以如果你希望底部落在地面上,location 的 z 值要设成高度的一半,也就是 1.0。八边形而不是十六边形,是为了保持低多边形的手工感,渲染时在轮廓上能看到一点点硬边,反而更贴近童话绘本的插画质感。
弯曲可以后面再加。一个稳妥的做法是给树干添加一个简单变形,而不是真的用曲线去建模,因为曲线的可控性对新手不友好。最简单的方式,是在树木生成完后,给树干对象加上一个位移修改器,或者直接用 Codex 生成一段“把顶点沿 x 轴偏移 0.2”的代码。只要幅度小,看起来就自然。
3.3 树冠:球体团块的分布逻辑
树冠是“像不像”的重头戏。我用的是最直白的方法:在树冠应该存在的区域里随机撒一堆球体。
但随机撒也不是完全随机,需要加几个约束:
第一,整体区域是一个扁球体,不是正球体。Tiny Glade 的树冠横向宽、纵向薄,所以我在代码里把 x 和 y 的随机范围设置得比 z 大。
第二,越靠近边缘,球体越小。这样树冠轮廓不会是一条平滑的弧线,而会有一点点参差不齐的绒毛感。实现方式很简单:计算球体中心到树干顶部的水平距离,距离越远,半径乘上一个缩小的系数。
第三,球体之间要有重叠。这是很多人最容易忽略的一点。如果你把球体当成互不接触的个体去随机分布,出来的效果就是一棵“长满棒棒糖的树”,而不是一团蓬松的云。要让球体重叠,最简单的方法是把数量调大,同时让位置分布更密集。
第四,z 方向的范围不能太夸张。树冠底部通常从树干高度的一半开始,顶部略高于树干顶端,整体像一个被压扁的帽子扣在树干上。
我让 Codex 写的核心循环大概是这个思路:
import bpy import random from mathutils import Vector random.seed(42) trunk_height = 2.0 crown_radius = 1.4 cluster_count = 24 for i in range(cluster_count): x = random.gauss(0, crown_radius * 0.45) y = random.gauss(0, crown_radius * 0.45) z = random.gauss(trunk_height + 0.4, crown_radius * 0.35) z = max(trunk_height * 0.8, min(z, trunk_height + crown_radius * 0.7)) dist = Vector((x, y, z - trunk_height)).length r = random.uniform(0.35, 0.7) * (1.0 - 0.4 * min(1.0, dist / crown_radius)) bpy.ops.mesh.primitive_uv_sphere_add( radius=r, location=(x, y, z), ) bpy.context.active_object.name = f"TinyTree_Cluster_{i:02d}"这里用random.gauss而不是random.uniform,是因为高斯分布会让更多球体集中在中心区域,边缘球体少且小,更容易形成一团一团的蓬松轮廓,而不是均匀散开的一堆点。这个方法是我在跟 Codex 反复试错后总结出来的,效果比纯均匀随机好得多。
3.4 材质与光照:风格感最后一步
模型对了以后,材质和光照才是“那口气”的来源。Tiny Glade 的颜色不是那种饱和度很高的草绿,而是像蒙了一层灰的莫兰迪绿。我用的基础色大约是 RGB 0.5、0.62、0.42,粗糙度拉到 0.8 以上,高光调低,基本去掉金属感。
在 Blender 里创建材质的代码片段可以参考:
mat = bpy.data.materials.new("TinyTree_Leaf") mat.use_nodes = True bsdf = mat.node_tree.nodes["Principled BSDF"] bsdf.inputs["Base Color"].default_value = (0.5, 0.62, 0.42, 1.0) bsdf.inputs["Roughness"].default_value = 0.8 bsdf.inputs["Specular"].default_value = 0.1给所有树冠球体赋上这个材质。如果你想让层次更丰富,可以在后续版本里再做“顶部亮、底部暗”的渐变,但起步阶段一个统一的柔光材质就够用了。
光照方面,默认的太阳光容易产生过硬的阴影,不适合这种童话风格。建议用面积光,摆在前上方偏侧的位置,阴影柔和。世界环境可以加一个淡蓝色或淡米色的背景,让整体色调偏暖偏干净。渲染器用 Cycles 或 Eevee 都可以,Eevee 快,配合柔和光照照样能出效果。
4. 每次说“不像”的时候,到底在说什么?排查对照表
4.1 症状-原因-调整方向对照表
如果你已经在用 Codex 反复改代码,但总感觉差一口气,建议对照这张表,把模糊的“不像”翻译成具体的“哪里不像”。
| 现象 | 可能原因 | 调整方向 |
|---|---|---|
| 树冠像一串串棒棒糖 | 球体之间没有重叠,或团块数量太少 | 降低位置分布范围,增大球体半径,提高重叠率 |
| 树冠太圆,像一个球 | 生成区域用的是正球体 | 把 z 方向的范围压扁,让轮廓变成横椭圆 |
| 边缘太整齐,没有蓬松感 | 所有球体大小一样 | 边缘球体半径缩小,中心球体半径放大 |
| 树干像垂直的电线杆 | 缺少锥度或弯曲 | 改成半径上小下大的锥台,加一点弯曲变形 |
| 树太高,主体失衡 | 树干高度和树冠半径比例不对 | 树干高度设为树冠半径的 1 到 1.5 倍 |
| 颜色太艳,塑料感强 | 材质高光偏高、饱和度偏高 | 降低饱和度,降低高光,提高粗糙度 |
| 整体氛围不对 | 默认灯光太硬,背景太脏 | 用面积光+柔和阴影,世界材质换淡色 |
这张表不是标准答案,而是一个排查思路。每次改完代码,拿出参考图,从上往下逐条比对,一定能找到最需要改的那个点。
4.2 如何把“不像”翻译成 Codex 能懂的话
很多人在 Codex 里说的最多的一句话就是“还是不像”。这句话对 AI 来说几乎等于没说。Codex 不知道你指的是颜色不像,还是轮廓不像,还是树冠分布不像。
我总结了一个反馈句式,按照“当前现象 + 期望效果 + 可量化参数”的结构来写:
现在的树冠团块有 24 个,半径在 0.35 到 0.7 之间,但看起来太分散,彼此之间几乎没有重叠。 我希望团块之间互相重叠,整体轮廓更接近一个扁球体,中心团块半径约 0.8, 边缘团块半径约 0.4,且位置分布在半径 1.2 的扁球体内。请修改随机生成逻辑。这样描述之后,Codex 的修改通常一次就能命中。因为它不再需要猜测“不像”是什么意思,你直接告诉它改哪里、改成什么样。这个能力其实不需要多高的提示词技巧,只是把你在 Blender 里看到的现象说出来,再补上数字,就成了。
4.3 一次只改一个变量
这是我在反复迭代中最大的教训。刚开始我总觉得“这轮要把树冠、树干、材质一起改到位”,结果每个部分都动了,一旦效果不好,根本分不清是哪个改动导致的退步。后来我改成一次只改一个变量,改完先固定 seed 重新生成,截图对比,确认满意了再动下一个变量。
固定 seed 也很关键。如果 seed 不固定,哪怕你一行代码都没改,每次运行生成的树也长得完全不一样。这样你根本无法判断“这版变好了”是改代码的效果,还是纯粹运气好。把 seed 固定住,比如seed = 42,再配合参数化脚本,你就能做到每次只验证一个变量,迭代效率直接翻倍。
另一个小技巧是给每个版本命名存档。比如“v1_seed42_overlap0.4.blend“、“v2_seed42_overlap0.6.blend”,区别只在文件名里就能看出来。这样就算某个参数改坏了,也能很喜欢回到上一个版本重新试,不用从头再来。
5. 三轮修改复盘:从“西兰花”到“能看的童话树”
5.1 第一轮:乱撒球体,树冠变成串串
我第一次拿到 Codex 生成的脚本时,树冠是在一个正球体内均匀随机撒了 20 个大小完全相同的球体。运行结果是:树冠像一个超大的草莓,表面鼓着一个个大小一样的包,间距很大,边缘没有任何蓬松感,整体看起来像长满瘤子的柱子。
当时我还没学会“把感觉翻译成参数”,只知道闷头让 Codex 改。改了两轮后,树冠从“草莓”变成了“西兰花”,虽然比第一版好一点,但还是不像童话树。真正让我意识到问题的是我拿参考图放到旁边,把两棵树并排截图,才发现最大的差别是“整体轮廓”和“球体分布密度”。于是我重新去跟 Codex 对话,把“树冠应该是扁椭圆,球体必须互相重叠”这个要求加了进去。
5.2 第二轮:加分层和重叠,变成西兰花
第二轮我改了两个地方:把生成区域从正球体改成扁球体,并把球体数量从 20 个提高到 35 个,同时要求重叠率更高。运行结果确实好了不少,至少整体轮廓是横向椭圆了,球体之间也能看到明显的重叠。
但新的问题出现了:树冠太密了,密到球体之间的边界全部消失,看起来像一个大馒头,没有“由多个团块组成”的层次感。这个阶段我意识到,光有随机重叠还不够,还需要控制“团块感”。于是我手动在树冠区域里指定了三四个“子中心”,每个子中心周围聚拢一批小球,整体看起来就像几大团棉花糖拼在一起,而不是一坨均匀的大球。
这个“子中心”思路其实不复杂,就是在随机撒点前,先随机生成几个父节点,再为每个球体随机选一个父节点作为位置基准,加上一点偏移。Codex 实现这个逻辑很擅长,只要你把“我要几个父节点、偏移量多大”说清楚。
5.3 第三轮:压扁顶部+弯曲树干,味道对了
最后一次关键改动是“压扁顶部”和“树干弯曲”。我把树冠整体的 z 轴范围进一步压缩,让顶部更平,底部更靠近树干中线,边缘保留一点下垂感。树干则从圆柱改成明显上细下粗的锥台,并给了 0.2 的弯曲偏移。
材质和光照也跟着调了一轮:颜色从鲜艳的草绿改成灰绿色,粗糙度提到 0.9,世界环境换成淡米色,阴影调软。渲染出来之后,终于有了一点 Tiny Glade 那种“手工童话模型”的味道。
回看这轮复盘,最大的体会是:没有一个改动是“魔法”,所有效果都来自具体参数的组合。而 Codex 的价值在于帮你把参数组合快速跑出来,省去大量手动建模和写节点的体力活。但“往哪个方向调”这个审美判断,必须由你来完成。
6. 避坑清单和提速心得
6.1 五个高频翻车点
第一个翻车点是脚本清空了整个场景。很多生成脚本会执行bpy.ops.object.select_all(action='SELECT')再删除,一不注意就把你原本的模型删了。所以我后来在 Codex 生成的脚本里,都会让它先检查对象名称前缀,只清理前缀匹配的对象,而不是全部删除。
第二个翻车点是 API 版本差异。Blender 不同版本之间的 Python API 会有细微变化,比如某些参数名从radius改成了radius1/radius2,Codex 有时候会生成基于新版本、但你本地是老版本的代码,运行直接报错。遇到这种情况,别急着让 Codex 猜,直接把报错信息复制给它,它一般能很快修正。
第三个翻车点是材质节点名称不对。Blender 的中文版和英文版在节点命名上可能有差异,Codex 默认按英文版生成,如果你用的是中文界面,Principled BSDF这个名称可能会找不到。建议把界面临时切成英文,或者让 Codex 使用material.node_tree.nodes.get("Principled BSDF")这种更稳妥的写法。
第四个翻车点是数值单位理解错误。Blender 场景单位有时候是厘米,有时候是米,你在提示词里说“树干高 2”,Codex 默认会理解为 2 个 Blender 单位,而实际渲染时可能大得离谱。建议在提示词开头写明“所有长度基于 Blender 默认单位米”,并且在脚本顶部加一个scale = 1.0的全局系数。
第五个翻车点是过度依赖一次生成。你以为让 Codex“再改好看一点”就行,但 AI 没有审美,这个词对它来说等于没说。它只会随机调整几个参数,结果往往更糟。正确做法是用参数化脚本,自己动手调那几个关键数值。Codex 的价值是帮你写出可调参的脚本,而不是替你做美术决策。
6.2 几个让效率翻倍的小习惯
第一个小习惯是给 Codex 提供“负面约束”。比如明确写“不要使用粒子系统”、“不要使用树生成插件”、“不要创建超过 100 个物体”。负面约束能显著减少垃圾代码,因为 Blender 里实现同一个效果的方式太多了,Codex 很容易选到最华丽但最难改的那条路。
第二个小习惯是每次生成前先清理旧对象。我在脚本开头固定放一段清理代码,只删除名字带“TinyTree_”前缀的对象。这样反复运行脚本时,场景不会越来越乱,不然生成几轮之后,满屏都是上一层残留的球体,你根本看不清当前版本长什么样。
第三个小习惯是善用屏幕截图做对比。不要凭记忆判断“改好了还是改坏了”。我会把参考图、上一版截图、当前渲染结果放在一起,用画图软件标注出差异,然后把这些观察变成一句话告诉 Codex。这个过程听起来麻烦,但实际能省掉大量来回试错的时间。
第四个小习惯是让 Codex 为代码写注释。生成脚本时,我通常会在提示词最后加一句“请为每一段关键逻辑添加中文注释”。这样以后回头改代码时,不用重新梳理逻辑,节省不少时间。你甚至可以要求它输出一个简洁的参数说明,就像产品的使用文档一样。
最后再说一个很实际的点:不要追求第一版就完美。我自己改到第三版才勉强满意,中间甚至有一版完全推倒重来。Tiny Glade 风格的树,本质上是一种“看似随意但经过精心控制”的造型。这种造型靠一次公式化生成很难一步到位,你必须接受“多轮迭代”这个过程。Codex 能把每一轮迭代的成本压得很低,但最终让它“像”的,是你对风格的理解和调参的方向感。