12 图层树 = 作画顺序
✅ 已验证 · 代码 code/job_trace.py
树
01_BG/
BG_Base 铺黑 ← 全片唯一一次 set_pixels
BG_Glow 背景辉光, 铺满整幅画布, 最底层
04_Color/
Subject_Silhouette 矢量: 主体剪影 ← 组底, 定义整体 alpha
<Part>/ ×15, 组, inheritAlpha → 裁到剪影
<Part>_Flat/ 组
Shape 矢量: 固有色轮廓 (向外扩 0.6px)
Soft paint, clip → 只在 Shape 里 airbrush 柔和过渡
Marks paint, clip → 只在 Shape 里 排线 / 细节 / 发丝
<Part>_Shadow1/ 组, clip 到部件 (下方累积 alpha)
Shape / Soft / Marks
<Part>_Shadow2/ … 每部件 2–5 档
06_Line/
Line 线稿 (anime 风格才有内容)
09_Post/ passthrough
Post_Grade soft_light, opacity 12
对 origin:15 个部件 → 73 个色阶组 → 307 个节点,其中矢量层 74 个。
顺序就是画师的顺序
从下往上读这棵树,就是一个画师的作画顺序:
- 铺背景,整幅铺满(不抠人物——人物在上面盖住)
- 定剪影
- 逐个部件:先铺固有色,再叠阴影 1、阴影 2、高光……每一档是一个形状
- 在每个形状里面画:柔和过渡、排线、发丝
- 最后描线稿、调色
ASSIGN 表的顺序决定部件组的顺序(底→顶 = 遮挡顺序),cel.levels() 的顺序决定色阶组的顺序(Flat 在最底,深阴影在浅阴影上面)。
为什么每个色阶自成一组
这是本书第五版最重要的一条架构决定,来自一次失败:
第一版把笔画层直接挂在部件组下,只 clip 到部件。结果一笔可以横跨眼睛和皮肤——Skin_Face 里眼睛是一个深色的色阶,皮肤是浅色的,一支从皮肤起笔的粗笔涂过眼睛,把矢量层刚立好的结构整片盖掉。8K 成品的梯度 p99 从矢量阶段的 64.0 掉到 15.8,眼睛变成一团圆斑。
左:只有矢量层。右:笔画只按部件 clip 之后。眼睛的形状没了。
修法:每个色阶自成一组,Shape(矢量)做组底,Soft / Marks clip 到它。笔画的活动范围是色阶形状,不是部件轮廓。 规划器那边同步改成按 (部件, 色阶) 联合标签规划(第 17 章)。改完 p99 回到 33.2。
代价是节点数从 110 涨到 307,建树时间从 72s 涨到 209s。值。
两级 clip
- 色阶组(
Shadow1/起)setInheritAlpha(True)→ 裁到部件组内下方的累积 alpha = 部件 - 部件组
setInheritAlpha(True)→ 裁到04_Color内下方的累积 alpha = 主体剪影
所以一个色阶里的笔画被裁两次:先裁到本档形状,再(通过部件组)裁到剪影。规则的实测依据在第 13 章。
建树的成本
| 节点 | 矢量层 | 控制点 | 耗时 | |
|---|---|---|---|---|
| 第一版(笔画只 clip 到部件) | ~110 | 31 | 20,495 | 72s |
| 现在(每色阶一组) | 307 | 74 | 20,495 | 209s |
矢量层是大头:addShapesFromSvg 一个 5000 控制点的 path 约 4s。每个矢量层之后要 pump(6, 0.05) 等它就绪。