Community图像github.com

手绘3D建模

将物体、动物、植物、食物或小场景以手绘墨水与马克笔风格渲染为3D模型,输出一个自包含的循环动画SVG(其中包含一个运动部件),以及一张PNG静态图或GIF。

手绘3D建模 是什么?

该“手绘3D”技能能让AI助手将用户指定的任何具体物体(如茶壶、烤面包机、风车、猫等)建模为3D模型,并以独特的“手绘墨水+马克笔”风格渲染输出。它利用一个专有的JavaScript工具包(kit.js)和渲染器(render.mjs)来创建等距视角的3D场景,自动为每个面分配平涂的明暗色调,并添加手绘质感的抖动外轮廓线,背景为奶油色纸纹。输出格式是自包含的、无脚本的循环动画SVG,通过CSS切换帧——这意味着它可以在浏览器和`<img>`标签中播放。此外,它还能生成PNG静态图和GIF动画。该技能专为“3D绘图”类请求设计,不适合图表、流程图或UI组件。工作流程涉及:将物体分解为几何实体部件(通过`k.box`, `k.lathe`, `k.tube`等API),使用`k.wave()`或`k.pulse()`等函数为某些部件添加循环运动(如盖子跳动、蒸汽升腾),然后通过渲染器生成并输出文件。它严格遵循风格指南,包括色调数量限制(3-5种颜色加墨线)、自动相机(默认等距)以及通过`k.group()`辅助的动画逻辑。此技能支持文字标签和内置手写字体(含越南语支持)。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/duy211099/handdrawn-skill/tree/HEAD/handdrawn-3d

Installed? Explore more 图像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜欢的 AI 中提问

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

文档

手绘3D建模 是做什么的?

你使用几个简单的实体为对象建立3D模型,然后工具包以手绘风格绘制它。每个面从左上角光源获得三个平涂的马克笔色调。相邻且色调相同的面会融合成一个色块。外轮廓用粗墨水线,折痕线用较细的、抖动渐尖的线条,画在奶油色纸上。场景根据一个循环变量 t 逐帧绘制。输出是一个循环动画SVG:帧通过CSS切换,无需脚本,因此可在浏览器和<img>标签中播放。文本使用内置手写字体,支持完整越南语。

工具包:assets/kit.js · 渲染器:assets/render.mjs · 所有函数和选项:references/kit.md(在编写场景前阅读) · 工作示例:examples/(杯子、茶壶、烤面包机、风车:阅读最相似的那个)。

首次设置

PNG/GIF导出需要 @resvg/resvg-js。如果 render.mjs 提示缺少此依赖,请在该技能的文件夹中运行 npm install。SVG本身无需任何外部依赖。

开始绘制前

  • 它能被画出来吗? 如果主题是抽象的(如“希望”、“效率”),不要画模糊的东西。建议一两个能展示它的具体场景,然后绘制用户选择的一个。
  • 图表、UI、按钮、交互式内容: 不使用本技能。
  • 什么会动? 每张图片都动画化物体本身:相机从不移动。选取属于该物体的一到两个运动。水壶的盖子跳动并冒气。烤面包弹起。风车的风车叶片转动。风扇旋转。猫尾巴摆动。台灯点头。植物摇摆。如果用户指定了一个运动,就使用那个运动。如果没有东西可以合理移动,就使用蒸汽、轻微上下摆动或摇曳,以及线条本身的抖动效果。

工作流程

  1. 拆解部件。 列出物体的真实部件,以及每个部件如何由实体构建。在场景文件顶部的注释中将其写成一个表格:部件 · 调用函数 · 尺寸/位置 · 颜色。根据真实部件(边缘、盖子、旋钮、手柄、脚、槽、铰链)建模,而不是画一个带名字的色块。查询你不确定的比例。
  2. 建模到 scene.js 中(世界坐标系:x向右,y向后,z向上,地面 z = 0;单位近似毫米;自动适配画面):
    • 可以在陶轮上旋转的圆形物体 → k.lathe(容器使用 wall: 参数)、k.cylinder、k.sphere
    • 方形物体 → k.box(使用 round: 参数实现柔软圆角)、异形轮廓 → k.extrude
    • 手柄、壶嘴、管道、腿、线缆、茎 → k.tube,起始于主体内部(会在表面处被截断)
    • 容器里的内容物 → { in: container };平面上的标记 → k.panel / k.line 加上 { on: solid }
    • 当物体的“侧视图”应面向观者时,使用 k.group({ rotate: { z: 45 } }, …) 旋转整个物体(例如茶壶的壶嘴在左,手柄在右)
  3. 制作动画 使用 t ∈ [0, 1):运动部件放在 k.group({ about, rotate, at }, …) 中,并由 k.wave()、k.pulse() 或 360 * t 驱动。每个运动必须在 t = 1 时回到起始位置。
  4. 渲染并检查:
    node <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png --strip --thumb
    
    使用阅读工具打开 out/scene.png(静态图)和 out/scene-frames.png(循环中的6帧),并观察它们。添加 --grid 以读取图纸坐标。检查 out/scene-128.png:它必须在128像素大小时仍然能被识别出是什么物体。
  5. 修正并重新渲染。 检查:
    • 一眼看去是否能识别出物体?首先要看轮廓。
    • 没有顺序错误的绘制: 部件穿透主体、远处的部件遮住近处的、内容物被遮挡或穿出。使用 references/kit.md 中“实体排序规则”下的方法修正:分离实体、in:、on:、只建模开口外部部分,以及最后手段的 layer。
    • 部件接触其支撑物。没有漂浮的部件(除非它应该漂浮,如跳动的盖子)。
    • 运动在帧序列中一目了然,并且循环没有跳变。
    • 标签位于边缘,并且尽可能少地跨越图形。 重复步骤4-5直到正确(通常需要2-4轮)。最终渲染不带 --grid。

在看过静态图和帧序列之前,绝不交付最终结果。 交付SVG路径(动画图片)、PNG,并展示PNG。当用户需要GIF,或者SVG需要放在不支持SVG动画的地方(如聊天应用、某些电子邮件客户端)时,添加 --gif out/scene.gif。

风格规则

  • 统一风格: 纸上的墨线+平涂马克笔色调。无渐变、发光、模糊、透明度效果、SVG <text> 或原始SVG。仅使用此工具包。
  • 颜色: 使用调色板名称(参见 references/kit.md),每张图片3-5种颜色加墨线。调色板名称效果最佳;任何十六进制颜色都会被柔化。每个填充自动提供亮、中、暗三个色调。不要用额外的实体伪造阴影。
  • 相机: 默认为等距视角。仅在必要时更改 sheet.camera。对于高耸物体(塔、瓶子、灯、人物),使用较低俯仰角(20-25)和25-35偏航角可获得更友好的“产品展示”效果。
  • 简洁而厚实: 几个干净的实体比许多琐碎的小块可读性更好。小部件(旋钮、脚、按钮)是使其看起来真实的关键:一定要添加它们。
  • 放置于地面: 阴影是自动的。站在板、桌子或碟子上的物体将阴影投射到支撑物上。在小物体下放置一块板、托盘、土丘或桌子有助于其定位到空间中。
  • 文字: 可选的 k.title(...) 位于左上角,以及指向3D点的简短小写边缘注释(k.label)。使用用户的母语编写。图形上不要有文字框或对话气泡。
  • 画布: 默认为1000×1000。对于宽场景,使用 export const sheet = { width: 1200, height: 900 }。加上 --transparent 可移除纸张背景。
  • 动画规格: 默认16帧,12 fps(一个1.3秒的循环);典型的SVG大小在0.5-1 MB之间。对于慢动作,使用 sheet.fps = 8。保持 frames ≤ 24。

场景模板

// 三脚架上的茶壶;盖子跳动。
// 部件        调用函数        尺寸/位置                           颜色
// 三脚架     cylinder        r 120, h 10                         wood
// 壶体       lathe { smooth } r 55→94→50, h 118, 在三脚架上       teal
// 壶嘴       tube [14, 7]     从壶体内部开始,向左延伸             teal
// 手柄       tube 8           两端都在壶体内部,右侧               teal
// 盖子+旋钮  lathe + sphere   在以其后边缘为铰链的组内             teal, ochre
export const sheet = { seed: 3 };
export function draw(k, t = 0) {
  k.cylinder([0, 0, 0], 120, 10, { fill: 'wood' });
  k.group({ rotate: { z: 45 } }, () => {                          // 壶嘴朝向屏幕左侧,手柄朝向屏幕右侧
    k.lathe([0, 0, 10], [[55, 0], [78, 10], [94, 45], [90, 85], [68, 112], [50, 118]], { fill: 'teal', smooth: true });
    k.tube([[-78, 0, 50], [-112, 0, 66], [-128, 0, 100], [-146, 0, 118]], [14, 7], { fill: 'teal' });
    k.tube([[70, 0, 112], [112, 0, 108], [122, 0, 72], [84, 0, 40]], 8, { fill: 'teal' });
    const hop = Math.max(0, k.wave(0, 2 * t));                    // 0..1,每循环跳动两次
    k.group({ about: [44, 0, 128], rotate: { y: -18 * hop }, at: [0, 0, 16 * hop] }, () => {
      k.lathe([0, 0, 127], [[52, 0], [50, 5], [30, 13], [8, 18], [0, 19]], { fill: 'teal', smooth: true });
      k.sphere([0, 0, 152], 10, { fill: 'ochre' });
    });
    k.steam([-150, 0, 125], { h: 90, n: 2, spread: 18 });
  });
  k.label('跳动的盖子', { to: [0, 0, 140], side: 'right' });
}

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能