第 2 章 从三维三角形开始 ------ 基础几何与节点入门
2.1 手动创建三维三角形(基础网格操作)
三角形是三维图形的 "最小单元"------ 任何复杂的网格模型,本质上都是由无数个三角形面组成的。本节先通过手动操作创建三维三角形,理解 "点→边→面" 的构成逻辑。
2.1.1 手动创建步骤
| 步骤 | 操作说明 | 注意事项 |
|---|---|---|
| 1 | 切换到 "布局" 工作区,删除默认物体(立方体、灯光、相机) | 避免默认物体干扰视图 |
| 2 | 进入顶点编辑模式:点击顶部菜单栏 Add → Mesh → Plane(添加一个平面),选中平面,按 Tab 键进入顶点编辑模式(此时平面的 4 个顶点会显示为橙色) |
顶点编辑模式下,可单独选择、移动、删除顶点 |
| 3 | 删除多余顶点:按 A 键取消全选,按住 Shift 键点击平面右上角的两个顶点(选中后显示为黄色),按 X 键 → 选择 "Vertices"(删除顶点) |
确保只删除两个顶点,保留两个顶点 + 一条边 |
| 4 | 添加第三个顶点:按 Tab 键退出顶点编辑模式,再按 Tab 键重新进入(确保处于顶点编辑模式),将鼠标移动到 3D 视图中合适位置(如平面上方),按 Shift+A → 选择 "Mesh → Vertex"(添加一个顶点) |
新顶点的位置可通过鼠标拖动调整,或在左侧工具栏输入精确坐标 |
| 5 | 连接顶点形成三角形面:按住 Shift 键依次点击三个顶点(按顺时针或逆时针顺序),按 F 键(创建面),此时三个顶点会围成一个三角形面 |
顶点选择顺序会影响面的法线方向(后续会讲解法线的作用) |
| 6 | 退出编辑模式:按 Tab 键退出顶点编辑模式,此时会看到一个完整的三维三角形 |
可通过 W 键(缩放)、E 键(移动)、R 键(旋转)调整三角形位置和大小 |
| 7 | 查看三角形信息:选中三角形,在右侧 "属性" 面板 → Object Data Properties(三角形图标),可查看顶点数(3)、边数(3)、面数(1) |
确认三角形的 "点→边→面" 结构正确 |
2.1.2 三角形法线与方向调整
三角形的 "法线"(Normal)是垂直于面的向量,决定了面的 "正面" 和 "背面"(Blender 中默认正面为可见,背面为透明):
- 显示法线:选中三角形,进入顶点编辑模式,点击顶部菜单栏
Overlay → Normals → Face Normals(显示面法线,红色箭头表示法线方向)。 - 翻转法线:若法线方向错误(如背面朝向视图,导致三角形透明),选中三角形面(进入面编辑模式:按
Tab→ 按2键),按Alt+N→ 选择 "Flip Normals"(翻转法线方向)。
2.2 用 Python 脚本生成三角形网格(精准控制)
手动创建三角形无法精确控制顶点坐标,通过 Python 脚本可直接定义三个顶点的坐标,生成精准的三维三角形。
2.2.1 核心原理
Blender 中的网格(Mesh)由 "顶点数据""边数据""面数据" 组成:
- 顶点数据:存储每个顶点的 (x, y, z) 坐标。
- 边数据:存储连接的顶点索引(如边由第 0 个和第 1 个顶点组成)。
- 面数据:存储组成面的顶点索引(如三角形面由第 0、1、2 个顶点组成)。
通过 bpy.data.meshes.new() 创建网格,手动传入顶点、边、面数据,即可生成自定义形状的网格。
2.2.2 完整 Python 脚本(生成等边三角形)
python
运行
# Python 脚本生成三维等边三角形(边长为 2,位于 XY 平面)
import bpy
import math
# 步骤 1:清除默认场景
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# 步骤 2:定义三角形的三个顶点坐标(等边三角形,中心在原点)
# 等边三角形顶点坐标计算:边长为 2,中心在 (0,0,0)
side_length = 2 # 边长
height = (math.sqrt(3) / 2) * side_length # 等边三角形高
vertices = [
(-side_length/2, 0, 0), # 顶点 0:左下角
(side_length/2, 0, 0), # 顶点 1:右下角
(0, height, 0) # 顶点 2:顶部
]
# 步骤 3:定义边数据(连接顶点的索引)
edges = [
(0, 1), # 边 0:顶点 0 → 顶点 1
(1, 2), # 边 1:顶点 1 → 顶点 2
(2, 0) # 边 2:顶点 2 → 顶点 0
]
# 步骤 4:定义面数据(组成面的顶点索引,按逆时针顺序)
faces = [
(0, 1, 2) # 面 0:顶点 0 → 1 → 2(逆时针顺序,确保法线方向正确)
]
# 步骤 5:创建网格数据
mesh = bpy.data.meshes.new(name="TriangleMesh")
mesh.from_pydata(vertices, edges, faces) # 传入顶点、边、面数据
mesh.update(calc_edges=True) # 更新网格边缘数据(确保边显示正常)
# 步骤 6:创建物体并关联网格
triangle = bpy.data.objects.new(name="EquilateralTriangle", object_data=mesh)
# 步骤 7:将物体添加到场景
scene = bpy.context.scene
scene.collection.objects.link(triangle)
# 步骤 8:选中并激活物体(方便在视图中查看)
bpy.context.view_layer.objects.active = triangle
triangle.select_set(True)
# 步骤 9:输出三角形信息
print("=" * 50)
print("三维等边三角形生成完成!")
print(f"三角形名称:{triangle.name}")
print(f"顶点坐标:{vertices}")
print(f"边长:{side_length}")
print(f"高:{height:.2f}")
print(f"顶点数:{len(mesh.vertices)}")
print(f"边数:{len(mesh.edges)}")
print(f"面数:{len(mesh.faces)}")
print("=" * 50)
2.2.3 脚本参数说明与修改
| 参数名称 | 作用 | 修改建议 |
|---|---|---|
side_length |
三角形边长 | 改为 3,生成更大的三角形 |
vertices |
顶点坐标列表 | 修改 z 坐标为 1,让三角形位于 z=1 平面 |
faces 中顶点顺序 |
决定面的法线方向 | 改为 (0, 2, 1),观察法线方向变化 |
2.2.4 常见问题排查
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 生成后只看到线段,没有面 | 面数据定义错误(如顶点顺序错误、缺少面数据) | 检查 faces 列表是否正确,确保顶点按逆时针顺序排列 |
| 三角形透明(看不到面) | 法线方向错误(背面朝向视图) | 翻转面的顶点顺序,或在脚本中添加 mesh.flip_normals()(创建网格后) |
| 运行脚本报错 "IndexError: list index out of range" | 边或面数据中的顶点索引超出顶点列表长度 | 确保 edges 和 faces 中的索引不大于 len(vertices)-1 |
2.3 几何节点基础节点应用(给三角形 "赋能")
通过几何节点,我们可以给三角形添加动态效果(如移动、旋转、变色),而无需修改原始网格数据。本节将使用基础输入节点、几何节点、输出节点,实现三角形的位置控制和颜色控制。
2.3.1 基础节点分类与核心功能(新手必记)
Blender 5.0 几何节点按功能可分为 8 大类,本节先掌握最基础的 3 类:
| 节点类别 | 核心作用 | 新手必学节点 |
|---|---|---|
| 输入节点(Input Nodes) | 提供基础数据(固定值、场景信息、物体信息等) | Boolean、Color、Value、Scene Time |
| 几何节点(Geometry Nodes) | 处理几何体(读取 / 修改位置、法线、拓扑等) | Position、Set Position、Normal |
| 输出节点(Output Nodes) | 输出效果或调试数据 | Group Output、Viewer |
2.3.2 实战案例:彩色三角形(手动创建节点树)
目标:通过几何节点控制三角形的位置和颜色,实现 "固定颜色 + 可调整位置" 的效果。
| 步骤 | 操作说明 | 节点参数设置 |
|---|---|---|
| 1 | 准备工作:运行 2.2 节的 Python 脚本,生成等边三角形,确保三角形处于选中状态 | - |
| 2 | 添加几何节点修改器:右侧 "属性" 面板 → 修改器 → 添加修改器 → Geometry Nodes |
修改器名称:ColorPositionTriangle |
| 3 | 进入几何节点编辑器:顶部工作区选择 Geometry Nodes,删除默认的 "Group Input" 和 "Group Output" 之间的连线 |
- |
| 4 | 添加输入节点:1. Add → Input → Value(命名为 "X 偏移")2. Add → Input → Value(命名为 "Y 偏移")3. Add → Input → Color(命名为 "三角形颜色") |
- |
| 5 | 添加几何节点:1. Add → Geometry → Position(读取顶点位置)2. Add → Geometry → Set Position(修改顶点位置)3. Add → Geometry → Set Material(给三角形添加颜色,需先创建材质) |
- |
| 6 | 添加向量节点:1. Add → Vector → Combine XYZ(将 X、Y 偏移组合为向量) |
节点名称:偏移向量 |
| 7 | 添加材质节点:1. 切换到 "材质" 工作区,点击 New 创建材质(命名为 "TriangleMaterial")2. 进入材质编辑器,添加 Principled BSDF 节点和 Material Output 节点3. 将 "三角形颜色" 节点的输出连接到 Principled BSDF 的 "Base Color" 输入端 |
材质类型:Principled BSDF(PBR 材质) |
| 8 | 连接节点(关键步骤):1. Group Input → Position(Geometry 端口)2. "X 偏移" → Combine XYZ(X 端口)3. "Y 偏移" → Combine XYZ(Y 端口)4. Combine XYZ(Vector 端口) → Set Position(Offset 端口)5. Position(Position 端口) → Set Position(Position 端口)6. Set Position(Geometry 端口) → Set Material(Geometry 端口)7. "三角形颜色" → TriangleMaterial 的 Base Color8. Set Material(Geometry 端口) → Group Output(Geometry 端口) | 确保所有连线正确,无断开 |
| 9 | 调整参数:1. "X 偏移" 设为 1.5,"Y 偏移" 设为 0.82. "三角形颜色" 设为(255, 100, 100)(红色) | 观察 3D 视图,三角形会移动并显示为红色 |
| 10 | 预览效果:点击几何节点编辑器中的 Viewer 节点(若未添加,可添加 Add → Output → Viewer),查看实时效果 |
- |
2.3.3 Python 脚本创建彩色三角形节点树(自动化实现)
手动创建节点树和材质较为繁琐,通过 Python 脚本可一键生成完整的节点树 + 材质:
python
运行
# Python 脚本:一键生成彩色可移动三角形(几何节点+材质)
import bpy
# 步骤 1:清除默认场景
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# 步骤 2:生成等边三角形(复用 2.2 节的代码)
import math
side_length = 2
height = (math.sqrt(3) / 2) * side_length
vertices = [(-side_length/2, 0, 0), (side_length/2, 0, 0), (0, height, 0)]
edges = [(0, 1), (1, 2), (2, 0)]
faces = [(0, 1, 2)]
mesh = bpy.data.meshes.new(name="TriangleMesh")
mesh.from_pydata(vertices, edges, faces)
mesh.update(calc_edges=True)
triangle = bpy.data.objects.new(name="ColorfulTriangle", object_data=mesh)
scene = bpy.context.scene
scene.collection.objects.link(triangle)
bpy.context.view_layer.objects.active = triangle
triangle.select_set(True)
# 步骤 3:创建材质(TriangleMaterial)
def create_triangle_material():
# 创建材质
mat = bpy.data.materials.new(name="TriangleMaterial")
mat.use_nodes = True # 启用节点材质
# 清除默认节点
nodes = mat.node_tree.nodes
links = mat.node_tree.links
nodes.clear()
# 添加 Principled BSDF 节点
bsdf_node = nodes.new(type='ShaderNodeBsdfPrincipled')
bsdf_node.location = (-200, 0)
bsdf_node.inputs['Roughness'].default_value = 0.5 # 粗糙度
bsdf_node.inputs['Metallic'].default_value = 0.0 # 金属度
# 添加 Material Output 节点
output_node = nodes.new(type='ShaderNodeOutputMaterial')
output_node.location = (0, 0)
# 连接节点
links.new(bsdf_node.outputs['BSDF'], output_node.inputs['Surface'])
return mat, bsdf_node
mat, bsdf_node = create_triangle_material()
# 给三角形添加材质
if triangle.data.materials:
triangle.data.materials[0] = mat
else:
triangle.data.materials.append(mat)
# 步骤 4:创建几何节点树
def create_color_position_node_tree(bsdf_node):
# 创建节点树
node_tree = bpy.data.node_groups.new(name="ColorPositionNodeTree", type='GeometryNodeTree')
# 添加 Group Input/Output
group_input = node_tree.nodes.new(type='NodeGroupInput')
group_input.location = (-600, 0)
group_output = node_tree.nodes.new(type='NodeGroupOutput')
group_output.location = (400, 0)
# 添加输入节点
x_offset_node = node_tree.nodes.new(type='ShaderNodeValue')
x_offset_node.name = "XOffset"
x_offset_node.label = "X 偏移"
x_offset_node.location = (-500, 200)
x_offset_node.outputs[0].default_value = 1.5 # 默认 X 偏移 1.5
y_offset_node = node_tree.nodes.new(type='ShaderNodeValue')
y_offset_node.name = "YOffset"
y_offset_node.label = "Y 偏移"
y_offset_node.location = (-500, 100)
y_offset_node.outputs[0].default_value = 0.8 # 默认 Y 偏移 0.8
color_node = node_tree.nodes.new(type='ShaderNodeRGB')
color_node.name = "TriangleColor"
color_node.label = "三角形颜色"
color_node.location = (-500, -100)
color_node.outputs[0].default_value = (1.0, 0.39, 0.39, 1.0) # RGBA 红色
# 添加几何节点
position_node = node_tree.nodes.new(type='GeometryNodeInputPosition')
position_node.name = "ReadPosition"
position_node.label = "读取位置"
position_node.location = (-300, 0)
set_position_node = node_tree.nodes.new(type='GeometryNodeSetPosition')
set_position_node.name = "SetPosition"
set_position_node.label = "设置位置"
set_position_node.location = (-100, 0)
# 添加向量节点
combine_xyz_node = node_tree.nodes.new(type='ShaderNodeCombineXYZ')
combine_xyz_node.name = "OffsetVector"
combine_xyz_node.label = "偏移向量"
combine_xyz_node.location = (-300, 150)
# 添加材质节点(连接几何节点和材质)
# 注意:几何节点中的 Set Material 节点需要关联材质
set_material_node = node_tree.nodes.new(type='GeometryNodeSetMaterial')
set_material_node.name = "SetMaterial"
set_material_node.label = "设置材质"
set_material_node.location = (200, 0)
set_material_node.inputs['Material'].default_value = mat # 关联创建的材质
# 连接节点(辅助函数)
def link_nodes(from_node, from_port, to_node, to_port):
node_tree.links.new(from_node.outputs[from_port], to_node.inputs[to_port])
# 连接输入节点 → 偏移向量
link_nodes(x_offset_node, "Value", combine_xyz_node, "X")
link_nodes(y_offset_node, "Value", combine_xyz_node, "Y")
# 连接位置节点 → 设置位置
link_nodes(group_input, "Geometry", position_node, "Geometry")
link_nodes(position_node, "Position", set_position_node, "Position")
link_nodes(combine_xyz_node, "Vector", set_position_node, "Offset")
# 连接设置位置 → 设置材质
link_nodes(set_position_node, "Geometry", set_material_node, "Geometry")
# 连接颜色节点 → 材质
# 注意:这里需要通过材质的节点树连接,而非几何节点直接连接
mat.node_tree.links.new(color_node.outputs["Color"], bsdf_node.inputs["Base Color"])
# 连接设置材质 → 输出
link_nodes(set_material_node, "Geometry", group_output, "Geometry")
return node_tree
node_tree = create_color_position_node_tree(bsdf_node)
# 给三角形添加几何节点修改器
geo_mod = triangle.modifiers.new(name="ColorPositionModifier", type='NODES')
geo_mod.node_group = node_tree
# 步骤 5:输出信息
print("=" * 50)
print("彩色可移动三角形生成完成!")
print(f"三角形名称:{triangle.name}")
print(f"材质名称:{mat.name}")
print(f"几何节点树名称:{node_tree.name}")
print(f"默认 X 偏移:{x_offset_node.outputs[0].default_value}")
print(f"默认 Y 偏移:{y_offset_node.outputs[0].default_value}")
print(f"默认颜色:{color_node.outputs[0].default_value[:3]}")
print("=" * 50)
运行脚本后,会自动生成一个红色的等边三角形,且可以在几何节点编辑器中调整 "X 偏移""Y 偏移" 和 "三角形颜色",实时看到效果变化。
2.4 三角形的动态效果:结合场景时间节点
静态三角形不够生动,通过 "场景时间节点"(Scene Time),可以让三角形的位置、颜色随时间变化,实现动态动画效果。
2.4.1 动态效果原理
"场景时间节点" 可获取当前动画的时间信息(如帧编号、秒数),将其作为参数传递给其他节点(如位置节点、颜色节点),即可实现 "时间驱动效果"。Blender 的动画默认帧率为 24 帧 / 秒,即 1 秒 = 24 帧。
2.4.2 实战案例:动态旋转 + 颜色渐变的三角形(手动操作)
目标:三角形绕 Z 轴旋转,同时颜色从红色渐变到蓝色。
| 步骤 | 操作说明 | 节点参数设置 |
|---|---|---|
| 1 | 准备工作:打开 2.3 节创建的彩色三角形文件,确保三角形和几何节点树处于选中状态 | - |
| 2 | 添加场景时间节点:Add → Input → Scene Time(命名为 "时间节点") |
- |
| 3 | 添加数学节点:1. Add → Math → Multiply(命名为 "旋转速度",用于控制旋转快慢)2. Add → Math → Sin(命名为 "颜色渐变",用于生成 0-1 之间的波动值) |
- |
| 4 | 添加向量节点:1. Add → Vector → Rotate Euler(命名为 "旋转向量",用于绕 Z 轴旋转) |
旋转类型:Z 轴(Euler Z) |
| 5 | 添加颜色节点:1. Add → Color → Mix(命名为 "颜色混合",用于混合红色和蓝色) |
混合类型:叠加(Add) |
| 6 | 连接节点:1. Scene Time(Seconds 端口) → Multiply(Value 端口)2. Multiply(Value 端口) → Rotate Euler(Angle 端口)3. Position(Position 端口) → Rotate Euler(Vector 端口)4. Rotate Euler(Vector 端口) → Set Position(Position 端口)5. Scene Time(Seconds 端口) → Sin(Value 端口)6. Sin(Value 端口) → Mix(Factor 端口)7. 红色节点 → Mix(Color1 端口)8. 蓝色节点(新增 Add → Input → Color,设为蓝色) → Mix(Color2 端口)9. Mix(Color 端口) → 材质的 Base Color 端口 |
- |
| 7 | 调整参数:1. Multiply 节点的第二个 Value 设为 0.5(旋转速度:0.5 圈 / 秒)2. Sin 节点的 Value 设为 1.0(颜色渐变幅度) | - |
| 8 | 播放动画:点击 3D 视图底部的 "播放" 按钮(▶️),观察三角形的旋转和颜色渐变效果 | 可通过 "时间线" 调整动画时长(默认 250 帧,约 10 秒) |
2.4.3 Python 脚本实现动态三角形(自动化动画)
python
运行
# Python 脚本:动态旋转+颜色渐变的三角形
import bpy
import math
# 步骤 1:清除默认场景
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# 步骤 2:生成等边三角形(复用之前的代码)
side_length = 2
height = (math.sqrt(3) / 2) * side_length
vertices = [(-side_length/2, 0, 0), (side_length/2, 0, 0), (0, height, 0)]
edges = [(0, 1), (1, 2), (2, 0)]
faces = [(0, 1, 2)]
mesh = bpy.data.meshes.new(name="DynamicTriangleMesh")
mesh.from_pydata(vertices, edges, faces)
mesh.update(calc_edges=True)
triangle = bpy.data.objects.new(name="DynamicTriangle", object_data=mesh)
scene = bpy.context.scene
scene.collection.objects.link(triangle)
bpy.context.view_layer.objects.active = triangle
triangle.select_set(True)
# 步骤 3:创建动态材质
def create_dynamic_material():
mat = bpy.data.materials.new(name="DynamicMaterial")
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
nodes.clear()
# 添加节点
bsdf_node = nodes.new(type='ShaderNodeBsdfPrincipled')
bsdf_node.location = (200, 0)
bsdf_node.inputs['Roughness'].default_value = 0.5
bsdf_node.inputs['Metallic'].default_value = 0.0
output_node = nodes.new(type='ShaderNodeOutputMaterial')
output_node.location = (400, 0)
mix_color_node = nodes.new(type='ShaderNodeMixRGB')
mix_color_node.name = "ColorMix"
mix_color_node.label = "颜色混合"
mix_color_node.location = (0, 0)
mix_color_node.blend_type = 'ADD'
red_node = nodes.new(type='ShaderNodeRGB')
red_node.name = "RedColor"
red_node.label = "红色"
red_node.location = (-200, 100)
red_node.outputs[0].default_value = (1.0, 0.39, 0.39, 1.0)
blue_node = nodes.new(type='ShaderNodeRGB')
blue_node.name = "BlueColor"
blue_node.label = "蓝色"
blue_node.location = (-200, -100)
blue_node.outputs[0].default_value = (0.39, 0.58, 1.0, 1.0)
# 连接材质节点
links.new(mix_color_node.outputs['Color'], bsdf_node.inputs['Base Color'])
links.new(bsdf_node.outputs['BSDF'], output_node.inputs['Surface'])
links.new(red_node.outputs['Color'], mix_color_node.inputs['Color1'])
links.new(blue_node.outputs['Color'], mix_color_node.inputs['Color2'])
return mat, mix_color_node
mat, mix_color_node = create_dynamic_material()
triangle.data.materials.append(mat)
# 步骤 4:创建动态几何节点树
def create_dynamic_node_tree(mix_color_node):
node_tree = bpy.data.node_groups.new(name="DynamicNodeTree", type='GeometryNodeTree')
# 添加 Group Input/Output
group_input = node_tree.nodes.new(type='NodeGroupInput')
group_input.location = (-800, 0)
group_output = node_tree.nodes.new(type='NodeGroupOutput')
group_output.location = (400, 0)
# 添加输入节点
scene_time_node = node_tree.nodes.new(type='GeometryNodeInputSceneTime')
scene_time_node.name = "SceneTime"
scene_time_node.label = "场景时间"
scene_time_node.location = (-700, 0)
# 添加数学节点
multiply_node = node_tree.nodes.new(type='ShaderNodeMath')
multiply_node.name = "RotateSpeed"
multiply_node.label = "旋转速度"
multiply_node.location = (-500, 200)
multiply_node.operation = 'MULTIPLY'
multiply_node.inputs[1].default_value = 0.5 # 旋转速度:0.5 圈/秒
sin_node = node_tree.nodes.new(type='ShaderNodeMath')
sin_node.name = "ColorGradient"
sin_node.label = "颜色渐变"
sin_node.location = (-500, -200)
sin_node.operation = 'SINE'
sin_node.inputs[1].default_value = 1.0 # 渐变幅度
# 添加向量节点
rotate_euler_node = node_tree.nodes.new(type='ShaderNodeVectorRotate')
rotate_euler_node.name = "RotateZ"
rotate_euler_node.label = "绕 Z 轴旋转"
rotate_euler_node.location = (-300, 0)
rotate_euler_node.rotation_type = 'EULER_Z'
# 添加几何节点
position_node = node_tree.nodes.new(type='GeometryNodeInputPosition')
position_node.name = "ReadPosition"
position_node.location = (-500, 0)
set_position_node = node_tree.nodes.new(type='GeometryNodeSetPosition')
set_position_node.name = "SetPosition"
set_position_node.location = (-100, 0)
set_material_node = node_tree.nodes.new(type='GeometryNodeSetMaterial')
set_material_node.name = "SetMaterial"
set_material_node.location = (200, 0)
set_material_node.inputs['Material'].default_value = mat
# 连接节点函数
def link(from_node, from_port, to_node, to_port):
node_tree.links.new(from_node.outputs[from_port], to_node.inputs[to_port])
# 连接时间 → 旋转
link(scene_time_node, "Seconds", multiply_node, "Value")
link(multiply_node, "Value", rotate_euler_node, "Angle")
link(position_node, "Position", rotate_euler_node, "Vector")
link(rotate_euler_node, "Vector", set_position_node, "Position")
# 连接时间 → 颜色渐变
link(scene_time_node, "Seconds", sin_node, "Value")
# 注意:Sin 输出范围是 [-1,1],需要归一化到 [0,1](添加 Add + Multiply)
add_node = node_tree.nodes.new(type='ShaderNodeMath')
add_node.name = "NormalizeAdd"
add_node.label = "归一化(+1)"
add_node.location = (-300, -200)
add_node.operation = 'ADD'
add_node.inputs[1].default_value = 1.0
multiply_norm_node = node_tree.nodes.new(type='ShaderNodeMath')
multiply_norm_node.name = "NormalizeMult"
multiply_norm_node.label = "归一化(×0.5)"
multiply_norm_node.location = (-100, -200)
multiply_norm_node.operation = 'MULTIPLY'
multiply_norm_node.inputs[1].default_value = 0.5
link(sin_node, "Value", add_node, "Value")
link(add_node, "Value", multiply_norm_node, "Value")
link(multiply_norm_node, "Value", mix_color_node, "Fac") # 连接到颜色混合的 Factor 端口
# 连接其他节点
link(group_input, "Geometry", position_node, "Geometry")
link(set_position_node, "Geometry", set_material_node, "Geometry")
link(set_material_node, "Geometry", group_output, "Geometry")
return node_tree
node_tree = create_dynamic_node_tree(mix_color_node)
# 添加几何节点修改器
geo_mod = triangle.modifiers.new(name="DynamicModifier", type='NODES')
geo_mod.node_group = node_tree
# 步骤 5:设置动画参数
scene.frame_start = 1 # 动画起始帧
scene.frame_end = 500 # 动画结束帧(约 20 秒)
scene.render.fps = 24 # 帧率
# 步骤 6:输出信息
print("=" * 50)
print("动态旋转+颜色渐变三角形生成完成!")
print(f"动画时长:{scene.frame_end - scene.frame_start + 1} 帧({((scene.frame_end - scene.frame_start + 1)/24):.1f} 秒)")
print(f"旋转速度:0.5 圈/秒")
print(f"颜色渐变:红色 ↔ 蓝色")
print("点击播放按钮查看动画效果!")
print("=" * 50)
运行脚本后,点击 3D 视图底部的播放按钮,即可看到三角形绕 Z 轴缓慢旋转,同时颜色在红色和蓝色之间平滑渐变。
2.5 本章小结与进阶方向
2.5.1 核心知识点回顾
- 掌握了三维三角形的手动创建和 Python 脚本生成,理解了 "点→边→面" 的网格结构。
- 熟悉了几何节点的基础分类(输入、几何、输出节点),能手动和通过 Python 脚本创建简单节点树。
- 学会了用几何节点控制模型的位置和颜色,结合场景时间节点实现动态动画效果。
- 理解了 Python 脚本与几何节点、材质的联动逻辑,能自动化生成完整的三维效果。
2.5.2 进阶方向
- 给动态三角形添加缩放效果(结合场景时间节点和缩放节点)。
- 实现三角形沿路径移动(添加曲线节点,让三角形跟随曲线运动)。
- 批量生成多个动态三角形,每个三角形的旋转速度和颜色不同。
- 给三角形添加阴影和反射效果(调整材质的粗糙度、金属度参数)。