Teardown Cinema
与 teardown(Three.js 代码、一个时钟、逐帧捕获、代码生成的配乐)使用相同的引擎,但目的相反。Teardown 用于解释,因此它有面板。Cinema 用于展示,因此屏幕上除了世界之外什么都没有。示例(包含所有文件):此技能中的 example/orison(30 秒电影 Orison 及其交互页面)。
需要与此技能并排放置 teardown 技能,以获取 node_modules(three、esbuild、playwright)、sims/capture.mjs 和 sfx/。捕获不需要 Playwright 自带的 Chromium:设置 CHROMIUM 为已安装的 Chrome。如果下载卡住,Chrome 也可以。
方法,按顺序
- 一张主图。 使用任何强大的图像模型生成一张复杂的图片。在 Codex 应用中:
codex exec --skip-git-repo-check -s workspace-write -C <dir> - < prompt.txt。提示词会离开你的机器,因此不要在其中包含机密内容。要求一些有结构、你可以命名的东西:圆顶、肋骨、环、丝带。Codex 不会报告它使用了哪个图像模型。 - 从主图生成纹理板。 使用
-i master.png附加主图,然后生成平坦、正面、光照均匀的纹理板:玻璃面板、纯黑背景上的金属花纹、丝绸、纯黑背景上的行星、环的横截面、俯视的生物。黑色是你需要裁切掉的部分。这些纹理板是结果能保留绘画细节的原因。一次只生成一个。 - 测量主图,然后重建它。 从图像中以像素为单位读取比例,并在编写几何体之前将其转换为世界单位。这里早期的错误几乎都是因为没人测量比例。
- 一个输入驱动整个主体。 选择生物或机器的节拍,用 JS 和 GLSL 编写,并在顶点着色器中根据此节拍摆布每个部分。没有任何关键帧。参见
shared/kin.js、shared/glsl.js。 - 镜头,而不是飞越。 一个镜头列表,每个镜头是其内部时间的纯函数,带有硬剪辑和每个镜头一个色彩分级。剪辑是让它成为电影的关键。参见
orison-film/shots.js。 - 每次迭代都与主图对比。 将主要画面与图像并排渲染,并记录差异。修复,重复。
- 在相同时间线上用代码生成配乐,使用 teardown 的
sfx/。参见score.py。 - 页面是同一个世界,只是操控摄像机的手不同。 滚动选择路径上的一个点,点击是一个节拍,拖动环顾四周。参见
orison-live/。
目录结构
my-film/
brief/ 主图和提示词
assets/ 纹理板,保存为 .jpg(内联到页面中)
shared/ 世界:kin.js、glsl.js、sky.js、creature.js、world.js
my-film-film/ main.js、shots.js、timeline.json
my-film-live/ main.js、path.js、audio.js、body.html、style.css
score.py
命令
从影片文件夹中运行。SKILL_DIR 是此技能,T 是并行的 teardown 技能。在 Windows PowerShell 5.1 中使用 npx.cmd 和 npm.cmd,不要用 &&。
node "$SKILL_DIR/build.mjs" ./my-film-film ./my-film-live
export CHROMIUM="C:/Program Files/Google/Chrome/Application/chrome.exe" # 捕获可以使用已安装的 Chrome
# 单帧,或一张拼接图,以选定质量:--config 指向 {"samples": N}
node "$T/sims/capture.mjs" my-film-film --size 1920x1080 --dpr 1 --config s.json --still 12.5 --out frame.png
node "$T/sims/capture.mjs" my-film-film --size 1920x1080 --dpr 1 --config s.json --stills 3,8,12,18,23,29 --cols 3 --out sheet.png
# 整部电影
node "$T/sims/capture.mjs" my-film-film --size 1920x1080 --dpr 1 --fps 24 --crf 15 --config s.json --out silent.mp4
python "$T/run_sfx.py" score.py
ffmpeg -i silent.mp4 -i teardown-out/my-score.wav -map 0:v -map 1:a -c:v copy -c:a aac -b:a 256k -shortest -movflags +faststart film.mp4
--stills 通过调色板平铺,因此拼接图会显示虚假的色带。通过其旁边的全帧来判断颜色和色带。
kit/cinema.js 提供给你的功能
new Cinema({canvas, samples, fps, shutter, msaa}),然后调用 cine.frame(t, draw, look)。
一个电影帧是 N 个子帧的平均值。每个子帧移动快门内的时间(真正的运动模糊)、相机在镜头盘上的位置并保持焦平面(真正的景深,也作用于透明图层),以及亚像素偏移(抗锯齿)。抖动的光线步进与此收敛。后期处理在平均后的 HDR 图像上运行一次:泛光、变形拉伸、朝一个点的光柱、ACES、色彩分级、颗粒、暗角。samples: 1 用于交互式页面的相同管道。
来自一台搭载集成 Radeon 780M 的笔记本电脑的数据,分辨率为 1920x1080:每帧 32 个样本(包括编码)耗时 2.3 秒:30 秒电影(24fps)需 27 分钟。960x480 分辨率和 4 个样本的草稿整部电影仅需 41 秒,因此可以随意使用草稿。交互式页面在 1600x900 分辨率下,整个滚动过程中帧率为 37 到 51 fps,在无其他程序运行时单点读数更高。检查捕获输出中的 gpu:;软件渲染器意味着 GPU 标志未生效。
决定成败的规则
- 画面中不能有文字。没有标签、数字、标题卡或字幕。 图片本身承载一切。
- 只打包一个 three.js 副本。
build.mjs强制实现。靠近影片的第二个副本(项目自己的node_modules)会静默失败:反射环境会丢失模糊级别,金属会变暗。 - 将渲染结果与主图以相同尺寸并排摆放,并列出差异。 首先是比例,然后是颜色。以像素为单位测量位置,并将其转换为方向。Orison 的大部分相似度都来自这些迭代。
- 景深只在物体很小时才保持较浅。 在巨大物体上使用重度模糊会使其看起来像微缩模型。对于 26 单位的生物,电影镜头半径为 0.012 到 0.03 单位。
- 时间样本和镜头样本不能共享同一个序列。 如果共享,模糊会出现可见的弧线。镜头使用黄金角,时间使用 Halton 基数 5。
- 永远不要对可能为负的值使用
pow()。 D3D 返回 NaN,一个 NaN 像素会通过泛光扩散为黑色矩形。用x*x。用max(1.-ndv,0.),而不是1.-ndv。此工具包也会清理其输入。 - 在 Windows 上,
smoothstep(a, b, x)中a > b会返回 0。 使用1.-smoothstep(b,a,x)。 - 在缩窄的表面上使用镜像纹理板时: 使用墨卡托投影以确保单元格保持圆形,并且只镜像纹理板的大单元格。细小的单元格在近距离会变成五彩纸屑。
- 与光线对齐的面板必须更清晰,而不是更亮。 否则,玻璃体内部的东西永远无法被看清。
- 黑暗的开口中需要有某种有生命的东西。 在第一个节拍到来之前,雾气中微弱的辉光可以承载一切。
- 交互式页面中的云: 半分辨率加上运行平均;在靠近摄像机的地方进行更密集的步进。云是柔和的,所以不会丢失细节。
- 交互式页面的第一秒是着色器编译。 在第一帧之前编译,并同时显示一个小脉冲,不显示加载文字。
交互式页面规则
teardown 交互式规则中的所有规则都适用(质量分级、预热着色器)。此外:打开时显示主图,着色器准备好后溶解到 3D 场景;当帧率恢复时,质量分级会回升,而不仅仅是下降;页面上没有标签;canvas 和任何按钮都有无障碍名称;点击目标至少 44 像素;声音仅在第一次手势后开始;主体在节拍后稳定下来,而不是无限攀升;质量根据测量的帧率自动降级,无需询问。
审阅
你无法观看视频,但你可以阅读帧。首先查看每个镜头的拼接图,对于拼接图标记的内容查看全帧,然后使用 --stills every:0.2 --from A --to B 查看过渡过程。读取最终编码的每秒一帧的拼接图:这显示了编码器写入了什么。使用 ffmpeg -af ebur128=peak=true 测量配乐。仍然需要有人观看电影并聆听配乐一次;在报告时说明这一点。
对于提供自己文档骨架的主机(例如 Claude Artifact),使用 FRAGMENT=1 构建,并用 PAGE_TITLE 设置名称:它还会写入 <name>.fragment.html。