docs(skills): teach shared cut constants and fill lights for Three.js scenes (#5077)

The three adapter skill had no guidance for camera cuts made inside one
canvas. A visibility window written as its own literal near a cut shows
the next shot's objects for the last frames of the previous shot, a
two-frame pop-in that a still per shot does not reveal. The skill now
says to declare each cut once, read it in both the shot selector and
every visibility window, and snapshot the last frame before each cut.

It also explains why a MeshStandardMaterial lit by a single key light
renders as a flat black cutout when the camera faces that light, and to
add a fill such as a HemisphereLight driven at a fixed ratio to the key.

Signed: Miga

Co-authored-by: Miguel Ángel <miguel.sierra@heygen.com>
This commit is contained in:
miga-heygen
2026-10-05 16:59:59 +00:00
committed by GitHub
co-authored by Miguel Ángel
parent 98fe011699
commit 6c353d89c8
2 changed files with 32 additions and 1 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
"files": 29
},
"hyperframes-animation": {
"hash": "5a771a306ac3b34e",
"hash": "6af72990949385ca",
"files": 122
},
"hyperframes-audio": {
@@ -114,6 +114,37 @@ function renderAt(time) {
If several mixers exist, seek all of them from the same `time`.
## Camera Cuts Inside One Canvas
When one scene switches camera shots by time, declare each cut once and read that constant everywhere: in the camera's shot selector and in every object's visibility window. A window written as its own literal near the cut (`t > 22.9` against a cut at `t < 23`) shows the next shot's objects in the last frames of the previous shot. At 30 fps that is a two-frame pop-in, which one still per shot will not show.
```js
const CUT_B = 23;
const CUT_C = 35;
function shotFor(t) {
if (t < CUT_B) return shotA(t);
if (t < CUT_C) return shotB(t);
return shotC(t);
}
function renderAt(t) {
const shot = shotFor(t);
camera.position.copy(shot.position);
camera.lookAt(shot.target);
shotBProps.forEach((mesh) => {
mesh.visible = t >= CUT_B && t < CUT_C;
});
renderer.render(scene, camera);
}
```
Verify each cut on the last frame before it and the first frame after it, not only somewhere inside each shot. The last frame before a cut is `(Math.ceil(cut * fps) - 1) / fps`: for a cut at 23 s in a 30 fps render, `npx hyperframes snapshot --at 22.9667,23 --no-end`.
## Lighting Lit Meshes
A `MeshStandardMaterial` lit by one `PointLight` or `DirectionalLight`, with no ambient light, environment map or emissive color, gets no light on its unlit side. When the camera faces that light, the mesh shows only that side and renders as a flat black cutout. Add a fill that stands in for the environment's bounce light, such as a `HemisphereLight` in the colors of the surrounding glow. If the key light's brightness changes over time, drive both lights from the same source at a fixed ratio, tuned by eye. Their intensity units differ, so do not copy the key light's number onto the fill.
## Good Uses
- Deterministic 3D objects, product spins, particles with seeded data, and shader plates.