Python + Blender 5.0 几何节点全栈实战教程2

第 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 中默认正面为可见,背面为透明):

  1. 显示法线:选中三角形,进入顶点编辑模式,点击顶部菜单栏 Overlay → Normals → Face Normals(显示面法线,红色箭头表示法线方向)。
  2. 翻转法线:若法线方向错误(如背面朝向视图,导致三角形透明),选中三角形面(进入面编辑模式:按 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" 边或面数据中的顶点索引超出顶点列表长度 确保 edgesfaces 中的索引不大于 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 进阶方向
  1. 给动态三角形添加缩放效果(结合场景时间节点和缩放节点)。
  2. 实现三角形沿路径移动(添加曲线节点,让三角形跟随曲线运动)。
  3. 批量生成多个动态三角形,每个三角形的旋转速度和颜色不同。
  4. 给三角形添加阴影和反射效果(调整材质的粗糙度、金属度参数)。
相关推荐
极梦网络无忧7 小时前
OpenClaw 基础使用说明(中文版)
python
codeJinger7 小时前
【Python】操作Excel文件
python·excel
XLYcmy8 小时前
一个针对医疗RAG系统的数据窃取攻击工具
python·网络安全·ai·llm·agent·rag·ai安全
Islucas8 小时前
Claude code入门保姆级教程
python·bash·claude
萝卜白菜。8 小时前
TongWeb7.0相同的类指明加载顺序
开发语言·python·pycharm
赵钰老师8 小时前
【ADCIRC】基于“python+”潮汐、风驱动循环、风暴潮等海洋水动力模拟实践技术应用
python·信息可视化·数据分析
爬山算法9 小时前
MongoDB(80)如何在MongoDB中使用多文档事务?
数据库·python·mongodb
YuanDaima20489 小时前
基于 LangChain 1.0 的检索增强生成(RAG)实战
人工智能·笔记·python·langchain·个人开发·langgraph
RopenYuan10 小时前
FastAPI -API Router的应用
前端·网络·python