Communitygithub.com

三维动画

用 Remotion 和 three.js 把短片写成代码,并交代摄影机、光、运动和声音。

三维动画 是什么?

它把三维片段当成一条被导演的镜头,而不是灰底里转圈的物件。会先定摄影机、光、运动和声音,再用 Remotion 和 three.js 逐帧写出来。适合产品或物件动画、有电影感的三维短片、竖屏短片,或一条看起来发平的现成场景。

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

在你喜欢的 AI 中提问

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

文档

3D动画师

一个简单的提示词只能得到一个在灰色虚空中心旋转的物体:静态摄像机、平淡的光、线性运动且没有声音。而一位动画师在编写任何代码之前会思考四件事:摄像机、灯光、运动和音效。本技能让你像动画师一样思考,然后将每一帧都编写成代码。

这些规则源自一个WhatsNext AI (@whats.nextai) 的制作流水线,并针对实测表现最佳的短视频进行了调优:

  • 静态帧率低于10%;
  • 每10秒硬切约0.7次;
  • 音乐音量低于人声约9dB。

0. 编码之前:进行导演

首先编写一个镜头列表。每个节拍对应一行:

节拍 | 秒数 | 主体 | 摄像机运动 | 灯光变化 | 动作事件 | 音效提示

镜头列表规则:

  • 第1帧展示主体。 不要从黑色淡入,不要显示Logo,不要在空舞台上开场。
  • 大约每1.5秒改变一些可见的东西: 摄像机移动、揭示或灯光变化。
  • 每个节拍只改变一件事: 比例(广角↔微距)、角度、光线或物体的状态。永远不要同时改变所有。
  • 重组同一个物体,而不是切换到不相关的场景。 结束镜头应与开场镜头呼应。
  • 没有主体?选择一个具有隐藏内部结构的物体, 以便摄像机有地方可去:手表、手机、引擎、城市街区、电缆。规划一个切出或揭示镜头。

1. 摄像机 (references/camera.md)

  • 摄像机从不静止。 在每个镜头之上添加一个由两个不可公度正弦波组成的缓慢轨道和呼吸式晃动,以确保没有静态帧。初始值:about 0.17 rad × sin(0.8t) + 0.09 rad × sin(1.9t + 0.7)。
  • 在关键摄像机之间使用缓入缓出(三次方)进行移动。 绝不使用线性移动,也绝不快切。
  • 推拉镜头,不要变焦。 移动摄像机位置,并将物体视野角度保持在30°到40°之间。广角FOV会扭曲产品。
  • 揭示时推进。提供背景时拉远。 每个节拍一次移动。
  • 减少硬切: 每10秒约0.7次。运动来自摄像机,而非剪辑。
  • 竖屏9:16构图:
    • 将主体保持在画面高度的中间60%。
    • 顶部15%用于标题。
    • 底部25%用于字幕和应用UI。
    • 在Instagram和TikTok上,右侧保留150像素空白。
  • 景深: 在前景放置一些物体,主体在中间,背景柔和。在视点附近添加漂浮的灰尘颗粒或粒子,即使缓慢的移动也能被感知为运动。

2. 灯光 (references/light.md)

  • 深色背景,一种强调色,一个主体。 例如,海军蓝 #0B0F18 的场景搭配橙色 #FF914D 的强调色用于“信息”。
  • 灯光设置:
    • 半球填充光:天空 #A9BDE0,地面 #0B0F18,强度约0.8。
    • 一束来自左前方的冷色调主定向光:强度约1.5,投射阴影。
    • 一侧是暖色点光源,另一侧是冷色点光源,使边缘与背景分离。
  • 反射: 使用环境贴图(通过 PMREMGenerator 加载 RoomEnvironment),强度0.2–0.6。没有它,金属和玻璃看起来像塑料。
  • 泛光仅用于特定目的:
    • 使用UnrealBloomPass,阈值0.9或更高,强度约0.4,半径约0.4。
    • 应该发光的物体使用 emissive 属性,其他物体不发蓝光。
    • 过曝陷阱: 纯白色材质加上泛光会使画面发白。使用浅灰色(#C9CFD9)作为“白色”塑料。
  • 使用雾(<fog args={[bg, near, far]}/>),使距离逐渐淡入背景色。
  • 灯光变化即故事节拍: 某部分在命名时亮起,房间为揭示变暗,闪光落在关键点。

3. 运动 (references/motion.md)

  • 每个动画都是帧的纯函数: t = frame / fps。
    • 绝不使用 Date.now() 或 Math.random()。使用remotion的 random(seed)。
    • 绝不使用 useFrame 进行动画。
  • 弹跳效果使用弹簧(阻尼12-14,刚度约170)。移动使用三次缓入缓出。仅对恒定运动如传送带和粒子漂移使用线性动画。
  • 相关元素交错3-5帧。 永远不要在同一帧上移动十个东西。
  • 添加次要动画: 主体物体缓慢转盘旋转(±0.4 rad),漂移的微粒,呼吸式缩放(±1%)。
  • 停顿是一种选择。 当它是一个刻意的戏剧性节拍时,最长2秒的冻结是可以的。否则总有东西在动。
  • 标签: 简短的大写状态标签在他们命名的节拍上弹出。将重制作品标记为“3D RECREATION”。

4. 音效 (references/sound.md)

  • 每个事件对应一个音效:
    • 大范围摄像机移动时用呼啸声;
    • 揭示时用重击声;
    • 揭示前用约2秒的上升音;
    • 标签出现时用咔嗒声或啵声。
    • 合成它们(scripts/sfx_synth.py)或使用CC0音效包。
  • 背景音乐音量设于人声下方6-11dB,目标约9dB。 在旁白下对音乐进行侧链压缩闪避。
  • 沉默是一种效果。 在关键台词前让音乐停止一个节拍,然后在重击声中猛然切回。
  • 母带处理至-14 LUFS综合响度,真实峰值低于或等于-1.5 dBTP。将人声音轨填充至完整时长,防止音乐尾部被截断。

5. 代码规则 (Remotion + three.js)

  • 画布: 从 @remotion/three 导入 <ThreeCanvas width={width} height={height}> 包裹3D内容,并且始终包含灯光。
  • 序列: 画布内的任何 <Sequence> 都需要设置 layout="none"。
  • 后期处理: EffectComposer 可以通过优先级为1的 useFrame(() => composer.render(), 1) 接管渲染。这是唯一允许的使用方式,因为Remotion每帧推进场景一次,确保输出是确定性的。参见模板 Fx3D.tsx。
  • 状态: 通过一个单一的状态函数 worldAt(t) 驱动场景,该函数返回摄像机、舞台和标志位。保持组件无状态(dumb)。
  • 渲染: 在macOS上当WebGL输出为黑色或不稳定时,使用 --gl=angle 参数渲染。使用H.264、yuv420p、1080×1920、30 fps。

现成组件(直接复制,不要导入):

  • templates/Fx3D.tsx:环境反射和泛光。
  • templates/camera.ts:easeCam、orbit、ramp、pop。
  • templates/Motes.tsx:确定性的尘埃粒子。

6. 像编辑一样验证

  1. 渲染4-6张静态帧:钩子镜头、每个揭示和最后一帧。检查过曝、主体被字幕或标题截断、空帧和不可读的文本。
  2. 渲染视频,然后运行 scripts/check_motion.sh out.mp4。目标:静态帧率低于10%,运动(YDIF)约2或更高,每10秒硬切约0.7次。如果视频静止,增加轨道或晃动、添加微粒、或增加推进镜头。不要增加剪辑点。
  3. 如果有音频,检查响度(-14 LUFS)并且音乐音量设于人声下方约9dB。
  4. 仅重新渲染失败的部分。

完成意味着: 镜头列表已存在,每个节拍都有摄像机运动、灯光角色、动作事件和音效提示,检查通过,并且你已查看静态帧。

相关技能