Communitygithub.com

pisakhov/x-motion-sumi

与核心 x-motion 技能配合使用,让影片在视觉和听觉上呈现水墨画般的动态效果(宣纸、碳墨、水、雾气、呼吸,以及一抹朱红点缀)。

x-motion-sumi 是什么?

该技能为动画和电影制作提供了一套完整的水墨画风格指导方案,基于墨水的物理特性(扩散、洇染、干枯)来模拟动态效果。它扩展了 x-motion 工作流,在完成构思、剧本、故事板和评审循环后,用于定义艺术风格和具体实现方案。技能涵盖视觉主题(每个节拍只做一个动作)、配色方案(暖调宣纸、碳墨、朱红)、光照材质模拟、构图规则、动作节奏与音响设计。支持 WebGL 渲染技术,包括噪声场、墨迹复合算法、笔触生成、分层景深等,并提供确定性渲染检查列表以确保结果稳定可靠。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pisakhov/x-motion/tree/HEAD/skills/x-motion-sumi

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

X 运动: 墨韵

墨、纸、呼吸。该主题将水墨画(ink-wash painting)的材质逻辑转化为时间维度:稀释的碳墨呈现丰富的灰度层次,温暖的纤维纸张、洇湿的边缘、干燥的笔触以及留白作为主要材质。它扩展了 x-motion;请先运行该方法(构思、剧本、故事板、评审循环),然后使用本文件进行艺术指导和具体方案制定。

视觉主题

通过墨水如同墨水般(扩散、洇染、干涸)在宁静的纸面上表现,让每个动作在刹那间显得必然,从而让观众感受到决定性瞬间前后的静寂。

  • 每个节拍一个动作。 一滴、一笔、一道、一只鸟。绝不同时发生两个焦点事件。
  • 留白承载重量。 画幅的 60% 到 80% 保持为未触碰的纸、雾气或水。空白空间是精心构图的,而非剩下的。
  • 材质的真实优于插图风格。 视觉效果源于模拟墨水如何吸收光、纸张如何吸收墨水,而非轮廓线或纯色填充。
  • 尊重与原创。 不使用书法、伪文字、真实或虚构字符、无服装、庙宇或灯笼道具,不使用红日+仙鹤纹样。印章是抽象的几何标记。

调色板

在线性光下工作;以下为 sRGB 十六进制锚点。

角色十六进制备注
宣纸(受光面)#f1e9d8暖调的和纸;绝不用纯白
宣纸(阴影面)#e0d3ba渐晕、光线的褶皱、斑驳
宣纸(深色面)#cbbb9c仅在画幅边缘或雾影中使用
墨,浓墨#14120f暖调碳黑;绝不用 #000
墨,中洗#5d5b57在暖调纸上略显冷感
墨,淡洗#a9a69f远山、扩散的云
朱红#c8372d唯一的颜色。最多一个标记,最多约占像素的 1.5%
雾中朱红#d7735f朱红受大气影响趋向纸色

墨不是用来涂的颜色;它是一种吸收。使用比尔-朗伯定律(Beer-Lambert)复合:rgb = paper * exp(-density * absorb),其中 absorb 在蓝色通道稍大(例如 vec3(1.0, 1.04, 1.1)),使淡洗偏冷而浓墨呈暖调黑色。

光影与材质

  • 纸张 从一侧被柔和地照亮:低频斑驳(±3%)、可见的楮纤维(长而细的半透明丝状,宽 1 到 2 像素)、以及干燥墨水附着时产生的细微纹理。预渲染一次;它是静态的。
  • 湿墨 具有较暗的边缘(颜料迁移到边缘所致)、羽化渗入纤维的效果、以及干燥过程中逐渐消失的微弱光泽。
  • 干墨 分裂成平行的笔毫纹理,并跳过纸张的低洼处(对纹理进行阈值处理)。
  • 水中的墨 是逆光下的体积:浓密的核心、侧视呈细暗线的层流片状、以及周围的柔和雾纱。
  • 大气 是纸色的。距离和雾气将亮度值趋向纸色,而非趋向蓝色或白色。

构图

  • 将主体放置在不对称的三分点上;留出一个大的平静区域(顶部或一侧)作为平衡。
  • 保持清晰的价值层次:一个接近黑色的区域,几个中间灰度,其余皆为纸色。
  • 画幅边缘保持平静。朝 #e0d3ba 的柔和渐晕能将视线吸引在画面内。
  • 朱红点缀远离主要物体,个体小、位置低、出现晚。它回应动作,而非与之竞争。
  • 检查缩略图:单个动作的轮廓在 320 像素宽时必须清晰可辨。

动作词汇与时间

动词特征典型曲线
呼吸(保持)只有光或雾气在动动作前 0.8 至 1.5 秒的静止
落下 / 撞击果断、快速、无过冲ease-in,0.3 至 0.6 秒
画画笔加速然后释放缓慢按压、快速中段、轻抬笔
绽放 / 扩散快速然后指数慢速1 - exp(-t / tau),tau 1 至 2 秒
洇 / 沉淀事件后微小的增长接触时间以来的 sqrt,有上限
漂移相机或雾气,恒定且缓慢线性或极长的缓动,每秒不超过画幅的 2%
溶解对比度下降,边缘扩大结尾的 2 至 3 秒,从不切到黑色
  • 节奏如同呼吸:静止、一个决定性事件、漫长的沉淀。不要在沉淀期引入新的事件。
  • 相机只跟着动作移动(随墨水下沉,滑行穿过雾气)。推镜头保持在 8% 以下。
  • 种子和噪声场缓慢演变:场偏移量每秒小于 0.05 单位,否则会看起来像在沸腾。

声音调色板与混音

声音和画面一样稀疏。静默本身就是一种信号。

  • 材质: 呼吸(带慢速滤波器扫频的带通噪声)、水(水滴用的上升正弦啁啾声、闷响的气泡声)、纸与笔(带通噪声,伴随稀疏的颗粒咔哒声,笔触变干时增强)、风(两个去相关的噪声床,带有预设的阵风曲线)。
  • 乐器: 气息感强的竖笛(正弦波加上少量二次和三次谐波,音高从下方滑动进入,呼吸噪声与音符锁定)、拨弦(Karplus-Strong 算法渲染到缓冲区,拨弦后可选的音高滑动)、低锣(非谐波泛音带有拍频对,低泛音持续最久)。
  • 和声: 少量开放音程(四度、五度、九度)的音符。避免常见的“东方”五声音阶乐句;让单个音符说话。
  • 空间: 一个长的人工混响(3 至 5 秒,尾部变暗,20 至 40 毫秒预延迟)。乐器湿声,纹理干声。
  • 同步: 滴落声与冲击同步;呼吸领先动作 0.3 至 0.8 秒;锣声与印章同步;旋律音符在视觉事件后 0.1 至 0.3 秒。
  • 目标: 集成功率约为 -18 LUFS,真峰值不超过 -1.5 dBFS,最后一帧尾部低于 -60 dBFS,无爆裂声(每次增益变化至少 5 毫秒的渐变)。

技术方案

1. 预渲染噪声和纸张一次。 上传可平铺的 256x256 RGBA16F 纹理:RG 保存旋度场(周期性梯度噪声的旋转梯度),BA 保存两个独立的噪声。用预设的 JS 代码(颗粒加上 Canvas 2D 纤维笔触)将带有 mipmap 的纸张预渲染为 RGBA8 纹理;每帧采样该纹理,而不是每像素计算 fbm。

2. 墨复合(线性光)。

vec3 lin(vec3 c){ return pow(c, vec3(2.2)); }
vec3 inkOver(vec3 paperLin, float density){
  return paperLin * exp(-density * vec3(3.4, 3.55, 3.75));
}

3. 通过逆平流模拟水中墨。 不进行模拟。将墨描述为少数解析基元(滴、茎、涡环、花瓣瓣),其位置是时间闭形式的函数,然后在扭曲的坐标上求值。扭曲是沿旋度场的几步,振幅随时间(从冲击时刻起)增长,从而将基元拉伸成卷曲的卷须。

vec2 q = p;
for (int i = 0; i < 4; i++) {
  vec2 c = texture(uNoise, q * freq[i] + drift * t).rg;   // 旋度场
  q += amp[i] * growth * c;
}
float dens = primitives(q, t);              // 高斯核 + 宽雾纱
dens += sheet(q) * veil;                     // 脊状噪声:侧视片状
  • 保持扭曲低频(基尺度为每帧高度 1 到 3 个周期,弱的三分之一倍频程)。高频扭曲会使墨变成扭动的虫子。
  • 卷曲效应来自局部旋涡(围绕每个涡核旋转 q,角度按高斯衰减),而非更多噪声。
  • 花瓣、瓣和雾纱需要柔和的边缘(高斯,宽度为半径的 0.2 至 0.3)。形状内部的细暗等高线看起来像地形图。
  • 判断轮廓,而非细节:一个径向五瓣形状从正面看像水母或海星。倾斜它(为向下约 30 度的相机投影 3D 瓣),否则会像花。
  • 保持细、锐、不透明的轨迹看起来像线或茎。将其视为尾迹:加宽、柔化、卷曲并在约一秒内淡出(先顶部),使形态独立。
  • 用暖色系数(蓝色多于红色,例如 vec3(3.2, 3.6, 4.2))吸收墨芯,用中性系数吸收稀释的边缘。这样芯呈现为墨黑色,而非平淡的灰色。

4. 笔触作为极坐标场。 对于円相(enso),使用 r(theta) = R + wobble(theta)。对每个像素计算角度,转换为笔触进度 u 和跨越笔触的有符号距离 d / width(u)。在 u < brushHead(t) 处显现。湿润度、宽度和干度是 u 的函数;洇染度是 t - timeTheBrushPassed(u) 的函数。

float lanes = texture(uNoise, vec2(across * 5.0, u * 0.35)).b;   // 笔毫纹理
float dryInk = step(dryness(u), lanes * 0.6 + tooth * 0.5);         // 跳过纸张低洼处
float rim = smoothstep(0.75, 1.0, abs(across)) * wet(u);            // 边缘暗化

5. 分层景深用于山水画。 每个山脊是深度 z 处的一维高度轮廓。对每个像素投影到世界 x,查找高度,与透视下该高度处的屏幕 y 比较。墨色在山脊线最强,向下向雾中衰减。从远到近复合,按 1 - exp(-depth * k) 向纸色混合。雾片位于山脊之间的山谷中,随时间漂移。当相机即将穿过山脊时将其淡出。

  • 从近到远复合,使用透射率(acc += T * a * layer; T *= 1.0 - a;),并在 T 接近零时终止。这是精确的,并且成本减半,因为画幅下半部分在一两层后停止。
  • 使用解析一维梯度噪声(哈希加五阶缓动)计算山脊线,而非纹理查找:双线性纹素会在长脊上显示为扭结。
  • 大气需要陡峭的曲线(exp(-0.45 * depth)),以便最远距离读作淡淡的影子而非另一种灰色。

6. 小剪影(鸟、印章)作为边界框测试内的有符号距离场(SDF)胶囊和方框,具有 1.5 像素的抗锯齿边缘。用相位函数驱动翅膀动作,而非物理模拟。

7. 音频构建块。

// 带有可选滑音的 Karplus-Strong 拨弦,确定性地渲染到缓冲区
for (let n = 0; n < len; n++) {
  const d = sr / freqAt(n) - 0.5, r = w - d;
  const a = read(r), b = read(r - 1);
  y = exc[n] + g * 0.5 * (a + b); write(y); out[n] = y;
}

混响脉冲:预设立体声噪声乘以 exp(-t / decay),通过一个截止频率随时间下降的单极点低通滤波器。主效果链:温和压缩器(比例 2 至 3),接着一个快速高比率压缩器作为限制器,然后是可测量的增益补偿,最后是线性主淡出,在结束前约 0.15 秒达到零,以确保混响尾部消失。

  • 位精确混音。 Chromium 以不确定的顺序对节点的输入求和。浮点加法仅对两个操作数产生相同位;压缩器会将 1e-7 舍入放大为可听电平的差异。通过链接增益节点,使每个混音点最多具有两个输入:
function summer(ctx, target) {        // 返回 add(node); 每个混音点 <= 2 个输入
  let open = target, count = 0;
  return node => { if (count === 1) { const j = ctx.createGain(); j.connect(open); open = j; count = 0; } node.connect(open); count++; };
}
  • DynamicsCompressorNode 会自行应用自动增益补偿,因此降低阈值会使混音更响。改用输出增益来设置响度。
  • 检查各声道的平衡:在不带旋律的情况下渲染一次。如果背景音与完整混音之差在 2 dB 以内,则旋律被掩盖了。

确定性渲染检查表

  • renderFrame(t) 仅根据 t 设置所有统一变量;不使用积累、Date、performance.now 或 Math.random。
  • 所有随机性来自预设的 PRNG(mulberry32)或加载时预计算的纹理哈希。
  • 纸张、噪声和 IR 在加载时同步构建,且永不改变。
  • 向后查找产生相同的像素;在播放后期后测试 t = 0。
  • 在 1920x1080 分辨率下使用软件 WebGL 测量帧成本;保持在 1.5 秒以下。对细微细节使用边界框,并将扭曲循环限制为四步。
  • 颗粒是静态的,低于 2%;无逐帧全屏噪声。
  • 线条和细丝至少有 1.5 像素的柔和衰减。
  • 音频使用预设的噪声缓冲区,且每个混音点最多有两个输入;两次调用必须返回字节相同的缓冲区。
  • 预览模式使用 requestAnimationFrame 循环;渲染模式自身不绘制任何内容。

避免

  • 纯白纸、纯黑墨、超出单独朱红标记之外的高饱和度颜色。
  • 类似书法的笔触、字符、伪书法、签名、常见的文化道具。
  • 多个动作同时出现;杂乱的背景;以恒定速度不断运动的墨水。
  • 发光、镜头光晕、色差、散景;墨水是哑光的。
  • 用均匀模糊冒充扩散;真正的扩散同时具有清晰的核和柔和的纱。
  • 风铃、每次剪辑时的铃铛声、持续的垫音、呼啸声、常见的五声音阶乐句。
  • 以切到黑色结尾;让图像沉淀或溶解到纸色或灰色中。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相关技能