Files
oak-editor/docs/zh/plans/ofx-misc-gpu-cleanroom.md
T
Mike-Solar a7916aa93d nodes: OpenFX-Misc cleanroom GPU ports, grouped and collapsible in the library
21 built-in effects reimplemented as native GPU nodes from the
OpenFX-Misc algorithm references (cleanroom, docs in
docs/zh/plans/ofx-misc-gpu-cleanroom.md):
- Color: Color Correct, Gamma, Saturation, Invert, Clamp, Grade
- Matrix/morphology: Color Matrix, Edge Detect, Dilate, Erode
- Blur: Directional Blur, Sharpen (unsharp mask)
- Merge: Dissolve, Key Mix, Premultiply, Unpremultiply
- Geometry/generators: Position, Mirror, Checkerboard, Color Bars, Ramp

Every node carries unit tests plus GPU pixel tests (28 cases over five
ofxmisc_* suites). The effect library groups built-ins by category
(color/filter/distort/keying/generator/math/general) with collapsible
group headers persisted to the config; the inspector's add menu groups
the same way. Registration wiring and the factory smoke table land with
the adjustment/transition wave sharing the same files.
2026-09-10 22:02:38 +08:00

156 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenFX-Misc 洁净室 GPU 重写(内置特效扩充)与特效分类/折叠计划
> 面向实现者的任务书(2026-09-10)。本文只描述方案与工作项,不含已执行的代码修改。
> 用户要求:"把 OpenFX-Misc 洁净室重写为 GPU 版本,作为内置特效加入进去,并给内置特效
> 加分类和折叠分类的功能。"参考源码已克隆到本机 `/tmp/ofx-misc`(上游
> `github.com/cgvirus/OpenFX-Misc`,GPL2,86 个插件目录,README 有完整清单)。
>
> 法律/工程边界:**洁净室**指不复制其代码——我们只读其算法描述与参数语义,
> GLSL 与节点代码全部自写。仓内节点实现模式已有 60+ 先例(oak-node/src/nodes/*.rs),
> 本计划实质是"参照 OpenFX-Misc 的特效清单,按仓内既有节点模式补齐内置特效"。
## 1. 现状
### 1.1 节点/渲染管线(完全够用)
- 内置特效 = `oak-node/src/nodes/*.rs` 的 `NodeBehavior` 实现:声明输入(`Input`),
`value()` 推 `ShaderJobPayload`(`crates/oak-node/src/jobs.rs`),`shader_code()`
返回 GLSL 片段。渲染端 `crates/oak-render/src/eval.rs::process_shader_job`:
编译(naga→WGSL,**不支持 GLSL switch**——新 shader 一律 if/else,教训见提交
`37df1d3d3`)、按名绑定全部纹理参数、嵌套 payload 递归(深度上限 8)、
`resolution_in` 自动锚定序列分辨率(提交 `fc9060424`)、`iterations` 多轮 +
`previous_iteration_in` 反馈。GPU 像素测试模式:`eval.rs tests::eval_node_row`。
- 坐标/基准约定:像素空间以**画面中心**为原点(transform 语义,提交 `d028a45ff`);
像素尺寸参数(半径/宽度/距离)按序列分辨率解释。
- 已有同类特效(避免重复):blur、opacity、transform、crop、flip(Distort 系)、
merge、mrg(生成器 alpha-over)、math、chromakey、colordifferencekey、despill、
solid、polygon、shape、noise、ociobase/lut/grading、whitebalance、threewaycolor、
mask、stroke、dropshadow、displaytransform、cornerpin(假实现,另案)、
tile/swirl/ripple/wave(Distort 系)、trigonometry、volume、pan。
### 1.2 特效库 UI
- `crates/oak-app/src/oakui/effectchain.rs::addable_effects`:内置(`group: None`)
+ OFX 动态条目(`group: Some(子类)`),排序已按组+名字。
- `crates/oak-app/src/panels/effect_library.rs`:渲染时组头已存在
(`group_header()`,内置统一一个 "Built-in" 头),**不可折叠**;有搜索框。
- 检查器"添加特效"菜单(`panels/inspector.rs:157`)吃同一张 `addable_effects` 表。
## 2. 目标
1. 参照 OpenFX-Misc 清单,按 GPU 版本洁净室重写一批常用特效,作为**内置特效**
(oak-node 原生节点,非 OFX 运行时)加入。
2. 内置特效按功能分类(Color / Filter / Keying / Distort / Generator / Merge / Time),
特效库与检查器添加菜单都按分类分组,**分类可折叠**(折叠状态持久化)。
## 3. 特效分批(实现范围)
### Tier 1(本批必做,算法简单、GLSL 直译,全部像素可测)
| 特效(参考) | 分类 | 输入(节点参数) | 算法要点 |
|---|---|---|---|
| ColorCorrectOFX | Color | saturation/contrast/gamma/gain/offset(各 5 组:master/shadows/midtones/highlights)太多了→**简化为全局 5 参数**(saturation/contrast/gamma/gain/offset) | 逐像素 `offset+gain*pow(x,gamma)`,contrast 绕 0.18 灰,saturation 绕 luma |
| GammaOFX | Color | gamma(单值) | `pow(x, 1/g)` |
| SaturationOFX | Color | saturation | luma 插值(与 whitebalance/threeway 不重复:它最简) |
| InvertOFX | Color | channel 开关(RGBA) | `1-x`(按通道掩码) |
| ClampOFX | Color | min/max | clamp 每通道 |
| ColorMatrixOFX | Color | 4x4 矩阵(16 float) | 矩阵×RGBA(uniform mat4 已有先例:transform_in) |
| GradeOFX | Color | blackPoint/whitePoint/blackOut/whiteOut/gamma | 黑白点重映射 |
| DirBlurOFX | Filter | amount/angle | 方向模糊(迭代采样 N=16,角度→方向向量) |
| SharpenCImg | Filter | amount | unsharp mask:x + amount·(x − blur(x))(blur 复用现有迭代模糊,嵌套 payload) |
| EdgeDetectCImg | Filter | threshold/通道 | Sobel 幅值 |
| Dilate/ErodeCImg | Filter | radius/shape(rect) | 3×3~7×7 结构元 max/min(radius 控制迭代轮数) |
| DissolveOFX | Merge | mix(0..1)、第二输入 blend_in | 加权平均(merge.rs 双输入绑定已有先例;转场功能的原子件) |
| KeyMixOFX | Merge | mask_in、blend_in | 按 mask 拷贝(mask 绑定已有先例:chromakey 的 garbage/core matte) |
| PreMult/UnpremultOFX | Merge | channel 选择 | rgb *= a / rgb /= a(0 保护) |
| PositionOFX | Distort | offset xy(整数 px) | 采样偏移(resolution_in 换算) |
| MirrorOFX | Distort | horizontal/vertical | 翻转采样(flip 节点已有?若有重复则跳过——实现时先查 flip.rs 覆盖面) |
| CheckerBoardOFX | Generator | size/color1/color2 | 程序化棋盘格 |
| ColorBarsOFX | Generator | SMPTE/100%/75% | 彩条(分段填色) |
| RampOFX | Generator | point0/point1/color0/color1 | 线性渐变 |
| Rand(噪声已有) | — | — | **跳过**(noise.rs 已覆盖) |
| Constant(solid 已有) | — | — | **跳过** |
合计约 17 个新节点(Mirror 可能合并/跳过)。
### Tier 2(第二批,涉及曲线/对数/卷积/积雨云)
HSVTool(色相替换+keyer 能力)、Quantize(海报化/抖动)、Log2Lin/PLogLin、
ClipTest(斑马纹超范围指示)、Matrix3x3/Matrix5x5(通用卷积)、GodRays(径向
辉光,迭代采样)、ColorLookup(分通道曲线——**复用现有曲线编辑器**
`gpui_widgets::curve_editor` + `oak_plugin::param_curve` 的 JSON 模型,参数为 Text)。
### Tier 3(明确不做,写明理由)
- Roto(要主机遮罩编辑)、TrackerPM(点跟踪,需交互与多帧)、Card3D(3D 投影)、
STMap/IDistort(位移图输入——其实可做,列 Tier 2 备选)、Shadertoy(沙盒运行时)、
全部 Views/立体声(无多视图管线)、CImg 重型族(DenoiseSharpen/Smooth* PDE/Inpaint——
迭代 PDE 不适合实时 GPU 预览)、**全部时间域**(FrameBlend/FrameHold/Retime/
TimeBlur/SlitScan/TimeOffset/AppendClip——`ShaderJobPayload` 只能采当前时刻纹理,
多时刻采样需要 job 管线扩展,**单独立案**,不在本计划)。
## 4. 节点实现模板(所有新节点统一)
每个新节点 = `oak-node/src/nodes/` 一个文件,遵循既有模式(参照 `opacity.rs` /
`colorcorrect` 无、参照 `blur.rs`/`math.rs`):
1. 常量输入 id + `create()`(输入、默认值、min/max、combo 字符串、`VIDEO_EFFECT` 标志、
`core.effect_input = "tex_in"`;双输入节点参考 merge.rs 的 base/blend)。
2. `value()`:无纹理直通(参考各节点的 `// CPP-PARITY` 注释体例),否则推
`ShaderJobPayload`(`shader_id: ""`,`iterations: 1`)。
3. `shader_code()`:GLSL 片段(ove_texcoord/frag_color;**禁用 switch**;
像素尺寸参数用 `resolution_in`;采样偏移用中心原点像素空间与否按特效语义——
颜色类与坐标无关,几何类参照 transform 的中心原点)。
4. `register()` 进 `nodes/mod.rs` 的注册表。
5. 单元测试(输入默认值/隐藏标志/job 参数)+ **`crates/oak-render/src/eval.rs`
GPU 像素测试**(eval_node_row 模式,无 GPU 自动跳过)。颜色类用纯色输入断言
输出值;几何/模糊类用点/块图案断言位移/扩散。
## 5. 分类与折叠(UI)
1. **内置特效分类**:`addable_effects()` 的内置分支改为 `group: Some(分类)`,
分类取自节点 `categories()` 首个 `Category` 映射:
`Category::Color→"调色"`(或英文 "Color",跟 i18n key)、`Filter→"滤镜"`、
`Distort→"扭曲"`、`Keyer→"键控"`、`Generator→"生成器"`、`Merge→"合成"`、
`Time→"时间"`、`Math→"数学"`、`Channel→"通道"`。映射函数放
`effectchain.rs`(`node_category_key` 已有类似物,见 engine.rs:206,
但该函数是给节点编辑器菜单的 i18n key,特效库分组可直接复用同一 key 体系)。
i18n:8 语言加 `effect_library.group.<key>`。
2. **折叠**:`effect_library.rs` 组头加点击折叠/展开(箭头 ▶/▼ + 组名):
- 面板 struct 增加 `collapsed: std::collections::HashSet<String>`(组 key),
点击组头切换;渲染时折叠组跳过其子行。
- 持久化:`oak_core::configstore`(参照现有 `UseProxyMedia` 等键的读写模式),
键 `EffectLibraryCollapsed`(逗号分隔组 key 列表)。
- 检查器的添加菜单(inspector.rs:157 的菜单构建)同样按组分组
(menu.rs 支持子菜单——组做子菜单,比折叠更适合菜单形态;实现时确认
`MenuItem::with_submenu` 用法,与 proxy_submenu 一致)。
3. 搜索时忽略折叠状态(搜索命中强制展开显示,已在循环内自然满足:
搜索非空时不跳过子行)。
## 6. 工作项(可分配给子代理的最小单元)
- **W1 Tier1 颜色组(6 节点)**:ColorCorrect/Gamma/Saturation/Invert/Clamp/Grade。
- **W2 Tier1 矩阵+卷积组(4 节点)**:ColorMatrix/EdgeDetect/Dilate/Erode
(+Tier2 的 Matrix3x3/5x5 若顺利一并)。
- **W3 Tier1 模糊/锐化组(2 节点)**:DirBlur/Sharpen。
- **W4 Tier1 合成组(4 节点)**:Dissolve/KeyMix/PreMult/Unpremult。
- **W5 Tier1 几何+生成器组(4~5 节点)**:Position/Mirror(或跳过)/CheckerBoard/
ColorBars/Ramp。
- **W6 分类与折叠 UI**:§5 全部(addable_effects 分组 + 特效库折叠 + 持久化 +
检查器子菜单 + i18n)。
- **W7 Tier2 批**:HSVTool/Quantize/Log2Lin/ClipTest/ColorLookup/GodRays
(W1-W6 完成并审查后再派)。
W1-W5 互相独立(不同文件),可并行派 5 个子代理;W6 独立;每个子代理须交付:
节点实现 + 单元测试 + GPU 像素测试 + `cargo test -p oak-node -p oak-render` 绿。
**统一禁令**:GLSL 不写 switch;不动 eval.rs/traverser 等管线文件(冲突根);
遵循 nodes/ 既有文件体例(GPL 头、CPP-PARITY 注释、输入常量文档)。
## 7. 验收标准
1. Tier1 全部节点出现在特效库对应分类下,可加到 clip,画面效果正确(GPU 测试
逐节点覆盖核心算法)。
2. 特效库分类可折叠,重启 app 折叠状态保留;检查器添加菜单按分类分组。
3. 搜索框在任何折叠状态下都能搜到特效。
4. `cargo test --workspace` 全绿。