greenlight-motion 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -0
- package/README.md +37 -9
- package/THIRD_PARTY_LICENSES.md +1 -1
- package/cli/index.mjs +118 -13
- package/cli/plugin3d.mjs +202 -0
- package/dist/assets/rigWorker-CGpWyn_f.js +1 -0
- package/dist/bundle-inputs.json +36 -0
- package/dist/greenlight-motion-script.mjs +16524 -202
- package/dist/greenlight-motion.js +698 -688
- package/dist/greenlight-motion.mjs +78778 -74492
- package/dist/script-inputs.json +6 -1
- package/package.json +9 -1
- package/schema/capabilities.json +1 -1
- package/skill/SKILL.md +22 -11
- package/skill/references/scene-script.md +86 -0
- package/skill/references/video-3d.md +223 -8
- package/skill/references/video-camera.md +3 -2
- package/skill/references/video-effects.md +13 -1
- package/skill/references/video-keyframes.md +6 -0
- package/skill/references/video-particles.md +5 -11
- package/skill/references/video-paths.md +2 -1
- package/skill/references/video-projects.md +18 -11
- package/skill/references/video-shapes.md +1 -0
- package/skill/references/video-text.md +43 -7
- package/skill/references/video-world3d.md +1548 -0
- package/skill/references/world3d-schema.json +15118 -0
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- [Particle Activation — a sweep instead of a pop](#particle-activation-activation--a-sweep-instead-of-a-pop)
|
|
18
18
|
- [Particle objects — stamp layers instead of sprites](#particle-objects-objects--stamp-layers-instead-of-sprites)
|
|
19
19
|
- [Lines — trails and ready-made lines](#lines-rendermode-lines--trails-and-ready-made-lines)
|
|
20
|
-
- [Particles
|
|
20
|
+
- [Particles in a world Scene](#particles-in-a-world-scene)
|
|
21
21
|
- [What re-bakes and what is free](#what-re-bakes-and-what-is-free)
|
|
22
22
|
|
|
23
23
|
### Particle layers (`mediaType: "particles"`) — a simulated Solver Box filmed by the project camera
|
|
@@ -178,9 +178,9 @@ Distribution is part of the simulation, so changing it re-bakes (a `mode` of `ra
|
|
|
178
178
|
|
|
179
179
|
#### The fluid field (v3) — fluid and smoke physics, Particular-style
|
|
180
180
|
|
|
181
|
-
`forces.fluid` turns on a **simulated** force field: an incompressible velocity grid the size of the Solver Box that emission stirs and particles ride. Unlike turbulence (a formula in position and time) it has **memory** — a plume meets the eddies it left behind, smoke curls back on itself, ink mushrooms. It is stepped at 1/60 s with the particles and thrown away after the bake; only particle snapshots are cached. The fluid supplies **movement** — particles carried, swirled and lifted by a medium. It is not rendered itself: there is no volumetric or dye render mode, and particles are always drawn as particles (for volumetric smoke and fire inside a 3D world, see world3d.md
|
|
181
|
+
`forces.fluid` turns on a **simulated** force field: an incompressible velocity grid the size of the Solver Box that emission stirs and particles ride. Unlike turbulence (a formula in position and time) it has **memory** — a plume meets the eddies it left behind, smoke curls back on itself, ink mushrooms. It is stepped at 1/60 s with the particles and thrown away after the bake; only particle snapshots are cached. The fluid supplies **movement** — particles carried, swirled and lifted by a medium. It is not rendered itself: there is no volumetric or dye render mode, and particles are always drawn as particles (for volumetric smoke and fire inside a 3D world, see [video-world3d.md](video-world3d.md#smoke-and-fire)). **Cost:** the grid steps 360× for a 6 s clip — `low` ≈ 4 ms/step, `medium` ≈ 10, `high` ≈ 30, `ultra`/`flat-hd` ≈ 80, `volume-hd` ≈ 250 — so a `flat-hd` preset bakes for ~30 s (in a worker, while the live GPU preview already shows the edit — see **Live preview** below).
|
|
182
182
|
|
|
183
|
-
**Live preview vs. the bake.** In the desktop editor the whole solver — field and particles — also runs **live on WebGPU**, so a change to any of these controls shows within a frame while the user edits; the bake above re-runs in the background after the edit and, once complete, is what the editor scrubs (any time is one read) and what **exports render**. Live is also the fallback-free path when the bake is not there yet; the bake is the fallback when live is not possible (Grow Points and the other baked-only features above) or when the live step cannot hold 60 fps on that machine. The bake itself is cancellable, debounced and streams in chunks, so even the fallback appears progressively. None of this changes the JSON: the bake is a pure function of the system and the live engine is only a preview of the same inputs. Route "smoke", "fluid", "ink in water", "cigarette smoke", "steam", "particles flowing like liquid" here when it is a layer of particles; volumetric smoke, fire or an explosion inside a 3D world is world3d.md
|
|
183
|
+
**Live preview vs. the bake.** In the desktop editor the whole solver — field and particles — also runs **live on WebGPU**, so a change to any of these controls shows within a frame while the user edits; the bake above re-runs in the background after the edit and, once complete, is what the editor scrubs (any time is one read) and what **exports render**. Live is also the fallback-free path when the bake is not there yet; the bake is the fallback when live is not possible (Grow Points and the other baked-only features above) or when the live step cannot hold 60 fps on that machine. The bake itself is cancellable, debounced and streams in chunks, so even the fallback appears progressively. None of this changes the JSON: the bake is a pure function of the system and the live engine is only a preview of the same inputs. Route "smoke", "fluid", "ink in water", "cigarette smoke", "steam", "particles flowing like liquid" here when it is a layer of particles; volumetric smoke, fire or an explosion inside a 3D world is [video-world3d.md](video-world3d.md#smoke-and-fire). Ready-made presets: `smoke` (Rising Smoke), `cigarette`, `ink`, `ember`, `shockwave` (a ring blast every 1.5 s that punches the fluid). A `text-cage` preset id is only a label; the system it carries bakes as written.
|
|
184
184
|
|
|
185
185
|
| Field | Range | Meaning |
|
|
186
186
|
| --- | --- | --- |
|
|
@@ -358,15 +358,9 @@ With `render.mode: "layers"`, each particle stamps one of up to 12 members. Obje
|
|
|
358
358
|
|
|
359
359
|
Move the plume with the smoke source's `position` / `motion` (`sweep` ripples the rows); `return.strength` sets how far a row is pulled before it settles (0 = carried off with the smoke).
|
|
360
360
|
|
|
361
|
-
#### Particles
|
|
361
|
+
#### Particles in a world Scene
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
```jsonc
|
|
366
|
-
{ "id": "prtitem1", "clipId": "prt1", "trimStart": 0, "trimEnd": 6, "freeStart": 0,
|
|
367
|
-
"particleLook": "3d",
|
|
368
|
-
"particleSystem": { /* as in the example above */ } }
|
|
369
|
-
```
|
|
363
|
+
A particle layer is drawn flat over the picture. For particles that live in a world Scene as real objects (lit, shadowed, colliding with shapes, traced in Final 3D), write a simulation in the Scene instead: sim.md (GreenLight Dash only).
|
|
370
364
|
|
|
371
365
|
#### What re-bakes and what is free
|
|
372
366
|
|
|
@@ -57,7 +57,8 @@ Any ordinary visual timeline item can follow a saved 3D bezier path. The path is
|
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
- A path is live only when it has at least two valid points and `follow: true`.
|
|
60
|
-
- `motionPathT` is 0–100. On an open path, 0 is the first anchor and 100 the last. On a closed path, 100 completes the loop back to the first anchor.
|
|
60
|
+
- `motionPathT` is 0–100. On an open path, 0 is the first anchor and 100 the last. On a closed path, 100 completes the loop back to the first anchor. The range is shared equally between the segments, not by distance: with 3 anchors, 50 is the middle anchor however long each half is, so evenly spaced anchors give an even speed.
|
|
61
|
+
- **The whole curved move is two keys on `motionPathT`**, 0 → 100. Progress tracks take `Linear` (constant speed); an eased progress crawls at both ends. Ease the pair on purpose, for a layer that starts from rest and lands (`AE Smooth`, or `Power` to land): Linear there starts at full speed and stops dead. A layer that enters at a cut already moving takes a matched start and a soft landing (motiongram/adapters/glea.md (GreenLight Dash only)). Use a path whenever a layer should travel an arc, instead of `translateX` / `translateY` keys with different curves.
|
|
61
62
|
- `aim: "tangent"` aligns the layer's local +X axis with the curve; `aim: "points"` orients the layer from the anchor rotations alone (below); `aim: "free"` preserves its ordinary rotation/keyframes.
|
|
62
63
|
- Anchors may carry a per-point rotation `rx`/`ry`/`rz` (degrees, same sign convention as the layer Rotate fields; omit when all zero — the sanitizer strips all-zero triples), blending linearly between anchors over each segment so the layer banks/tilts/spins into a rotated point as it travels. With `aim: "tangent"` it is applied **in the aimed local frame** on top of the tangent aim; with `aim: "points"` the blended anchor rotation drives orientation by itself on world axes — no tangent alignment — falling back to Free behaviour while no anchor is rotated.
|
|
63
64
|
- While Follow Path is live, the path owns local X/Y/Z position. Turn `follow` off before editing `translateX/Y/Z` as the visible position authority. Scale remains independent; Free aim also leaves rotation independent.
|
|
@@ -326,31 +326,38 @@ Set `"background": { …backgroundConfig… }` at the `data` root to fill the st
|
|
|
326
326
|
|
|
327
327
|
Set `"motionBlurEnabled": true` at the `data` root — a project-wide switch, not per layer — to bake cinematic shutter blur into full renders. The choice is made per output **frame**, not per layer: a frame where motion is detected is rendered as a multi-sample accumulation of the **whole composition** across a shutter window centred on the frame, so every layer that changes inside that window blurs (keyframed layers, text animators, motion layers, transitions, particles), not only the one that triggered it. A frame with no detected motion renders once and stays sharp, so cost only grows where motion exists.
|
|
328
328
|
|
|
329
|
+
Two things are not re-sampled across that window:
|
|
330
|
+
|
|
331
|
+
- **Footage.** A `video` layer (top level or inside a `sequence`) shows the frame's own picture in every sub-frame: real footage already carries its camera's blur, so it is never blended with its neighbouring frames. The layer's own movement (its keys, a parent, the Camera layer moving an unlocked footage channel) still blurs; the picture inside it is one source frame. A speed ramp is not motion by itself.
|
|
332
|
+
- **A Final 3D Scene whose world is all that moves.** When the only things moving across the window are inside a Scene in `"mode": "final"` (its objects', flat layers' and camera's keys, the Camera layer that films it), the frame is traced **once**: every sample gets its own time inside the shutter, so the blur is continuous (no stepped copies) and the frame costs about what a sharp one does. Anything else moving on that frame (another layer, the Rig's own keys, a model layer that moves) renders it the accumulated way ([video-world3d.md](video-world3d.md#motion-blur)).
|
|
333
|
+
|
|
329
334
|
A frame is accumulated when any of these change across its shutter window:
|
|
330
335
|
|
|
331
336
|
- the camera layer's pose (any camera track), or the frame enters or leaves a camera clip;
|
|
332
337
|
- a keyframed layer's resolved pose: its position, rotation or scale as drawn, from any track that places it (`translateX/Y/Z`, `xPercent`/`yPercent`, `rotate`, `rotateX/Y`, `scale`, `scaleX`/`scaleY`), and a live motion path's `motionPathT`, `motionPathOffsetX/Y/Z` or keyed path shape (adjustment-layer pan/zoom included);
|
|
333
338
|
- the parent of a parented layer, or the tracked point of a `motionFollow` layer;
|
|
334
|
-
- a `video` item with a speed curve (any `speedPoints` value other than 1): every frame of that item, the 1× stretches included;
|
|
335
339
|
- a particle system, or an `html` clip drawn live (the render default): every frame they are on screen;
|
|
336
|
-
- the inner timeline of a `sequence` clip, by the same rules, down to the 4-level nesting limit (parenting and `motionFollow` links inside a sequence are not read)
|
|
340
|
+
- the inner timeline of a `sequence` clip, by the same rules, down to the 4-level nesting limit (parenting and `motionFollow` links inside a sequence are not read);
|
|
341
|
+
- letters a Text Animator moves, on 2D text and 3D Text alike: a keyed track while its value changes, a Time cascade while a letter is in flight, Flow, Wiggle, Scramble and a blinking caret (a static offset or a cascade at rest is still);
|
|
342
|
+
- a `model3d` layer's own GLB clips (`model3dConfig.animation`) while they play and the pose changes: a `once` clip past its end, keys that hold and speed 0 are still;
|
|
343
|
+
- the Rig's own keyframes (`sc:` / `scc:` tracks), and what moves inside a 3D Scene: its objects', flat layers' and camera's keys, bodies, cloth, particles, smoke, matter and a `.blend` import's baked playback ([video-world3d.md](video-world3d.md#motion-blur)).
|
|
337
344
|
|
|
338
|
-
Nothing else triggers a frame by itself:
|
|
345
|
+
Nothing else triggers a frame by itself: MotionFast `motion` layers, enter/exit and cross transitions, keyed opacity or effect params, and movement inside footage at normal speed. They blur on frames something in the list triggers and are sharp everywhere else. The same rules hold inside a `sequence` clip.
|
|
339
346
|
|
|
340
347
|
**Strength** is `"motionBlurShutter"` — a **shutter angle in degrees** alongside `motionBlurEnabled`. Only these four values are meaningful; anything else (missing, non-numeric, an off-table angle) snaps to the nearest level, so `180` is the effective default:
|
|
341
348
|
|
|
342
|
-
| Angle | Level | Samples | Cost on
|
|
343
|
-
| --- | --- | --- | --- |
|
|
344
|
-
| `90` | Subtle | 8 | ~8× |
|
|
345
|
-
| `180` | Normal — cinematic default | 16 | ~16× |
|
|
346
|
-
| `270` | Strong | 24 | ~24× |
|
|
347
|
-
| `360` | Max | 32 | ~32× |
|
|
349
|
+
| Angle | Level | Samples | Cost on accumulated frames | Final Scene traced once |
|
|
350
|
+
| --- | --- | --- | --- | --- |
|
|
351
|
+
| `90` | Subtle | 8 | ~8× | ~1× |
|
|
352
|
+
| `180` | Normal — cinematic default | 16 | ~16× (a Final Scene's: 16 traces, each denoised) | ~1× |
|
|
353
|
+
| `270` | Strong | 24 | ~24× | ~1× |
|
|
354
|
+
| `360` | Max | 32 | ~32× | ~1× |
|
|
348
355
|
|
|
349
|
-
The angle is how much of each frame interval the exposure covers, so wider = more blur
|
|
356
|
+
The angle is how much of each frame interval the exposure covers, so wider = more blur; on accumulated frames also proportionally slower. The field is only stored while blur is on. Blur is baked by the full renders (`/render-onserver`, `/render-onserver-job`, the desktop Download) and never shown in the editor preview; the fast `/render` ignores it. Worth enabling for projects with fast zooms/pans that would otherwise strobe. Renders get proportionally slower on accumulated frames (~16× each at the default), and a particle system or a live html clip makes every frame it covers an accumulated one. A frame a Final Scene traces once with its motion keeps that Scene's cost. Putting a 3D object into footage (tracking-data.md (GreenLight Dash only)) sets the angle from the footage's own blur.
|
|
350
357
|
|
|
351
358
|
#### Renderer
|
|
352
359
|
|
|
353
|
-
Every project renders on the engine the app is set to — one app-wide setting, not a project field. Read it with `GET /api/video-editor/engine` (`engine`: `"webgl"`, the default, or `"webgpu"`). Preview and the desktop Download use it; the headless renders (`/render-onserver`, `/render-onserver-job`, `/render-still`) take it as the request's `"renderer"` field, which defaults to `"webgl"`, so pass the engine there to render what the editor shows. It matters wherever shading is written by hand rather than picked from a list: an uploaded Advanced Transition package is authored for one engine and is refused on the other, and a **custom** adjustment/layer effect (`"id": "custom"`) cannot run on WebGPU at all — its body is compiled at runtime, so the effect is skipped with a reason. Building a new template or transition: custom-builds.md (GreenLight Dash only).
|
|
360
|
+
Every project renders on the engine the app is set to — one app-wide setting, not a project field. Read it with `GET /api/video-editor/engine` (`engine`: `"webgl"`, the default, or `"webgpu"`). Preview and the desktop Download use it; the headless renders (`/render-onserver`, `/render-onserver-job`, `/render-still`) take it as the request's `"renderer"` field, which defaults to `"webgl"`, so pass the engine there to render what the editor shows. A 3D Scene ([video-world3d.md](video-world3d.md)) is the exception: it draws only on WebGPU, so a project with one renders and stills on `"webgpu"` whatever the setting or the request says, and an editor on WebGL shows a notice in its place. It matters wherever shading is written by hand rather than picked from a list: an uploaded Advanced Transition package is authored for one engine and is refused on the other, and a **custom** adjustment/layer effect (`"id": "custom"`) cannot run on WebGPU at all — its body is compiled at runtime, so the effect is skipped with a reason. Building a new template or transition: custom-builds.md (GreenLight Dash only).
|
|
354
361
|
|
|
355
362
|
#### Sound & audio fades
|
|
356
363
|
|
|
@@ -183,6 +183,7 @@ The After Effects analog, distinct from clipping masks: it scopes to **one consu
|
|
|
183
183
|
- If the source clip isn't under the playhead the matte is EMPTY — `alpha`/`luma` hide the consumer, inverted modes show it untouched.
|
|
184
184
|
- The matte clips the consumer's **finished** look (after its filters, glow, overlay effects and motion blur), matching AE. The **source is read finished too**: its own `effects` chain, `layerEffects`, rig warp and motion blur shape the matte, so an `extract` (histogram key) or `alphaChoker` on the source layer is the normal way to author a matte from footage rather than from a silhouette.
|
|
185
185
|
- Works at the top level and inside a sequence's inner timeline alike (inside a sequence only the layer's `effects` chain shapes the matte — glow, motion blur and the other Layer Effects are top-level stages); grids strip it on grouping.
|
|
186
|
+
- **World matte** (top level): with `sourceId` the 3D Scene layer's item and `objects: ["<scene object id>", …]` and/or `materials: ["<scene material name>", …]`, the matte is the coverage of those objects in the Scene's picture (Draft and Final, soft edges), and the Scene layer stays visible. Up to three different sets per project. See [video-world3d.md](video-world3d.md#render-passes-and-masks-renderpasses-lookpassmix-world-mattes).
|
|
186
187
|
|
|
187
188
|
#### Card framing on every visual layer
|
|
188
189
|
|
|
@@ -190,20 +190,56 @@ layer transform. **Rotate 3D in a Text Animator turns the letters for real**, sh
|
|
|
190
190
|
"palette": ["#e8392f", "#2f6fe8", "#f5c518", "#2fb04a"], // optional: colours cycled per letter (toy look)
|
|
191
191
|
"material": "plastic",// plastic | matte | metal | glass
|
|
192
192
|
"light": "studio", // studio | soft | dramatic — only without a 3D Rig in the project
|
|
193
|
-
"envIntensity": 1
|
|
193
|
+
"envIntensity": 1, // reflections strength (0–3), only without a Rig
|
|
194
|
+
"castShadow": true, // the letters' shadow on the set, the models and each other (false: none, Draft and Final)
|
|
195
|
+
"receiveShadow": true,// the set's and the models' shadows on the letters (false: none in Draft; Final traces real light)
|
|
196
|
+
"sceneMaterial": "neon" // optional, in a 3D Scene only: wear this material of the Scene (its id), an animated one included
|
|
194
197
|
}
|
|
195
198
|
```
|
|
196
199
|
|
|
197
|
-
- **Lighting.**
|
|
198
|
-
`renderer: "classic"`
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
- **Lighting.** Without a Rig, `light` picks a studio set and `envIntensity` the reflections. With
|
|
201
|
+
`renderer: "classic"` the Rig's lights and environment light the letters, and they cast and receive the Rig's
|
|
202
|
+
shadows. In a 3D Scene (any other Rig, on WebGPU) the letters stand in the Scene's world itself, as a model layer
|
|
203
|
+
does: they cast and take shadows between each other, the models, the scene objects and the floor, show in
|
|
204
|
+
reflections, and are path traced in Final; 2D layers and the Camera layer's depth of field meet them by their real
|
|
205
|
+
depth ([video-world3d.md](video-world3d.md#3d-text-in-the-world)).
|
|
201
206
|
- **Fonts.** Each letter is traced from the font the layer really draws with, so Google, uploaded and system fonts
|
|
202
207
|
and any weight work. The face is the 2D glyph's exact outline; the bevel swells the sides outward.
|
|
203
208
|
- **Not in 3D:** the caption bar, outline stroke, text shadow and glow, blur and decorations are 2D paint and are not
|
|
204
209
|
drawn on 3D letters. A Text Animator's opacity and colour apply; its blur, glow, shadow and stroke do not.
|
|
205
210
|
- **Cost:** a glyph's geometry is built once per font, character, depth and bevel and shared; each frame poses the
|
|
206
|
-
letters and renders one 3D pass
|
|
211
|
+
letters and renders one 3D pass (in a 3D Scene, no pass of their own: the world draws them, and moving or
|
|
212
|
+
recolouring a letter rebuilds nothing). `depth`, `bevel` and `bevelSegments` are not keyframable (they rebuild
|
|
213
|
+
geometry).
|
|
214
|
+
|
|
215
|
+
### Flat text in the 3D Scene (`textInWorld`)
|
|
216
|
+
|
|
217
|
+
A text layer can stand in a 3D Scene's world as flat letters instead of lying on top of the frame: models in front hide them, Position
|
|
218
|
+
`z` is real depth, Rotate 3D a real turn, and the Scene's camera and depth of field film them ([video-world3d.md](video-world3d.md#flat-text-in-the-world)).
|
|
219
|
+
Everything else stays the text layer's own, and with no world Scene on the frame the field does nothing.
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
"textInWorld": { "enabled": true } // exact 2D colours, no shadows (the default)
|
|
223
|
+
"textInWorld": { "enabled": true, "lit": true, "castShadow": true } // lit by the Scene, casting and taking shadows
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
| Field | Default | Notes |
|
|
227
|
+
| --- | --- | --- |
|
|
228
|
+
| `enabled` | `false` | The letters stand in the Scene. Stored only when set; omit the whole block for ordinary text. |
|
|
229
|
+
| `lit` | `false` | Each letter takes the Scene's light and look (a matte surface) instead of keeping its exact colours. |
|
|
230
|
+
| `castShadow` | `false` | The letters' shadow falls on the world, lit or not. |
|
|
231
|
+
| `receiveShadow` | `true` with `lit` | `false` keeps the world's shadows off lit letters. Unlit letters take none. |
|
|
232
|
+
|
|
233
|
+
- Under the Scene's own camera (`scene.camera`) the layer's plane (`panZ` 0) stands on the plane the camera looks at (its `target`), whatever the
|
|
234
|
+
composition's size; `panZ` moves the letters in depth by the Scene's units ([video-world3d.md](video-world3d.md#flat-text-in-the-world)).
|
|
235
|
+
- A text layer's `shadowPlate` (Cast shadow, Receive shadow, Depth occlusion: the classic Rig's flat plate) does nothing over a world Scene; these
|
|
236
|
+
`textInWorld` fields are its way into the Scene's light and shadows.
|
|
237
|
+
|
|
238
|
+
- One flat card per unit of the Text Animators (`basedOn`: a letter, a word or a line); letters when there are none.
|
|
239
|
+
- Not drawn in the Scene: the caption bar and its border, and the animators' glow, box and caret. The layer's In and Out transitions do
|
|
240
|
+
not play there; bring the letters in and out with Text Animators.
|
|
241
|
+
- A layer with effects, colour filters, blur or Grow Fill, a clip mask (`textClipMask`), one in a sequence or a camera-locked channel
|
|
242
|
+
stays flat. `text3d.enabled` wins.
|
|
207
243
|
|
|
208
244
|
### Dynamic text placeholders
|
|
209
245
|
|
|
@@ -363,7 +399,7 @@ Rules the sanitizer enforces (anything else is dropped or clamped on load): `aid
|
|
|
363
399
|
**Depth and one camera.**
|
|
364
400
|
- `layer` puts one camera in front of the text plate's centre; it rides the layer, like CSS perspective inside a 3D-transformed element.
|
|
365
401
|
- `project` films the letters with the project's Camera layer. A dolly, pan, tilt or the layer's own `rotateX`/`rotateY` gives true parallax between letters at different `z`; with no camera move it equals `layer`.
|
|
366
|
-
- 3D Text (`text3d`) letters move in real depth with `z`; the camera field doesn't apply there.
|
|
402
|
+
- 3D Text (`text3d`) letters, and flat letters in a 3D Scene (`textInWorld`), move in real depth with `z`; the camera field doesn't apply there.
|
|
367
403
|
- Track: `txa:<aid>:<pid>.z`.
|
|
368
404
|
|
|
369
405
|
```json
|