工作流:一个始终是它自己的角色
「我想拍一部关于这个特定角色的电影。」角色只建一次,做成一个模块;只审批一次,以设定图(model sheet)的形式;从那以后,每一张静帧、每个镜头、每部影片、每种画风都只是给它摆姿势。再也没有任何东西重新画它。现成的示例:Mira(
engine/src/canvas-core/characters/mira/)。
为什么。 storybook.ts 和 print.ts 都画 Bit,用的是两套各自独立的控制点。改了其中一个,另一个就成了另一个机器人。逐个镜头画的角色会逐个镜头走样:眼镜变大变小,外套换了一种黄,手长出第六根手指。解决办法是结构上的,而不是靠勤勉:一个唯一的事实来源,加上一道在某个镜头偏离它时会报出来的闸门。
模块(每个角色一个文件,外加它的姿势和配色)
| 导出项 | 是什么 |
|---|---|
| 比例标准 + 规格(canon + spec) | 比例标准表里的一行(human/canon.ts)、身高、身体和头部的规格 |
| 骨骼绑定(rig) | 比例标准所隐含的 3D 骨架,带关节限位(human/skeleton.ts) |
| 手绘视图(drawn views) | 体积描述不了的部件(刘海、翘起的一撮头发),在 3 个视角里各画成 2D 形状,各视角之间有对应点,按视角角度混合(view25d.ts,Rivers et al. 2010) |
| 颜色角色(palette roles) | coat、skin、hair …… 每个都有一个色相族;每种手笔用自己的媒介去映射这些颜色角色(palettes.ts) |
| 辨识特征(distinguishing features) | 眼镜、刘海、翘发、雀斑、雨衣、挎包、雨靴:部件 id,加上它们必须出现的视角 |
pose(p) | 校验一个姿势;任何关节超出范围就抛出异常 |
toScene(pose, camera) | 把角色转成一个 Scene:按绘制顺序排列的部件,每个部件是若干多边形的并集再加上笔触,用颜色角色的颜色着色 |
各种手笔用自己的笔触渲染任意一个 Scene:storybook、marker、riso、woodcut、scratch、sumi、pencil(在 character/render/ 里),每一种都建立在它所属样张的工具包上。对同一个姿势,每种手笔拿到的几何完全相同(闸门会断言这一点)。
一致性与画风无关。 模块是一份规格(特征、比例、颜色角色、标志性形状),而不是一种外观。线条类手笔直接画 Scene;网格类手笔(render/grid.ts → pixel.ts、brick.ts)用它们自己的单位重新表达它:每个格子取最上层的部件,把小圆环(眼镜)夸大到一个最小半径,丢掉精灵图容纳不下的东西(眼睑、眉毛、镜腿)。然后在格子上而不是在 Scene 上检查身份(character/identity.ts),再加上与更细采样之间的剪影 IoU。
绘制层(插画师优先,进行中)。 骨架、比例标准、限位和平衡是看不见的检查器和姿势来源。看得见的体块是设计出来的扫掠体(character/design.ts):一条穿过各关节的动势曲线,一张沿曲线编写的截面表,垂直于曲线取出的剪影,在关节处切开并留出重叠,这样就看不到接缝。Mira 的外套、袖子、腿和靴子,以及面包师(characters/theo/baker.ts)都用了它;Scene 带有 gesture 曲线,供起稿那一遍使用。还没做完的:每个视角手工放置的轮廓控制点、所有衣物从接触点出发的垂坠、作为绘制层上轮廓断点的标志点。较早的 Theo 人物模型仍然照字面渲染体块。
步骤
- 从描述出发:用一段话写出身份(年龄、比例标准、一个孩子凭记忆会画出来的 5-8 个特征)。选比例标准表里的一行;如果造型需要更大的头,就声明一个风格化的行,身体保持写实。从用户的图片出发:列出特征,把颜色取样归入颜色角色,对照以头长为单位的网格读出比例,先画这张图本身的那个视角;图里没有出现的视角是编出来的,并在设定图上标明是编的。
- 搭建模块:规格、颜色角色、特征、做成膨胀身体团块的衣物、头发用的 2.5D 部件、一个姿势库,由落脚位置、求解出的腿、平衡和够取目标构建出来。
- 设定图(
miraSheet.ts):在头长网格上画转面图(正面、3/4、侧面、背面),六种表情、六个姿势、六只手、一张身高比例对照。以原尺寸对照 references/anatomy.md 的「看一眼清单」去看它。✋ 唯一的一次审批。 它锁定版本。 - 验证各种手笔:把同一个姿势、同一个镜头放进你要用的每一种手笔里(
miraTriptych.ts,以及九种手笔的miraEveryHand.ts,每一格都是miraTile.ts出的原尺寸图)。如果她看起来像不同的女孩,修的是手笔的颜色角色映射,不是角色本身。 - 使用它:镜头导入模块并给它摆姿势。影片逐帧计算一个姿势(走路是一个个脚步,不是关键帧),再交给
toScene。 - 修改它:对模块的任何改动都要升版本号,并重新渲染设定图。
闸门检查的不变量(node tools/character-check.mjs)
- 比例标准的比值和各段长度;每个姿势里骨骼长度不变;左右对称;
- 姿势库里的每个姿势都在关节限位之内;站姿保持平衡;脚踩在地面上,而不是穿过地面;
- 五根手指长度顺序正确,指关节成弧,捏的动作里拇指碰到食指;
- 每个辨识特征都出现在它该出现的每一个视角里(十个视角,两侧都查);
- 每种手笔里每个颜色角色都在它的色相族之内(riso 按它实际印出的叠印色来测量);
-
Scene 几何是确定性的;影片里踩实的脚不打滑。
-
全手笔对照图里的每一种手笔:特征清单(线条类手笔查 Scene 特征,像素和积木查格子特征)、颜色角色在色相族之内、像素和积木的网格 IoU > 0.8。
每一项都有一个必须失败的反例孪生。闸门看不到的是:她看起来像不像她自己。在线条类手笔之间,剪影重叠在构造上就完全相同,所以在那里它什么也证明不了;设定图和全手笔对照图,由人去看,才是身份测试。