- Implemented `image_plane.py` to build the Image Plane Geometry Nodes group with customizable parameters for geometry, subdivide, and thickness. - Created `image_plane_validation.py` to validate the functionality of the image plane, ensuring correct geometry generation and material assignment. - Developed `material_layers.py` to construct shader node groups for image materials, including depth and normal handling. - Authored `plane_layouts.py` to define node arrangements for image geometry assets. - Introduced `shadeless.py` to create a shadeless shader node group that displays color without scene lighting while preserving shadows and reflections.
12 KiB
节点资产
生产节点组由脚本构建到 src/anyimage/assets/O_AnyImage.blend;运行时只加载,不创建节点组。
构建
在项目根目录执行:
uv run build_node
脚本依次构建资产、运行三项 Blender 验证和完整测试,任一步失败即退出。
脚本按 --blender、环境变量 BLENDER_BIN、项目 .env、PATH 的顺序查找 Blender。无法自动找到时,在项目根目录的 .env 中配置:
BLENDER_BIN="/absolute/path/to/blender"
.env 已被 Git 忽略。临时指定路径或跳过 Python 测试:
uv run build_node --blender "/path/to/blender"
uv run build_node --skip-tests
资产清单
| 节点组 | 构建模块 |
|---|---|
O Image Plane |
image_plane.py |
O Image Depth Plane |
depth_plane.py |
O Image Layer、O Image Depth Layer |
material_layers.py |
O Shadeless |
shadeless.py |
O Image Cutout、O Image Depth Cutout、O Image Depth Balloon |
cutout.py |
构建从空 Factory 文件生成全部节点组,关闭 .blend1 备份,并覆盖唯一发布资产。
源码职责
tools/node_assets/ 的模块按资产、几何计算、布局和验证组织:
| 模块 | 职责 |
|---|---|
asset_library.py |
构建全部节点组并保存唯一资产 |
image_plane.py、depth_plane.py |
普通平面与 Relief / Camera 深度平面 |
material_layers.py、shadeless.py |
图像材质层与无光照着色 |
cutout.py、cutout_shapes.py |
Cutout 修改器接口与各预设几何 |
depth_plane_camera.py、depth_surface.py |
Camera 平面、共享投影、深度分离与厚度 |
cutout_volume.py、cutout_rounding.py |
平滑中心曲面与轮廓圆润 |
cutout_inflation.py、cutout_shell.py |
正面膨胀、法线和正背面位置 |
plane_layouts.py、depth_plane_layout.py |
平面资产与 Camera 分支布局 |
cutout_layout.py、cutout_shape_layouts.py、depth_cutout_layout.py |
Cutout 阶段布局、坐标与跨区域几何引用 |
node_graph.py、node_layout.py |
共用字段节点、平滑构建、布局与边界检查 |
asset_validation.py |
资产清单、接口、结构与布局检查 |
image_plane_validation.py、cutout_validation.py |
平面和 Cutout 几何求值验证 |
tools/build_node.py 依次启动资产构建与三个验证脚本。运行时加载入口位于 common/node.py。
Depth Cutout 的布局由 depth_cutout_layout.py 编排:Split 属性采样位于主链上方,原始几何旁路沿下方的 Reroute 通道汇入 Switch;长距离投影引用共用分段干线,并在 Uniform 厚度与零厚度输出附近分叉。几何统计支线就近放置在其使用区域。
三个 Cutout 节点组直接作为修改器使用,统一接收局部 XY 平面,以 -Z 表示向图片内部的方向。每组在塑形与平滑后处理 Inward Axis:默认 -Z 直接输出原生几何,+X 分支执行一次 Z 到 X 的轴转换;运行时对象矩阵使用逆变换补偿,保证两种模式落在相同世界空间位置。
O Image Depth Plane、O Image Depth Cutout 与 O Image Depth Balloon 使用 Reference Depth 作为采样深度的运算基准。
Cutout 预设与厚度
| 创建入口 | 修改器节点组 | 默认设置 |
|---|---|---|
| Flat | O Image Cutout | Balloon,Thickness 0 |
| Solid(默认) | O Image Cutout | Balloon,Thickness 1 |
| Depth Solid | O Image Depth Cutout | Balloon,Thickness 1 |
| Depth Balloon | O Image Depth Balloon | Thickness 1,Double Sided 开启 |
前两种节点组提供 Mode,默认显示 Balloon。两个独立输入均显示为 Thickness:第一个是 Balloon 的无量纲倍率,第二个是 Uniform 的距离,各自保存数值。普通 Cutout 在零厚度时输出平面,深度 Cutout 输出深度表面。全部基础网格包含 POINT 域的 o_balloon,Flat 可直接调整为 Solid。
深度 Cutout 的 Balloon 厚度由 cutout_volume.py 构造平滑中心,再由 cutout_rounding.py 处理圆润轮廓与凸起方向。Options 中位于 Front Inflation 前的 Edge Round 默认 0.2,正背面共用 1 − smootherstep(0, max(o_balloon), o_balloon) 衰减权重。正面向中心加 Balloon 的轮廓靠拢,背面按 Balloon 值补充饱满度。Options 中的 Normal Smooth 默认 50:在中心曲面上平滑并归一化法线,背面沿该方向凸起,正面按边缘权重过渡。两个边缘范围及法线影响固定为 1。
中心位置以投影正面 Z 减去 o_balloon 初始化,固定轮廓与切口,在内部通过一个 Blur Attribute 执行 256 次邻域平滑,边界 Weight 为 0。圆润处理前,深凹处保留至少 0.05 × o_balloon 的厚度。轮廓零厚度点按来源身份合并,暂存字段使用 POINT 域 o_balloon_surface_* 并在输出前清理。cutout_shell.py 让薄厚度的 Balloon 从正面沿法线向内生长,再按平滑过渡达到 Thickness 为 1 的圆润体积;大于 1 时继续沿用该体积公式。Uniform 沿正面法线偏移指定距离,同样受 Normal Smooth 控制。Thickness 为 0 时返回原深度表面。整体 Smooth 复用公共构建函数,三个 Cutout 节点组的 Smooth 默认 0,Smooth Weight 默认 1。
cutout_inflation.py 在邻域中拟合深度已有的结构性鼓起,Options 中 Front Inflation 默认 1。Balloon 令结构量为 k、Thickness 与 Front Inflation 的乘积为 a,正面增加 o_balloon × (cbrt((k+0.25)³+(a+0.25)³−0.25³)−k−0.25),通过有理化形式求值以保持小厚度精度。已有 1 倍鼓起、两个参数均为 1 时,额外增加约 0.323 倍 Balloon。Uniform 直接增加 Thickness × Front Inflation,不受结构量或轮廓权重限制;Front Inflation 为 1 时,正面边缘和中心的增量均等于背面的厚度距离。两种模式厚度为 0 时仍返回原表面,单层侧壁直接连接正背面。
Normal Smooth 同时控制正面、背面与 Uniform 的法线;正面膨胀在基础法线平滑之后使用 5.12 倍迭代范围,默认 50 对应额外 256 次,保持大膨胀量下的连续方向。设置为 0 时两阶段均停止平滑。Front Inflation 为 0 时关闭正面额外鼓起。
Normal Map 勾选控制 Flat 与 Solid 的 TANGENT 法线;Depth Solid 固定生成 OBJECT 法线,Depth Balloon 固定生成 TANGENT 法线。材质读取 o_normal_scale:普通 Cutout 和 Depth Balloon 使用 POINT 域的轮廓适配权重;Depth Cutout 使用 FACE 域的正面标记,让背面与切口保留几何法线。该属性属于输出材质协议,随 UVMap 与 o_balloon 保留。
Options 依次排列 Cleanup Threshold、Split Threshold、Reference Depth、Edge Round、Front Inflation、Normal Smooth、Smooth Weight;各节点组仅显示适用项,Depth Balloon 的 Depth Direction 位于末尾。
Depth Cutout 分离与厚度
Options 中的 Split Threshold 范围为 0–1,默认 0 关闭分离,数值越大越容易分离。节点比较 原始 Z 差 × Uniform Scale × Split Threshold > 原始面中心距离 × 2.5;0.5 对应深度坡度阈值 5。Uniform Scale 将原始深度标定到网格单位,Depth Scale 仅控制最终置换幅度。
flowchart TD
A[基础网格与深度图片] --> D[共用 Cleanup 按原平面岛面积清理]
D --> B[面中心采样与共享边判别]
B --> C[存入面角命名属性并 Split Edges]
C --> E[切口顶点沿原相机射线采用所属侧深度]
E --> J[固定顶点数据并投影]
J --> L[选择平滑 Balloon 或 Uniform 厚度]
L --> F[生成正背面与单层四边侧壁]
F --> G[按原顶点及正背面身份连接]
G --> H[恢复场景坐标]
H --> K[移除 o_depth_* 暂存属性]
K --> I[边缘与整体平滑及方向变换]
三个节点组在塑形前复用 Cleanup,按原平面岛的总面积清理小区域。Depth Cutout 随后执行 Split,保留分离产生的小片;Split 关闭时使用原顶点采样。
未关联选中切边的顶点使用原始 XYZ。切口顶点以 原 XYZ × 所属侧 Z / 原 Z 保持原相机射线,随后执行既有 Uniform Scale、Reference Depth 和 Depth Scale 投影。
厚度前固定顶点数据,使正背面和侧壁使用相同位置。连接时以原顶点编号和正背面身份构造临时整数坐标,合并同一身份的副本后恢复场景坐标,保持近距离分离区域各自独立。实现位于 depth_surface.py,由 cutout.py 构建进共享节点资产。
暂存值通过 Store Named Attribute 写入保留前缀 o_depth_:面中心与相机采样使用 FACE,所属侧相机采样与切口标记使用 CORNER,最终相机坐标、表面位置与源顶点编号使用 POINT。计算区域就近使用 Named Attribute,末尾用一个 Wildcard 模式的 Remove Named Attribute 匹配 o_depth_*,输出保留 UVMap 与用户属性。
整图 Depth Plane
O Image Depth Plane 提供默认 Relief 与 Camera 模式,共用完整矩形网格和 depth.exr。RGB 保存相机 XYZ,Alpha 保存有效性。Relief 与 Depth Balloon 读取 B/Z,Camera 与 Depth Cutout 读取 XYZ。用户控制为 Mode、Subdivide、Thickness、Depth Scale 和 Options 中的 Reference Depth、Normal Smooth;Depth Image 与 Uniform Scale 为隐藏数据输入。
flowchart TD
A[O Image Plane 零厚度矩形细分] --> B[按 Depth Scale 插值相机 XY 与相对 Z]
B --> C{Thickness}
C -- 0 --> D[单层曲面]
C -- 大于 0 --> E[沿平滑法线向内生成背面并连接边界]
D --> F[清理临时属性并输出]
E --> F
两个独立输入均显示 Thickness,默认均为 0 m:第一个控制 Relief 的固定底面基础厚度,第二个控制 Camera 的向内壳厚度。上图描述 Camera 分支:Depth Scale 为 0 时恢复平面,1 时使用完整相机投影;正面 POINT 法线按 Normal Smooth 平滑并归一化,再按 Thickness 向内生成背面。Normal Smooth 范围 0–50、默认 50,仅影响 Camera。模式切换保留各自厚度值并复用图片。Camera 分支位于 depth_plane_camera.py,投影与厚度共用 depth_surface.py,布局由 depth_plane_layout.py 编排。
几何节点布局
全部五个几何节点组使用连续横排的几何主轴。主轴可适当宽松,支线内部紧凑,同一目的的计算聚在同一侧,内部间距明显小于与其他部分的距离;独立用途可在两侧错落展开。长算式横排,末端就近汇入主轴。Join Geometry、Menu Switch、Combine XYZ 的同级独立分支末端排成一列并对齐输出端,菜单分支按输入顺序上下排列,共享上游留在公共位置。必要的向左引用直接连接。Group Input 与 Named Attribute 就近放置,全接线的简单运算可折叠,常数和域设置保持可见。
plane_layouts.py 组织平面资产布局,cutout_shape_layouts.py 和 depth_cutout_layout.py 组织 Cutout 的局部计算阶段;cutout_layout.py 将阶段布局放入三个修改器,node_layout.py 验证节点边界与同级输入对齐。布局验收包含实际节点编辑器预览及几何求值。
修改节点组
- 修改
tools/node_assets/中对应资产、计算或布局模块; - 更新对应验证;
- 运行一键构建脚本;
- 搜索并清理旧名称、接口和路径;
- 检查
.blend、代码、测试和文档差异。
接口、节点、连线、默认值或布局变化时必须重建。只修改运行时 Python、Markdown 或打包逻辑时无需重建。
O_AnyImage.blend1 等备份不应提交或打包。