mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 18:18:17 -06:00
Merge branch 'main' into worktree-agent-a15cecfec57d5290d
# Conflicts: # crates/effects/src/ocio.rs # crates/engine/src/commands/stubs.rs # docs/parity.md
This commit is contained in:
+11
-2
@@ -172,7 +172,8 @@ chain with one upload and one readback. Tests render scenes on both paths and co
|
||||
(≤ 1/255 at 8 bpc, ≤ 1e-3 at 32 bpc); they skip without an adapter. The desktop viewer builds the
|
||||
`Gpu` on egui-wgpu's device and shows frames from GPU textures without reading them back
|
||||
(`ui-egui::frames`); headless renders, the CLI (unless `--gpu`) and CI use the CPU. On the web
|
||||
(WebGPU) the GPU composites viewer frames; steps that need a readback fall back to the CPU.
|
||||
(WebGPU) the GPU composites viewer frames; steps that need a readback fall back to the CPU (the
|
||||
Info panel's pixel readout reads GPU frames back asynchronously).
|
||||
|
||||
**Colour and bit depth** (`crates/render/src/color.rs`, `crates/color/src/space.rs`). Pixels are
|
||||
`f32`, but 8 and 16 bpc projects clamp and quantise each layer after its source and masks and
|
||||
@@ -315,6 +316,14 @@ inspect and click the interface. See [agents.md](agents.md) and
|
||||
|
||||
Settings (`engine::prefs`), keyboard shortcut presets (`engine::shortcuts`) and auto-save /
|
||||
crash recovery (`engine::autosave`) live in the engine too; they persist through a
|
||||
`ConfigStore` the frontend provides (a directory on the desktop, `localStorage` on the web).
|
||||
`ConfigStore` the frontend provides (a directory on the desktop; the Origin Private File System,
|
||||
or IndexedDB, on the web). Auto-saves go through the store's `FileOps` (the file system by
|
||||
default, the browser storage on the web).
|
||||
|
||||
Renders and analyses run on background threads on the desktop. Where there are no threads (the
|
||||
browser), `engine::offload` sends them to a second engine instance instead: the session's
|
||||
`Offload` ships the serialized project, the footage it reads and the job (`WorkerRequest`) to a
|
||||
Web Worker, and the worker's replies (progress, item status, the analysed property group) are
|
||||
applied on the UI thread.
|
||||
The shortcut dispatcher and the menus read the active preset. See
|
||||
[preferences.md](preferences.md).
|
||||
|
||||
+421
@@ -0,0 +1,421 @@
|
||||
# Effects
|
||||
|
||||
<!-- Generated from the effect registry (crates/effects/src/catalog.rs); do not edit by hand.
|
||||
Regenerate: UPDATE_DOCS=1 cargo test -p effectcraft-effects --lib effects_doc_is_current -->
|
||||
|
||||
EffectCraft ships 303 effects with 2434 parameters in total, grouped into the same categories as the Effects & Presets panel. Every effect is our own implementation, written from public behaviour descriptions and standard image-processing literature. Parameter names, order, popup options, units, defaults and ranges follow the reference application so that projects, expressions and muscle memory carry over.
|
||||
|
||||
- **GPU**: 24 effects also run on the GPU compositor with identical results.
|
||||
- **32**: 303 effects process 32-bit float (HDR, overbright) pixels without clamping.
|
||||
- **Status**: 261 implemented in full, 42 partial (what is missing is listed).
|
||||
|
||||
Effects are addressed by id (`ec.<category>.<name>`) or display name in commands, scripts and the control channel, and every parameter by its id (`effects/#1/blurriness`).
|
||||
|
||||
## 3D Channel
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| 3D Channel Extract | `ec.3d.channelextract` | 5 | | 32 | Partial: no anti-alias option |
|
||||
| Cryptomatte | `ec.3d.cryptomatte` | 4 | | 32 | Implemented |
|
||||
| Depth Matte | `ec.3d.depthmatte` | 3 | | 32 | Implemented |
|
||||
| Depth of Field | `ec.3d.depthoffield` | 4 | | 32 | Implemented |
|
||||
| EXtractoR | `ec.3d.extractor` | 8 | | 32 | Implemented |
|
||||
| Fog 3D | `ec.3d.fog3d` | 8 | | 32 | Implemented |
|
||||
| ID Matte | `ec.3d.idmatte` | 5 | | 32 | Implemented |
|
||||
| IDentifier | `ec.3d.identifier` | 3 | | 32 | Implemented |
|
||||
|
||||
## Audio
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Backwards | `ec.audio.backwards` | 1 | | 32 | Implemented |
|
||||
| Bass & Treble | `ec.audio.basstreble` | 2 | | 32 | Implemented |
|
||||
| Compressor | `ec.audio.compressor` | 8 | | 32 | Implemented |
|
||||
| Delay | `ec.audio.delay` | 5 | | 32 | Implemented |
|
||||
| Distortion | `ec.audio.distortion` | 7 | | 32 | Implemented |
|
||||
| Flange & Chorus | `ec.audio.flangechorus` | 9 | | 32 | Implemented |
|
||||
| Gate | `ec.audio.gate` | 4 | | 32 | Implemented |
|
||||
| High-Low Pass | `ec.audio.highlowpass` | 4 | | 32 | Implemented |
|
||||
| Modulator | `ec.audio.modulator` | 4 | | 32 | Implemented |
|
||||
| Parametric EQ | `ec.audio.parametriceq` | 12 | | 32 | Implemented |
|
||||
| Reverb | `ec.audio.reverb` | 6 | | 32 | Implemented |
|
||||
| Stereo Mixer | `ec.audio.stereomixer` | 5 | | 32 | Implemented |
|
||||
| Tone | `ec.audio.tone` | 7 | | 32 | Implemented |
|
||||
|
||||
## Blur & Sharpen
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Bilateral Blur | `ec.blur.bilateral` | 3 | | 32 | Implemented |
|
||||
| CC Cross Blur | `ec.blur.cccross` | 3 | | 32 | Implemented |
|
||||
| CC Radial Blur | `ec.blur.ccradial` | 4 | | 32 | Implemented |
|
||||
| CC Radial Fast Blur | `ec.blur.ccradialfast` | 3 | | 32 | Implemented |
|
||||
| CC Vector Blur | `ec.blur.ccvector` | 4 | | 32 | Implemented |
|
||||
| Camera Lens Blur | `ec.blur.cameralens` | 10 | | 32 | Partial: no Diffraction Fringe or Blur Map layer |
|
||||
| Camera-Shake Deblur | `ec.blur.camerashakedeblur` | 8 | | 32 | Implemented |
|
||||
| Channel Blur | `ec.blur.channel` | 6 | | 32 | Implemented |
|
||||
| Compound Blur | `ec.blur.compound` | 4 | | 32 | Implemented |
|
||||
| Directional Blur | `ec.blur.directional` | 2 | GPU | 32 | Implemented |
|
||||
| Fast Box Blur | `ec.blur.fastbox` | 4 | GPU | 32 | Implemented |
|
||||
| Gaussian Blur | `ec.blur.gaussian` | 3 | GPU | 32 | Implemented |
|
||||
| Radial Blur | `ec.blur.radial` | 4 | | 32 | Implemented |
|
||||
| Sharpen | `ec.blur.sharpen` | 1 | | 32 | Implemented |
|
||||
| Smart Blur | `ec.blur.smart` | 3 | | 32 | Implemented |
|
||||
| Unsharp Mask | `ec.blur.unsharp` | 3 | | 32 | Implemented |
|
||||
|
||||
## Channel
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Arithmetic | `ec.channel.arithmetic` | 5 | | 32 | Implemented |
|
||||
| Blend | `ec.channel.blend` | 4 | | 32 | Implemented |
|
||||
| CC Composite | `ec.channel.cccomposite` | 3 | | 32 | Implemented |
|
||||
| Calculations | `ec.channel.calculations` | 9 | | 32 | Implemented |
|
||||
| Channel Combiner | `ec.channel.combiner` | 6 | | 32 | Partial: no Saturation Multiplied target |
|
||||
| Compound Arithmetic | `ec.channel.compoundarithmetic` | 6 | | 32 | Implemented |
|
||||
| Invert | `ec.channel.invert` | 2 | GPU | 32 | Implemented |
|
||||
| Minimax | `ec.channel.minimax` | 4 | | 32 | Partial: no Don't Shrink Edges option |
|
||||
| Remove Color Matting | `ec.channel.removecolormatting` | 2 | | 32 | Implemented |
|
||||
| Set Channels | `ec.channel.setchannels` | 9 | | 32 | Implemented |
|
||||
| Set Matte | `ec.channel.setmatte` | 6 | | 32 | Implemented |
|
||||
| Shift Channels | `ec.channel.shiftchannels` | 4 | | 32 | Implemented |
|
||||
| Solid Composite | `ec.channel.solidcomposite` | 4 | | 32 | Implemented |
|
||||
|
||||
## Color Correction
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Auto Color | `ec.color.autocolor` | 6 | | 32 | Implemented |
|
||||
| Auto Contrast | `ec.color.autocontrast` | 5 | | 32 | Implemented |
|
||||
| Auto Levels | `ec.color.autolevels` | 5 | | 32 | Implemented |
|
||||
| Black & White | `ec.color.blackwhite` | 8 | | 32 | Implemented |
|
||||
| Brightness & Contrast | `ec.color.brightnesscontrast` | 3 | GPU | 32 | Implemented |
|
||||
| Broadcast Colors | `ec.color.broadcast` | 3 | | 32 | Implemented |
|
||||
| CC Color Neutralizer | `ec.color.cccolorneutralizer` | 11 | | 32 | Implemented |
|
||||
| CC Color Offset | `ec.color.cccoloroffset` | 4 | | 32 | Implemented |
|
||||
| CC Kernel | `ec.color.cckernel` | 12 | | 32 | Implemented |
|
||||
| CC Toner | `ec.color.cctoner` | 7 | | 32 | Implemented |
|
||||
| Change Color | `ec.color.changecolor` | 9 | | 32 | Implemented |
|
||||
| Change to Color | `ec.color.changetocolor` | 9 | | 32 | Implemented |
|
||||
| Channel Mixer | `ec.color.channelmixer` | 13 | | 32 | Implemented |
|
||||
| Color Balance | `ec.color.colorbalance` | 10 | | 32 | Implemented |
|
||||
| Color Balance (HLS) | `ec.color.colorbalancehls` | 3 | | 32 | Implemented |
|
||||
| Color Link | `ec.color.colorlink` | 6 | | 32 | Implemented |
|
||||
| Color Stabilizer | `ec.color.colorstabilizer` | 6 | | 32 | Implemented |
|
||||
| Colorama | `ec.color.colorama` | 5 | | 32 | Partial: no Add Phase, editable Output Cycle, Modify, Pixel Selection or Masking |
|
||||
| Curves | `ec.color.curves` | 0 | GPU | 32 | Partial: no Channel popup |
|
||||
| Equalize | `ec.color.equalize` | 2 | | 32 | Implemented |
|
||||
| Exposure | `ec.color.exposure` | 14 | GPU | 32 | Implemented |
|
||||
| Gamma/Pedestal/Gain | `ec.color.gammapedestalgain` | 10 | | 32 | Implemented |
|
||||
| Hue/Saturation | `ec.color.huesaturation` | 7 | GPU | 32 | Partial: no per-range Channel Control |
|
||||
| Leave Color | `ec.color.leavecolor` | 5 | | 32 | Implemented |
|
||||
| Levels | `ec.color.levels` | 7 | GPU | 32 | Partial: master channel only (no Channel popup) |
|
||||
| Levels (Individual Controls) | `ec.color.levelsic` | 27 | | 32 | Implemented |
|
||||
| Lumetri Color | `ec.color.lumetri` | 38 | | 32 | Partial: no HSL Secondary, hue/saturation curves, HDR mode or look files |
|
||||
| OCIO CDL Transform | `ec.color.ociocdl` | 12 | | 32 | Implemented |
|
||||
| OCIO Color Space Transform | `ec.color.ociocolorspace` | 4 | | 32 | Implemented |
|
||||
| OCIO Display Transform | `ec.color.ociodisplay` | 5 | | 32 | Implemented |
|
||||
| OCIO File Transform | `ec.color.ociofile` | 4 | | 32 | Implemented |
|
||||
| OCIO Look Transform | `ec.color.ociolook` | 6 | | 32 | Implemented |
|
||||
| PS Arbitrary Map | `ec.color.psarbitrarymap` | 2 | | 32 | Implemented |
|
||||
| Photo Filter | `ec.color.photofilter` | 4 | | 32 | Implemented |
|
||||
| Selective Color | `ec.color.selectivecolor` | 37 | | 32 | Partial: simplified Colors / Details layout |
|
||||
| Shadow/Highlight | `ec.color.shadowhighlight` | 14 | | 32 | Implemented |
|
||||
| Tint | `ec.color.tint` | 3 | GPU | 32 | Implemented |
|
||||
| Tritone | `ec.color.tritone` | 4 | | 32 | Implemented |
|
||||
| Vibrance | `ec.color.vibrance` | 2 | | 32 | Implemented |
|
||||
| Video Limiter | `ec.color.videolimiter` | 5 | | 32 | Implemented |
|
||||
|
||||
## Distort
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Bezier Warp | `ec.distort.bezierwarp` | 13 | | 32 | Implemented |
|
||||
| Bulge | `ec.distort.bulge` | 6 | | 32 | Implemented |
|
||||
| CC Bend It | `ec.distort.ccbendit` | 4 | | 32 | Implemented |
|
||||
| CC Bender | `ec.distort.ccbender` | 5 | | 32 | Implemented |
|
||||
| CC Blobbylize | `ec.distort.ccblobbylize` | 15 | | 32 | Implemented |
|
||||
| CC Flo Motion | `ec.distort.ccflomotion` | 7 | | 32 | Implemented |
|
||||
| CC Griddler | `ec.distort.ccgriddler` | 5 | | 32 | Implemented |
|
||||
| CC Lens | `ec.distort.cclens` | 3 | | 32 | Implemented |
|
||||
| CC Page Turn | `ec.distort.ccpageturn` | 7 | | 32 | Implemented |
|
||||
| CC Power Pin | `ec.distort.ccpowerpin` | 10 | | 32 | Implemented |
|
||||
| CC Ripple Pulse | `ec.distort.ccripplepulse` | 5 | | 32 | Implemented |
|
||||
| CC Slant | `ec.distort.ccslant` | 4 | | 32 | Implemented |
|
||||
| CC Smear | `ec.distort.ccsmear` | 4 | | 32 | Implemented |
|
||||
| CC Split | `ec.distort.ccsplit` | 3 | | 32 | Implemented |
|
||||
| CC Split 2 | `ec.distort.ccsplit2` | 4 | | 32 | Implemented |
|
||||
| CC Tiler | `ec.distort.cctiler` | 3 | | 32 | Implemented |
|
||||
| Corner Pin | `ec.distort.cornerpin` | 4 | | 32 | Implemented |
|
||||
| Detail-preserving Upscale | `ec.distort.upscale` | 4 | | 32 | Implemented |
|
||||
| Displacement Map | `ec.distort.displacementmap` | 8 | | 32 | Implemented |
|
||||
| Liquify | `ec.distort.liquify` | 12 | | 32 | Implemented |
|
||||
| Magnify | `ec.distort.magnify` | 10 | | 32 | Implemented |
|
||||
| Mesh Warp | `ec.distort.meshwarp` | 3 | | 32 | Implemented |
|
||||
| Mirror | `ec.distort.mirror` | 2 | | 32 | Implemented |
|
||||
| Offset | `ec.distort.offset` | 2 | | 32 | Implemented |
|
||||
| Optics Compensation | `ec.distort.opticscompensation` | 5 | | 32 | Partial: no Optimal Pixels |
|
||||
| Polar Coordinates | `ec.distort.polar` | 2 | | 32 | Implemented |
|
||||
| Puppet | `ec.distort.puppet` | 1 | | 32 | Implemented |
|
||||
| Reshape | `ec.distort.reshape` | 6 | | 32 | Partial: no correspondence points |
|
||||
| Ripple | `ec.distort.ripple` | 7 | | 32 | Implemented |
|
||||
| Rolling Shutter Repair | `ec.distort.rollingshutterrepair` | 5 | | 32 | Partial: Pixel Motion Detail has no effect |
|
||||
| Smear | `ec.distort.smear` | 8 | | 32 | Implemented |
|
||||
| Spherize | `ec.distort.spherize` | 2 | | 32 | Implemented |
|
||||
| Transform | `ec.distort.transform` | 10 | GPU | 32 | Partial: no shutter-angle motion blur |
|
||||
| Turbulent Displace | `ec.distort.turbulentdisplace` | 11 | | 32 | Partial: no locked pinning variants |
|
||||
| Twirl | `ec.distort.twirl` | 3 | | 32 | Implemented |
|
||||
| Twirl (Legacy) | `ec.distort.twirllegacy` | 3 | | 32 | Implemented |
|
||||
| Warp | `ec.distort.warp` | 5 | | 32 | Implemented |
|
||||
| Warp Stabilizer | `ec.distort.warpstabilizer` | 20 | | 32 | Implemented |
|
||||
| Wave Warp | `ec.distort.wavewarp` | 7 | | 32 | Implemented |
|
||||
|
||||
## Expression Controls
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| 3D Point Control | `ec.control.point3d` | 1 | GPU | 32 | Implemented |
|
||||
| Angle Control | `ec.control.angle` | 1 | GPU | 32 | Implemented |
|
||||
| Checkbox Control | `ec.control.checkbox` | 1 | GPU | 32 | Implemented |
|
||||
| Color Control | `ec.control.color` | 1 | GPU | 32 | Implemented |
|
||||
| Dropdown Menu Control | `ec.control.dropdown` | 1 | GPU | 32 | Implemented |
|
||||
| Layer Control | `ec.control.layer` | 1 | GPU | 32 | Implemented |
|
||||
| Point Control | `ec.control.point` | 1 | GPU | 32 | Implemented |
|
||||
| Slider Control | `ec.control.slider` | 1 | GPU | 32 | Implemented |
|
||||
|
||||
## Generate
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| 4-Color Gradient | `ec.generate.fourcolor` | 12 | | 32 | Implemented |
|
||||
| Advanced Lightning | `ec.generate.advancedlightning` | 16 | | 32 | Partial: no Alpha Obstacle; most Expert Settings missing |
|
||||
| Audio Spectrum | `ec.generate.audiospectrum` | 23 | | 32 | Implemented |
|
||||
| Audio Waveform | `ec.generate.audiowaveform` | 17 | | 32 | Implemented |
|
||||
| Beam | `ec.generate.beam` | 11 | | 32 | Implemented |
|
||||
| CC Glue Gun | `ec.generate.ccgluegun` | 7 | | 32 | Implemented |
|
||||
| CC Light Burst 2.5 | `ec.generate.cclightburst` | 6 | | 32 | Implemented |
|
||||
| CC Light Rays | `ec.generate.cclightrays` | 8 | | 32 | Implemented |
|
||||
| CC Light Sweep | `ec.generate.cclightsweep` | 9 | | 32 | Implemented |
|
||||
| CC Threads | `ec.generate.ccthreads` | 8 | | 32 | Implemented |
|
||||
| Cell Pattern | `ec.generate.cellpattern` | 14 | | 32 | Partial: HQ variants render like the standard ones |
|
||||
| Checkerboard | `ec.generate.checkerboard` | 10 | | 32 | Implemented |
|
||||
| Circle | `ec.generate.circle` | 11 | | 32 | Implemented |
|
||||
| Ellipse | `ec.generate.ellipse` | 8 | | 32 | Implemented |
|
||||
| Eyedropper Fill | `ec.generate.eyedropperfill` | 5 | | 32 | Implemented |
|
||||
| Fill | `ec.generate.fill` | 3 | GPU | 32 | Partial: no Fill Mask / All Masks / feather |
|
||||
| Fractal | `ec.generate.fractal` | 21 | | 32 | Implemented |
|
||||
| Gradient Ramp | `ec.generate.gradientramp` | 7 | GPU | 32 | Implemented |
|
||||
| Grid | `ec.generate.grid` | 12 | | 32 | Implemented |
|
||||
| Lens Flare | `ec.generate.lensflare` | 4 | | 32 | Implemented |
|
||||
| Paint Bucket | `ec.generate.paintbucket` | 11 | | 32 | Implemented |
|
||||
| Radio Waves | `ec.generate.radiowaves` | 17 | | 32 | Partial: no Image Contours or Mask wave types, Parameters Are Set At, reflection or stroke profile |
|
||||
| Scribble | `ec.generate.scribble` | 21 | | 32 | Partial: no caps, joins or Start/End Apply To |
|
||||
| Stroke | `ec.generate.stroke` | 11 | | 32 | Implemented |
|
||||
| Vegas | `ec.generate.vegas` | 26 | | 32 | Implemented |
|
||||
| Write-on | `ec.generate.writeon` | 10 | | 32 | Implemented |
|
||||
|
||||
## Immersive Video
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| VR Blur | `ec.vr.blur` | 2 | | 32 | Implemented |
|
||||
| VR Chromatic Aberrations | `ec.vr.chromaticaberrations` | 8 | | 32 | Implemented |
|
||||
| VR Color Gradients | `ec.vr.colorgradients` | 19 | | 32 | Implemented |
|
||||
| VR Converter | `ec.vr.converter` | 8 | | 32 | Partial: common layouts only |
|
||||
| VR De-Noise | `ec.vr.denoise` | 4 | | 32 | Implemented |
|
||||
| VR Digital Glitch | `ec.vr.digitalglitch` | 8 | | 32 | Partial: reduced control set |
|
||||
| VR Fractal Noise | `ec.vr.fractalnoise` | 16 | | 32 | Implemented |
|
||||
| VR Glow | `ec.vr.glow` | 7 | | 32 | Implemented |
|
||||
| VR Plane to Sphere | `ec.vr.planetosphere` | 6 | | 32 | Implemented |
|
||||
| VR Rotate Sphere | `ec.vr.rotatesphere` | 5 | | 32 | Implemented |
|
||||
| VR Sharpen | `ec.vr.sharpen` | 2 | | 32 | Implemented |
|
||||
| VR Sphere to Plane | `ec.vr.spheretoplane` | 5 | | 32 | Implemented |
|
||||
|
||||
## Keying
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Advanced Spill Suppressor | `ec.key.advancedspill` | 5 | | 32 | Partial: no Tolerance, Desaturate or Spill Color Correction |
|
||||
| CC Simple Wire Removal | `ec.key.ccsimplewireremoval` | 7 | | 32 | Implemented |
|
||||
| Color Difference Key | `ec.key.colordifference` | 16 | | 32 | Implemented |
|
||||
| Color Range | `ec.key.colorrange` | 8 | | 32 | Implemented |
|
||||
| Difference Matte | `ec.key.differencematte` | 6 | | 32 | Implemented |
|
||||
| Extract | `ec.key.extract` | 6 | | 32 | Implemented |
|
||||
| Inner/Outer Key | `ec.key.innerouter` | 10 | | 32 | Partial: one additional mask per side; no cleanup strokes |
|
||||
| Key Cleaner | `ec.key.keycleaner` | 4 | | 32 | Implemented |
|
||||
| Key Light | `ec.keying.keylight` | 42 | | 32 | Partial: no Source Crops X/Y Method or Edge Colour; no colour suppression / balancing |
|
||||
| Linear Color Key | `ec.key.linearcolor` | 6 | | 32 | Implemented |
|
||||
| Screen Key | `ec.key.screen` | 11 | | 32 | Implemented |
|
||||
| Unmult | `ec.key.unmult` | 6 | | 32 | Implemented |
|
||||
|
||||
## Matte
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Matte Choker | `ec.matte.mattechoker` | 7 | | 32 | Implemented |
|
||||
| Mocha shape | `ec.obsolete.mochashape` | 6 | | 32 | Implemented |
|
||||
| Refine Hard Matte | `ec.matte.refinehard` | 11 | | 32 | Partial: no Reduce Chatter or motion blur |
|
||||
| Refine Soft Matte | `ec.matte.refinesoft` | 13 | | 32 | Partial: no Reduce Chatter or motion blur |
|
||||
| Roto Brush & Refine Edge | `ec.matte.rotobrush` | 24 | | 32 | Implemented |
|
||||
| Simple Choker | `ec.matte.simplechoker` | 2 | | 32 | Implemented |
|
||||
|
||||
## Noise & Grain
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Add Grain | `ec.noise.addgrain` | 22 | | 32 | Partial: no preview region, presets, channel balance or temporal controls |
|
||||
| Curl Noise | `ec.noise.curlnoise` | 10 | | 32 | Implemented |
|
||||
| Dust & Scratches | `ec.noise.dustscratches` | 3 | | 32 | Implemented |
|
||||
| Fractal Noise | `ec.noise.fractal` | 26 | GPU | 32 | Implemented |
|
||||
| Match Grain | `ec.noise.matchgrain` | 25 | | 32 | Partial: no preview region, presets, sampling or temporal controls |
|
||||
| Median | `ec.noise.median` | 2 | | 32 | Implemented |
|
||||
| Median (Legacy) | `ec.noise.medianlegacy` | 2 | | 32 | Implemented |
|
||||
| Noise | `ec.noise.noise` | 3 | | 32 | Implemented |
|
||||
| Noise Alpha | `ec.noise.noisealpha` | 8 | | 32 | Implemented |
|
||||
| Noise HLS | `ec.noise.noisehls` | 6 | | 32 | Implemented |
|
||||
| Noise HLS Auto | `ec.noise.noisehlsauto` | 6 | | 32 | Implemented |
|
||||
| Remove Grain | `ec.noise.removegrain` | 7 | | 32 | Partial: no preview region, sampling or temporal filtering |
|
||||
| Turbulent Noise | `ec.noise.turbulent` | 22 | | 32 | Implemented |
|
||||
|
||||
## Obsolete
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Basic 3D | `ec.obsolete.basic3d` | 5 | | 32 | Implemented |
|
||||
| Basic Text | `ec.obsolete.basictext` | 11 | | 32 | Implemented |
|
||||
| Color Key | `ec.key.colorkey` | 4 | | 32 | Implemented |
|
||||
| Gaussian Blur (Legacy) | `ec.obsolete.gaussianlegacy` | 2 | | 32 | Implemented |
|
||||
| Lightning | `ec.obsolete.lightning` | 25 | | 32 | Implemented |
|
||||
| Luma Key | `ec.key.luma` | 5 | | 32 | Implemented |
|
||||
| Path Text | `ec.obsolete.pathtext` | 21 | | 32 | Partial: no kerning, shear/scale, line spacing, fade time or jitter |
|
||||
| Reduce Interlace Flicker | `ec.blur.reduceflicker` | 1 | | 32 | Implemented |
|
||||
| Spill Suppressor | `ec.key.spill` | 3 | | 32 | Implemented |
|
||||
|
||||
## Paint
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Paint | `ec.paint.paint` | 1 | | 32 | Implemented |
|
||||
|
||||
## Perspective
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| 3D Camera Tracker | `ec.perspective.cameratracker` | 10 | | 32 | Implemented |
|
||||
| 3D Glasses | `ec.perspective.3dglasses` | 8 | | 32 | Implemented |
|
||||
| Bevel Alpha | `ec.perspective.bevelalpha` | 4 | | 32 | Implemented |
|
||||
| Bevel Edges | `ec.perspective.beveledges` | 4 | | 32 | Implemented |
|
||||
| CC Cylinder | `ec.perspective.cccylinder` | 12 | | 32 | Implemented |
|
||||
| CC Environment | `ec.perspective.ccenvironment` | 4 | | 32 | Implemented |
|
||||
| CC Sphere | `ec.perspective.ccsphere` | 14 | | 32 | Implemented |
|
||||
| CC Spotlight | `ec.perspective.ccspotlight` | 8 | | 32 | Implemented |
|
||||
| Drop Shadow | `ec.perspective.dropshadow` | 6 | GPU | 32 | Implemented |
|
||||
| Radial Shadow | `ec.perspective.radialshadow` | 9 | | 32 | Implemented |
|
||||
|
||||
## Simulation
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| CC Ball Action | `ec.sim.ccballaction` | 8 | | 32 | Implemented |
|
||||
| CC Bubbles | `ec.sim.ccbubbles` | 7 | | 32 | Implemented |
|
||||
| CC Drizzle | `ec.sim.ccdrizzle` | 14 | | 32 | Implemented |
|
||||
| CC Hair | `ec.sim.cchair` | 20 | | 32 | Implemented |
|
||||
| CC Mr. Mercury | `ec.sim.ccmrmercury` | 23 | | 32 | Implemented |
|
||||
| CC Particle Systems II | `ec.sim.ccparticlesystems2` | 21 | | 32 | Implemented |
|
||||
| CC Particle World | `ec.sim.ccparticleworld` | 30 | | 32 | Implemented |
|
||||
| CC Pixel Polly | `ec.sim.ccpixelpolly` | 10 | | 32 | Implemented |
|
||||
| CC Rainfall | `ec.sim.ccrainfall` | 14 | | 32 | Implemented |
|
||||
| CC Scatterize | `ec.sim.ccscatterize` | 4 | | 32 | Implemented |
|
||||
| CC Snowfall | `ec.sim.ccsnowfall` | 19 | | 32 | Implemented |
|
||||
| CC Star Burst | `ec.sim.ccstarburst` | 6 | | 32 | Implemented |
|
||||
| Card Dance | `ec.sim.carddance` | 35 | | 32 | Partial: no camera system, corner pins or lighting/material controls |
|
||||
| Caustics | `ec.sim.caustics` | 21 | | 32 | Partial: no Sky group or light type |
|
||||
| Foam | `ec.sim.foam` | 24 | | 32 | Partial: no wobble, pop velocity, custom bubble texture, environment map or flow map |
|
||||
| Particle Playground | `ec.sim.particleplayground` | 37 | | 32 | Partial: no Particle Exploder, Ephemeral Property Mapper, Affects groups or text particles |
|
||||
| Shatter | `ec.sim.shatter` | 26 | | 32 | Partial: no custom shatter map, gradient, textures or extrusion rendering |
|
||||
| Wave World | `ec.sim.waveworld` | 27 | | 32 | Partial: no wireframe controls, dry-area rendering or ground group |
|
||||
|
||||
## Stylize
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Brush Strokes | `ec.stylize.brushstrokes` | 7 | | 32 | Implemented |
|
||||
| CC Block Load | `ec.stylize.ccblockload` | 5 | | 32 | Implemented |
|
||||
| CC Burn Film | `ec.stylize.ccburnfilm` | 3 | | 32 | Implemented |
|
||||
| CC Glass | `ec.stylize.ccglass` | 17 | | 32 | Implemented |
|
||||
| CC HexTile | `ec.stylize.cchextile` | 5 | | 32 | Implemented |
|
||||
| CC Kaleida | `ec.stylize.cckaleida` | 4 | | 32 | Implemented |
|
||||
| CC Mr. Smoothie | `ec.stylize.ccmrsmoothie` | 7 | | 32 | Implemented |
|
||||
| CC Plastic | `ec.stylize.ccplastic` | 18 | | 32 | Implemented |
|
||||
| CC RepeTile | `ec.stylize.ccrepetile` | 5 | | 32 | Implemented |
|
||||
| CC Threshold | `ec.stylize.ccthreshold` | 4 | | 32 | Implemented |
|
||||
| CC Threshold RGB | `ec.stylize.ccthresholdrgb` | 7 | | 32 | Implemented |
|
||||
| CC Vignette | `ec.stylize.ccvignette` | 4 | | 32 | Implemented |
|
||||
| Cartoon | `ec.stylize.cartoon` | 11 | | 32 | Partial: no Edge Enhancement |
|
||||
| Color Emboss | `ec.stylize.coloremboss` | 4 | | 32 | Implemented |
|
||||
| Emboss | `ec.stylize.emboss` | 4 | | 32 | Implemented |
|
||||
| Find Edges | `ec.stylize.findedges` | 2 | | 32 | Implemented |
|
||||
| Glow | `ec.stylize.glow` | 13 | GPU | 32 | Partial: no Glow Operation or arbitrary colour map |
|
||||
| Mosaic | `ec.stylize.mosaic` | 3 | | 32 | Implemented |
|
||||
| Motion Tile | `ec.stylize.motiontile` | 8 | | 32 | Implemented |
|
||||
| Posterize | `ec.stylize.posterize` | 1 | | 32 | Implemented |
|
||||
| Roughen Edges | `ec.stylize.roughenedges` | 13 | | 32 | Implemented |
|
||||
| Scatter | `ec.stylize.scatter` | 3 | | 32 | Implemented |
|
||||
| Strobe Light | `ec.stylize.strobe` | 7 | | 32 | Implemented |
|
||||
| Texturize | `ec.stylize.texturize` | 4 | | 32 | Implemented |
|
||||
| Threshold | `ec.stylize.threshold` | 1 | | 32 | Implemented |
|
||||
|
||||
## Text
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Numbers | `ec.text.numbers` | 14 | | 32 | Implemented |
|
||||
| Timecode | `ec.text.timecode` | 12 | | 32 | Implemented |
|
||||
|
||||
## Time
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| CC Force Motion Blur | `ec.time.ccforcemotionblur` | 4 | | 32 | Implemented |
|
||||
| CC Wide Time | `ec.time.ccwidetime` | 3 | | 32 | Implemented |
|
||||
| Echo | `ec.time.echo` | 5 | | 32 | Implemented |
|
||||
| Pixel Motion Blur | `ec.time.pixelmotionblur` | 4 | | 32 | Implemented |
|
||||
| Posterize Time | `ec.time.posterizetime` | 1 | | 32 | Implemented |
|
||||
| Time Difference | `ec.time.timedifference` | 5 | | 32 | Implemented |
|
||||
| Time Displacement | `ec.time.timedisplacement` | 4 | | 32 | Implemented |
|
||||
| Timewarp | `ec.time.timewarp` | 10 | | 32 | Partial: Pixel Motion blends frames (no optical flow); no matte, warp or crop controls |
|
||||
|
||||
## Transition
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Block Dissolve | `ec.transition.blockdissolve` | 4 | | 32 | Partial: no Soft Edges option |
|
||||
| CC Glass Wipe | `ec.transition.ccglasswipe` | 5 | | 32 | Implemented |
|
||||
| CC Grid Wipe | `ec.transition.ccgridwipe` | 7 | | 32 | Implemented |
|
||||
| CC Image Wipe | `ec.transition.ccimagewipe` | 7 | | 32 | Implemented |
|
||||
| CC Jaws | `ec.transition.ccjaws` | 6 | | 32 | Implemented |
|
||||
| CC Light Wipe | `ec.transition.cclightwipe` | 8 | | 32 | Implemented |
|
||||
| CC Line Sweep | `ec.transition.cclinesweep` | 5 | | 32 | Implemented |
|
||||
| CC Radial ScaleWipe | `ec.transition.ccradialscalewipe` | 3 | | 32 | Implemented |
|
||||
| CC Scale Wipe | `ec.transition.ccscalewipe` | 3 | | 32 | Implemented |
|
||||
| CC Twister | `ec.transition.cctwister` | 5 | | 32 | Implemented |
|
||||
| CC WarpoMatic | `ec.transition.ccwarpomatic` | 8 | | 32 | Implemented |
|
||||
| Card Wipe | `ec.transition.cardwipe` | 12 | | 32 | Partial: 2D flip only; no back layer picker, camera, lighting or jitter |
|
||||
| Gradient Wipe | `ec.transition.gradientwipe` | 5 | | 32 | Implemented |
|
||||
| Iris Wipe | `ec.transition.iriswipe` | 7 | | 32 | Implemented |
|
||||
| Linear Wipe | `ec.transition.linearwipe` | 3 | | 32 | Implemented |
|
||||
| Radial Wipe | `ec.transition.radialwipe` | 5 | | 32 | Implemented |
|
||||
| Venetian Blinds | `ec.transition.venetian` | 4 | | 32 | Implemented |
|
||||
|
||||
## Utility
|
||||
|
||||
| Effect | Id | Params | GPU | 32 | Status |
|
||||
|---|---|---:|:-:|:-:|---|
|
||||
| Apply Color LUT | `ec.utility.applylut` | 0 | | 32 | Implemented |
|
||||
| CC Overbrights | `ec.utility.ccoverbrights` | 2 | | 32 | Implemented |
|
||||
| Cineon Converter | `ec.utility.cineon` | 7 | | 32 | Implemented |
|
||||
| Color Profile Converter | `ec.utility.colorprofileconverter` | 7 | | 32 | Implemented |
|
||||
| Grow Bounds | `ec.utility.growbounds` | 1 | | 32 | Implemented |
|
||||
| HDR Compander | `ec.utility.hdrcompander` | 3 | | 32 | Implemented |
|
||||
| HDR Highlight Compression | `ec.utility.hdrcompression` | 1 | | 32 | Implemented |
|
||||
|
||||
+28
-10
@@ -114,22 +114,25 @@ the disk cache in the formats wave; the 3D Camera Tracker in M12.6.)
|
||||
| Audio | 85% | 0.5 | audio to keyframes |
|
||||
| Import | 88% | 2.0 | AI/EPS/PDF vector footage, PSD smart objects and 3D layers (PSD as footage/composition/retain layer sizes, SVG footage and Create Shapes from Vector Layer landed) |
|
||||
| Automation | ≈ 90% | 0.8 | scripting covers the documented core object model (AUT-2, M14.4: `app`, project items, comps, layers, properties and keyframes, text documents, markers, render queue, Script Console, `effectcraft-cli script`, MCP `run_script`); still missing: ScriptUI panels/dialogs, `.jsxbin`, sockets |
|
||||
| Shapes | 68% | 3.9 | taper and wave strokes (pen tool for shape paths and vertex editing landed in M6.5) |
|
||||
| Shapes | ≈ 80% | 1.5 | Lottie can't carry stroke taper/wave (stroke Taper and Wave, Dash 2/Gap 2/Dash 3/Gap 3 and radial-gradient Highlight Length/Angle landed in M13.5; pen tool for shape paths and vertex editing in M6.5) |
|
||||
| Compositions | ≈ 80% | 3.5 | Mocha-style planar tracks for templates, Essential Graphics' rare controls (font menus, mirrored properties) (the marker dialog, Composition Flowchart, Essential Graphics with master properties, `.ectemplate` templates and Responsive Design — Time landed: CMP-6, CMP-7) |
|
||||
| Animation | 65% | 10.4 | puppet, Wiggler/Smoother/Motion Sketch (motion-path handles and the graph editor transform box landed in M5.8) |
|
||||
| Text | ≈ 86% | 1.3 | vertical type is basic (upright characters, no tate-chu-yoko), no OpenType feature panel, no extruded strokes (extruded, bevelled text landed in M7.6); per-character styles, paragraph settings, on-canvas editing and the `sourceText` style API landed (M9.9–M9.10) |
|
||||
| Web | 60% | 2.5 | threads, browser storage, audio |
|
||||
| 3D | 84% | 7.0 | multi-view layouts, collapsed 3D precomps in Advanced 3D, the Extended Viewer; stereo rigs, orbit nulls, lights controlled by the camera, cameras/lights from glTF models, environment backgrounds, Advanced 3D motion blur, blend modes and track mattes landed in M7.7; Advanced 3D (glTF/OBJ models, primitives, extruded text and shapes, PBR, image-based light, shadow maps, GPU rasteriser) landed in M7.4–M7.6 |
|
||||
| Effects | ≈ 75% | 5.0 | GPU versions of more effects (every After Effects effect exists since M9.11, M12.5 and M12.6) |
|
||||
| Interface | 70% | 6.0 | Timeline horizontal scrolling of many columns, a richer Learn area (native macOS menu bar, Timeline columns/search/reveal-add, Home screen with recent projects and all AE workspaces landed; viewer rulers/snapping/channels/snapshots landed in M0.13) |
|
||||
| Animation | 67% | 10.0 | puppet, Wiggler/Smoother/Motion Sketch (motion-path handles and the graph editor transform box landed in M5.8; keyframe colour labels and Select Keyframe Label Group, Graph Editor snapping to markers / layer ends in M13.5) |
|
||||
| Text | ≈ 91% | 0.8 | no OpenType feature panel, no extruded strokes, variable-axis animation changes outlines but not advances (vertical Roman / Tate-Chu-Yoko, forced LTR paragraphs, caret on animated and path text, Variable Font Axes and Lottie style runs landed in M13.5; extruded, bevelled text in M7.6; per-character styles, paragraph settings, on-canvas editing and the `sourceText` style API in M9.9–M9.10) |
|
||||
| Web | 85% | 1.0 | viewer frames and Roto Brush propagation still on the page's thread; GPU effects in the browser (browser storage, Web Audio, Web Worker renders/analyses, WebGPU viewer and offline install landed in M15.2) |
|
||||
| 3D | 85% | 6.5 | multi-view layouts, iris shapes in Advanced 3D's depth of field, collapsed 3D precomps in Advanced 3D, the Extended Viewer; stereo rigs, orbit nulls, lights controlled by the camera, cameras/lights from glTF models, environment backgrounds, Advanced 3D motion blur, blend modes and track mattes landed in M7.7; Classic 3D iris-shaped bokeh with highlights, progressive depth of field on tilted layers and the focus-link commands landed in M13.5; Advanced 3D (glTF/OBJ models, primitives, extruded text and shapes, PBR, image-based light, shadow maps, GPU rasteriser) in M7.4–M7.6 |
|
||||
| Effects | ≈ 80% | 4.5 | GPU versions of more effects and the missing controls listed as partial in [effects.md](effects.md) (every After Effects effect exists since M9.11, M12.5 and M12.6; parameter names, order, twirl-downs, popups, units and defaults were aligned in M9.12) |
|
||||
| Interface | 74% | 5.0 | a richer Learn area (Timeline outline and Project panel columns scroll horizontally, the Layer Style dialog, ROI resize handles, Pan Behind snapping and 3D Reference Axes landed in M13.5; native macOS menu bar, Timeline columns/search/reveal-add, Home screen with recent projects and all AE workspaces landed; viewer rulers/snapping/channels/snapshots landed in M0.13) |
|
||||
| Project | ≈ 68% | 5.5 | auto-save, folder moves, OCIO displays beyond the built-in tone map (Color Engine with OCIO/ACES working spaces, HDR compand/tone mapping, Rec. 2100 PQ/HLG output, Feet + Frames, display colour management, Simulate Output and the locked viewer landed in M7.7; proxies and Interpret Footage fields / pixel aspect / alpha guess landed: PRJ-8, PRJ-3) |
|
||||
| Masks & roto | 68% | 6.0 | variable-width mask feather points, Roto Brush's learned (3.0) segmentation model (mask tracking and Mask Interpolation landed in M6.6; Roto Brush & Refine Edge with graph-cut segmentation, flow propagation, edge matting, decontamination and Freeze in M6.7) |
|
||||
| Masks & roto | 74% | 5.0 | Roto Brush's learned (3.0) segmentation model (variable-width mask feather points with the Mask Feather tool landed in M13.5; mask tracking and Mask Interpolation landed in M6.6; Roto Brush & Refine Edge with graph-cut segmentation, flow propagation, edge matting, decontamination and Freeze in M6.7) |
|
||||
| Preview | 62% | 5.0 | GPU 3D and adjustment layers (persistent disk cache with the blue cache bar landed; region of interest, snapshots, exposure and Fast Previews landed in M0.13) |
|
||||
| Tracking | ≈ 85% | 2.5 | face tracking, Subspace Warp's mesh warp, lens distortion in the camera solve (Rolling Shutter Repair landed in M9.11; point tracker, mask tracking, Warp Stabilizer and the 3D Camera Tracker landed in M6.x / M12.5 / M12.6) |
|
||||
| Paint | 0% | 4.0 | Brush, Clone Stamp, Eraser |
|
||||
|
||||
## Effects still missing
|
||||
|
||||
The full catalogue with GPU / 32-bpc badges and per-effect status is [effects.md](effects.md)
|
||||
(generated from the registry).
|
||||
|
||||
None: the 3D Camera Tracker landed in M12.6. Boris FX
|
||||
Mocha and Cineware are third-party and not counted.
|
||||
|
||||
@@ -138,7 +141,7 @@ Mocha and Cineware are third-party and not counted.
|
||||
| Category | Effects | Notes |
|
||||
|---|---|---|
|
||||
| 3D Channel | 3D Channel Extract, Cryptomatte, Depth Matte, Depth of Field, EXtractoR, Fog 3D, ID Matte, IDentifier | Read auxiliary channels: multi-layer OpenEXR (any `layer.channel`, Cryptomatte manifests from the header) or the compositor's own depth / layer-ID / normal / UV / Cryptomatte pass for precomps of 3D comps. |
|
||||
| Immersive Video | VR Blur, VR Chromatic Aberrations, VR Color Gradients, VR Converter, VR De-Noise, VR Digital Glitch, VR Fractal Noise, VR Glow, VR Plane to Sphere, VR Rotate Sphere, VR Sharpen, VR Sphere To Plane | Seam-aware equirectangular processing (wrap-around, pole continuation, latitude-scaled filters), mono / over-under / side-by-side layouts; VR Converter between equirectangular, cube maps (4:3, 3:2, 6:1), sphere map and 2D. |
|
||||
| Immersive Video | VR Blur, VR Chromatic Aberrations, VR Color Gradients, VR Converter, VR De-Noise, VR Digital Glitch, VR Fractal Noise, VR Glow, VR Plane to Sphere, VR Rotate Sphere, VR Sharpen, VR Sphere to Plane | Seam-aware equirectangular processing (wrap-around, pole continuation, latitude-scaled filters), mono / over-under / side-by-side layouts; VR Converter between equirectangular, cube maps (4:3, 3:2, 6:1), sphere map and 2D. |
|
||||
| Color Correction | OCIO CDL / Color Space / Display / File / Look Transform, Color Stabilizer | Built-in minimal OCIO-style config (ACES2065-1, ACEScg, ACEScct, sRGB, Rec.709, Rec.2020, Display P3, linear variants, XYZ) from published matrices and transfer functions; `.cube` / `.3dl` / `.csp` LUTs and ASC `.cc` / `.ccc` / `.cdl`. Custom `.ocio` config files are read (Configuration ▸ Custom: colorspaces, roles, displays/views; Matrix, File, Exponent, Log, LogAffine, CDL, Range and Group transforms). |
|
||||
| Distort | CC Flo Motion, Liquify, Rolling Shutter Repair | Liquify strokes are effect data replayed into a displacement mesh (`liquify.stroke` / `liquify.clear` commands; no interactive viewer brush yet). Rolling Shutter Repair uses the KLT tracker. |
|
||||
| Blur & Sharpen | Camera-Shake Deblur, CC Radial Blur | Deblur substitutes aligned patches from sharper neighbouring frames. |
|
||||
@@ -146,7 +149,22 @@ Mocha and Cineware are third-party and not counted.
|
||||
| Simulation | CC Hair, Particle Playground | Particle Playground: cannon, grid, layer exploder, layer map, gravity, repel, wall, persistent property mapper (no Particle Exploder, text particles or ephemeral mapper yet). |
|
||||
| Keying | Key Light | The full Keylight 1.2 control set under a generic name ("Keylight" is a vendor trademark); `lookup("Keylight (1.2)")` finds it. |
|
||||
| Utility | Color Profile Converter | Our colour spaces and ACES; rendering intents (perceptual gamut compression, relative / absolute colorimetric, saturation). |
|
||||
| Obsolete | mocha shape | Mocha's export format is not public: reads a documented JSON shape format instead. |
|
||||
| Matte | Mocha shape | Mocha's export format is not public: reads a documented JSON shape format instead. |
|
||||
|
||||
## Update: M13.5 long-tail polish
|
||||
|
||||
Stroke Taper / Wave / multi-segment dashes and the radial gradient highlight (SHP-2);
|
||||
variable-width mask feather points (MSK-1; mask motion blur verified by tests); the Adaptive
|
||||
Sample Limit driving per-layer motion-blur samples (LYR-10); Classic 3D depth of field with
|
||||
the camera's iris shape, rotation, roundness, aspect ratio, diffraction fringe and highlights,
|
||||
progressive blur on tilted layers, and Link Focus Distance to Point of Interest / to Layer and
|
||||
Set Focus Distance to Layer (3D-1); Timeline outline and Project panel column scrolling;
|
||||
keyframe colour labels and Select Keyframe Label Group (ANM-1); vertical Roman text,
|
||||
Tate-Chu-Yoko, forced LTR paragraphs, the editing caret on animated / path text and Lottie
|
||||
style runs; the Layer Style dialog (LYR-9); Graph Editor snapping to markers and layer ends
|
||||
(ANM-4; the reference graph existed); viewer ROI resize handles, Pan Behind snapping and 3D
|
||||
Reference Axes; Animate Text ▸ Variable Font Axes. Remaining in these rows: Lottie can't carry
|
||||
taper/wave, Advanced 3D's DOF has no iris shapes, and variable axes don't change advances.
|
||||
|
||||
## Highest-value gaps, in order
|
||||
|
||||
|
||||
+138
-30
@@ -2,9 +2,10 @@
|
||||
|
||||
`apps/effectcraft-web` runs the same engine and egui UI as the desktop app in the browser: the
|
||||
workspace compiled to `wasm32-unknown-unknown`, started by eframe's web runner on WebGPU (WebGL2
|
||||
fallback). It is a static site: one `.wasm`, its `wasm-bindgen` JavaScript glue, `index.html` and an
|
||||
icon. Nothing is uploaded anywhere; projects, media and renders stay in the page and on the user's
|
||||
machine.
|
||||
fallback). It is a static site: one `.wasm`, its `wasm-bindgen` JavaScript glue, `index.html`, a
|
||||
few small scripts (worker, audio worklet, service worker), a web manifest and icons. Nothing is
|
||||
uploaded anywhere: projects, media, settings and renders stay in the browser (its private storage)
|
||||
and on the user's machine.
|
||||
|
||||
## Build and run
|
||||
|
||||
@@ -15,48 +16,136 @@ machine.
|
||||
| wasm-opt (optional) | any recent binaryen | `brew install binaryen`; used by `cargo xtask web` when found |
|
||||
|
||||
```sh
|
||||
cargo xtask web # release build → <target>/web/dist (index.html, effectcraft_web.js, effectcraft_web_bg.wasm, favicon.svg)
|
||||
cargo xtask web # release build → <target>/web/dist
|
||||
cargo xtask web --dev # unoptimised build (faster to compile, slow to run)
|
||||
cargo xtask web --serve 8765 # build, then serve dist on http://127.0.0.1:8765/
|
||||
```
|
||||
|
||||
`<target>` is `$CARGO_TARGET_DIR` or `target`. `--serve` is a tiny localhost-only static server that
|
||||
sends `Cross-Origin-Opener-Policy` / `Cross-Origin-Embedder-Policy`, so the page is cross-origin
|
||||
`<target>` is `$CARGO_TARGET_DIR` or `target`. `dist` holds `index.html`, `effectcraft_web.js` +
|
||||
`effectcraft_web_bg.wasm` (+ `snippets/`, the browser glue `js/host.js`), `worker.js`,
|
||||
`audio-worklet.js`, `sw.js` (its precache list and version filled in by the build),
|
||||
`manifest.webmanifest`, `favicon.svg` and `icon-256.png` / `icon-512.png` (copied from
|
||||
`assets/app-icon`). `--serve` is a tiny localhost-only static server that sends
|
||||
`Cross-Origin-Opener-Policy` / `Cross-Origin-Embedder-Policy`, so the page is cross-origin
|
||||
isolated like a production deployment should be. Any static server works
|
||||
(`python3 -m http.server -d target/web/dist 8765`); it must serve `.wasm` as `application/wasm`.
|
||||
Service workers need a secure context: `https://`, or `http://localhost` / `127.0.0.1`.
|
||||
|
||||
The release `.wasm` is about 31 MB before `wasm-opt` (20 MB code: the effects, codecs, the
|
||||
expression engine and the UI; 8.5 MB data, mostly the bundled fonts; 2 MB function names for
|
||||
readable panics). Served compressed it is a fraction of that.
|
||||
The release `.wasm` is about 38 MB before `wasm-opt` (code: the effects, codecs, the expression
|
||||
engine and the UI; data, mostly the bundled fonts; function names for readable panics). Served
|
||||
compressed it is a fraction of that, and the service worker caches it after the first visit.
|
||||
|
||||
The web crate is empty on non-wasm targets, so `cargo test --workspace` and clippy are unaffected;
|
||||
`cargo xtask wasm` (part of `cargo xtask ci`) checks it, with every L0–L4 crate and
|
||||
`effectcraft-ui-egui`, for `wasm32-unknown-unknown`.
|
||||
On other targets the web crate holds only its portable storage model (`store.rs`, unit-tested by
|
||||
`cargo test --workspace`); `cargo xtask wasm` (part of `cargo xtask ci`) checks the whole crate,
|
||||
with every L0–L4 crate and `effectcraft-ui-egui`, for `wasm32-unknown-unknown`.
|
||||
|
||||
URL flags: `?empty` (start without the demo project), `?home` (show the start screen).
|
||||
URL flags: `?empty` (a blank project; the session is not restored or recorded), `?demo` (the demo
|
||||
project instead of the last session), `?home` (show the start screen), `?storage=indexeddb` /
|
||||
`?storage=memory` (force a storage backend), `?noworkers` (render and analyse on the page's
|
||||
thread), `?nosw` (don't register the service worker).
|
||||
|
||||
## How the desktop pieces map to the browser
|
||||
|
||||
| Desktop | Web |
|
||||
|---|---|
|
||||
| frame render thread pool (`ui-egui/src/frames.rs`) | `Frames::pump`: queued frames render on the UI thread after each egui frame, most important first (the viewer's frame, then prefetch), within 40 ms (24 ms while playing) |
|
||||
| Render Queue on a background thread | `Session::start_render` always runs inline on wasm32: the page waits until the render is done |
|
||||
| Render Queue on a background thread | a Web Worker running a second engine instance (below); progress streams back, the page never waits |
|
||||
| tracker / mask tracker / Warp Stabilizer / 3D Camera Tracker / Roto Brush Freeze threads | the same workers; the analysed property group comes back as one undo step |
|
||||
| `rayon` parallel loops (raster, effects, export batches) | rayon's global pool falls back to the calling thread when threads are unavailable: same code, serial |
|
||||
| `std::time::Instant` / `SystemTime` (panic on wasm32) | `web-time` (re-exports `std::time` on native) |
|
||||
| `std::fs` project reads/writes (`FsServices`) | `files::WebServices`: an in-memory file table; saving downloads the `.ecproj` |
|
||||
| `std::fs` project reads/writes (`FsServices`) | `files::WebServices`: the virtual file table, persisted (below); saving also downloads the `.ecproj` |
|
||||
| config directory: settings, shortcut presets, recent projects, the recovery sentinel | `store::WebConfig` in browser storage |
|
||||
| auto-save folder | `/EffectCraft Auto-Save/` in browser storage (`ConfigStore::files`) |
|
||||
| media reads (`MediaPool`, `probe`) | `files::WebImporter`: bytes from the file table, handed to `MediaPool::add_bytes` / `probe_bytes` |
|
||||
| export writes (`effectcraft-export`) | the job's `sink` (`effectcraft_host::FileExporter { sink }`): files land in the table and download after the render; several files (an image sequence) download as one stored `.zip` |
|
||||
| rfd file dialogs | `<input type=file>` for File ▸ Open / Import; drop files anywhere on the page (`.ecproj` opens, everything else imports); "Save As" / "Output To" pick a download name |
|
||||
| system fonts | not scanned; the bundled fonts (Inter, Noto Serif, JetBrains Mono) are always there |
|
||||
| TCP control channel / MCP | `window.effectcraft` (below) |
|
||||
| audio output | none yet (if `cpal` lands for desktop playback it must stay behind a cfg/feature off wasm32; a WebAudio backend would replace it) |
|
||||
| cpal audio output | Web Audio (below) |
|
||||
| GPU compositor on the desktop's wgpu device | the same compositor on eframe's WebGPU device (below) |
|
||||
|
||||
### Threads
|
||||
### Persistence
|
||||
|
||||
wasm threads need a cross-origin isolated page **and** a wasm build with atomics (a nightly
|
||||
`build-std` toolchain), so this build is single-threaded: frames, effects and exports run on the UI
|
||||
thread. A long Render Queue job freezes the page until it finishes; keep web renders short or
|
||||
small (resolution, time span).
|
||||
Everything that lives in files on the desktop lives in the browser's **Origin Private File
|
||||
System** (OPFS); where OPFS can't be written from the page (older Safari), **IndexedDB**; with
|
||||
neither (some private windows), memory only. `effectcraft.info().storage.backend` says which.
|
||||
The page asks for persistent storage (`navigator.storage.persist()`), which browsers grant to
|
||||
installed apps, so the store isn't evicted under storage pressure.
|
||||
|
||||
The engine's storage traits are synchronous and the browser's are not, so the app works on an
|
||||
in-memory mirror (`store.rs`): every stored entry is read before the app starts, reads and writes
|
||||
hit the mirror, and changes flush in the background (one write per changed key, in order; OPFS
|
||||
writes are atomic: a swap file replaced on close). Keys:
|
||||
|
||||
| Key | What |
|
||||
|---|---|
|
||||
| `config/prefs.json`, `config/shortcuts.json` | Settings (with File ▸ Open Recent's list) and keyboard shortcut presets |
|
||||
| `config/session.lock` | the crash-recovery sentinel |
|
||||
| `config/session.ecproj`, `config/session.json` | the session snapshot: the open project and editor state (active comp, time, selection), written at most once a second while they change |
|
||||
| `files/<path>` | the file table: imported media, projects saved with File ▸ Save / Save As or `saveToBrowser`, auto-saves |
|
||||
|
||||
On the next visit the app reopens the snapshot (unsaved changes stay unsaved: the project is
|
||||
dirty), registers every stored media file with the media pool so its footage decodes, and File ▸
|
||||
Open Recent reopens saved projects from storage. Without a snapshot (first visit) it opens the
|
||||
demo project. Render outputs are not stored: they download.
|
||||
|
||||
### Background jobs: Web Workers
|
||||
|
||||
wasm threads need shared memory, which needs a nightly `build-std` toolchain, so this build is
|
||||
single-threaded per instance. Long jobs run in **Web Workers** instead, each with its own instance
|
||||
of the same module (the page compiles it once and posts the `WebAssembly.Module`, so nothing is
|
||||
compiled twice) and its own memory (`crates/engine/src/offload.rs`, `src/worker.rs`):
|
||||
|
||||
1. The session's `Offload` serializes a `WorkerRequest`: the project JSON, the footage paths it
|
||||
reads, and the job (`render` with the resolved queue items and output paths; `warp`, `camera`,
|
||||
`track`, `maskTrack`, `rotoFreeze` with the target and analysis parameters).
|
||||
2. `js/host.js` takes an idle worker from its pool (or starts one), sends it the footage bytes it
|
||||
doesn't have yet, then the request.
|
||||
3. The worker runs the job on a plain engine session, blocking, and posts `WorkerReply`s: render
|
||||
progress (at most every 100 ms), item started/finished, rendered files (transferred), analysis
|
||||
progress, the analysed property group, `failed`, `done`.
|
||||
4. The page applies them every frame: `Session::poll_render` updates the queue items and the
|
||||
progress bar, `Session::poll_offload` writes an analysis result as one undo step (the effect /
|
||||
tracker / mask group is replaced; other edits made meanwhile are kept) and the downloads start.
|
||||
|
||||
Stopping a job terminates its worker (a worker can't be interrupted mid-frame): the item being
|
||||
rendered becomes "User Stopped", an analysis writes nothing. `renderQueue.render {wait: true}` (the
|
||||
default for agents) and analysis commands with `wait: true` still run on the page's thread and
|
||||
return when done. Roto Brush propagation fills the session's segmentation cache rather than the
|
||||
project, so it runs on the page's thread too, as do viewer frames (`Frames::pump`).
|
||||
|
||||
### Audio
|
||||
|
||||
Audio preview goes through **Web Audio**: an AudioWorklet (`audio-worklet.js`; a
|
||||
ScriptProcessorNode where worklets are unavailable) plays interleaved stereo blocks. The mixdown
|
||||
is the desktop's (`AudioPlayback`, `mix_comp`): without a feeder thread, `AudioPlayback::pump`
|
||||
mixes ahead on every UI frame (≈ 350 ms queued) and the output device takes what keeps it
|
||||
≈ 150 ms ahead of the playhead. A/V sync follows `AudioContext.currentTime`: the playback clock
|
||||
is the frames played by the context clock minus its output latency, and the viewer shows the
|
||||
frame under the audible sample, as on the desktop. The Audio panel's meters read the same feed.
|
||||
|
||||
Browsers start an AudioContext suspended until the user interacts with the page; the app resumes
|
||||
it on the first pointer or key event, so audio plays from the first preview after any click or
|
||||
key press.
|
||||
|
||||
### GPU
|
||||
|
||||
eframe starts on WebGPU where the browser has it (WebGL2 otherwise), and the GPU compositor
|
||||
(`effectcraft-gpu`) runs on the same device: viewer frames are composited by compute shaders and
|
||||
drawn straight from their texture, with no readback. Steps that need the CPU mid-render (3D runs,
|
||||
adjustment layers, CPU-only effects) fall back to the CPU renderer for that frame, because the
|
||||
page's thread can't wait for a GPU readback. The Info panel's pixel readout and the eyedroppers
|
||||
read GPU frames back asynchronously (`Gpu::read_display_async`: the pixels arrive a frame
|
||||
later). On WebGL2, or without a usable adapter, everything renders on the CPU.
|
||||
`effectcraft.info().gpu` reports `{compositor, viewerOnGpu}`.
|
||||
|
||||
### Offline and install (PWA)
|
||||
|
||||
`manifest.webmanifest` (name, icons, standalone display) makes the app installable; `sw.js`
|
||||
precaches every file of the build into a cache named after the build's hash, serves them
|
||||
cache-first (the cached responses keep the server's COOP/COEP headers, so the page stays
|
||||
cross-origin isolated offline), and drops older caches when a new build activates. After the
|
||||
first visit the app loads without a network.
|
||||
|
||||
## `window.effectcraft`: the agent / test API
|
||||
|
||||
@@ -70,34 +159,53 @@ with the method's `result`, errors reject with the message.
|
||||
| `effectcraft.commands()` / `effectcraft.inspect()` | `engine.commands` / `ui.inspect` |
|
||||
| `effectcraft.renderFrame(params)` | `render.frame` with `base64: true`: `{comp, time, width, height, png}` |
|
||||
| `effectcraft.screenshot(params)` | `ui.screenshot`; without `path` the PNG comes back inline as `png` (base64) |
|
||||
| `effectcraft.addFile(fileOrUrl, name?)` | put a `File`/`Blob` (or fetched URL) into the file table and open (`.ecproj`) or import it; resolves with its path |
|
||||
| `effectcraft.addFile(fileOrUrl, name?)` | put a `File`/`Blob` (or fetched URL) into the file table (stored) and open (`.ecproj`) or import it; resolves with its path |
|
||||
| `effectcraft.files()` / `effectcraft.readFile(path)` | the file table `[{path, size}]` / a file's bytes (`Uint8Array`), e.g. a render |
|
||||
| `effectcraft.info()` | graphics backend, version, `crossOriginIsolated`, load timings |
|
||||
| `effectcraft.saveToBrowser(path?)` | save the project to browser storage without downloading it (default: its path, or `/<name>.ecproj`); resolves with `{path, bytes}` |
|
||||
| `effectcraft.listStored()` | `{backend, usage, quota, persisted, pending, files: [{path, size, modified}], config: [name]}` |
|
||||
| `effectcraft.removeStored(path)` | delete a stored file |
|
||||
| `effectcraft.flush()` | resolves once every change is written to browser storage |
|
||||
| `effectcraft.info()` | graphics backend, `gpu`, `storage`, `audio` (`{state, sampleRate, backend, posted, played, underruns}`), `workers`, `restored`, `webgpu`, `serviceWorker`, version, `crossOriginIsolated`, load timings |
|
||||
|
||||
`window.effectcraftLoad` holds `{wasmMs, readyMs}` (module fetch + compile, and until the app runs).
|
||||
|
||||
```js
|
||||
await effectcraft.execute("layer.newSolid", {color: "#ff8800"});
|
||||
await effectcraft.request("ui.menu.invoke", {id: "renderQueue.add", params: {format: "gif", resolution: 0.25}});
|
||||
await effectcraft.execute("renderQueue.render", {}); // the GIF downloads
|
||||
await effectcraft.execute("renderQueue.render", {wait: false}); // renders in a worker; the GIF downloads
|
||||
await effectcraft.saveToBrowser("/my-project.ecproj"); // File ▸ Open Recent has it after a reload
|
||||
```
|
||||
|
||||
## Browser test
|
||||
|
||||
`apps/effectcraft-web/tests/smoke.mjs` drives headless Chrome over the DevTools protocol (Node ≥ 22,
|
||||
no npm packages): load, the demo comp in the viewer, `render.frame`, Render Queue GIF and PNG
|
||||
sequence (`.zip`) downloads, Save As and re-opening the saved project. It writes screenshots and
|
||||
`report.json`:
|
||||
no npm packages): load, the GPU path (WebGPU → GPU compositor, viewer on the GPU), the demo comp
|
||||
in the viewer, `render.frame`, Render Queue GIF and PNG sequence (`.zip`) downloads, a background
|
||||
render in a worker while measuring the page's event-loop gaps (must stay under 400 ms) and its
|
||||
progress, the AudioContext starting on a (simulated) key press and a tone playing through it
|
||||
with the meters moving, Save As and re-opening the saved project, persistence across a reload
|
||||
(session snapshot, a stored project, imported media, a setting, Open Recent) and an offline
|
||||
reload through the service worker. It writes screenshots and `report.json`:
|
||||
|
||||
```sh
|
||||
cargo xtask web --serve 8765 &
|
||||
node apps/effectcraft-web/tests/smoke.mjs --url http://127.0.0.1:8765/ --out target/web/smoke
|
||||
```
|
||||
|
||||
Native unit tests cover the storage model (`apps/effectcraft-web/src/store.rs`: write
|
||||
coalescing, file table, `ConfigStore` / `FileOps`, auto-save and crash recovery through the
|
||||
browser store) and the worker protocol (`crates/engine/src/offload.rs`: serde round trips of
|
||||
every request and reply, a render through an in-process offload).
|
||||
|
||||
## Gaps
|
||||
|
||||
- Single-threaded (above); Render Queue renders block the page.
|
||||
- No audio playback.
|
||||
- Imported media live in memory for the session only (nothing is persisted; reload = fresh start).
|
||||
- Viewer frames, RAM preview and Roto Brush propagation still render on the page's thread (one
|
||||
frame at a time between UI frames).
|
||||
- GPU effects run only in the desktop GPU path: in the browser, effects run on the CPU (inside
|
||||
workers for renders) because the page's thread can't wait for mid-render readbacks.
|
||||
- No disk cache (Settings ▸ Media & Disk Cache) in the browser: the layer cache stays in memory.
|
||||
- Cancelling an analysis drops its partial result (the worker is terminated).
|
||||
- Stored media count against the origin's storage quota; `effectcraft.listStored()` shows usage,
|
||||
`removeStored` frees it (there is no storage manager in the UI yet).
|
||||
- `engine.execute` rejects the spread Render Settings / Output Module keys of `renderQueue.add`
|
||||
(`resolution`, `timeSpan`…) through its strict parameter check; use `ui.menu.invoke` as above.
|
||||
|
||||
Reference in New Issue
Block a user