Adjustment layers blend in their blend mode (#2618)

An adjustment layer replaced the comp below with its effects' result whatever its blend
mode. As in After Effects, a mode other than Normal now blends the adjusted comp onto the
comp below in that mode, inside the footprint, track matte and opacity (an adjustment
layer with no effects in Screen screens the comp with itself). CPU and GPU paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-30 11:43:19 +07:00
co-authored by Claude Opus 5.5
parent e56c916085
commit 94c8bde240
4 changed files with 54 additions and 4 deletions
+6
View File
@@ -510,6 +510,12 @@ fn layer_styles_collapsed_precomps_and_cpu_fallbacks() {
adj.switches.adjustment = true;
s.effect(&mut adj, "ec.channel.invert", &[]);
s.push(adj);
// An adjustment layer in another blend mode blends the adjusted comp in that mode (#2618).
let mut adj = s.solid([1.0, 1.0, 1.0], 70, 40);
adj.switches.adjustment = true;
adj.blend_mode = BlendMode::Screen;
set(&mut adj, "transform/opacity", Value::Scalar(60.0));
s.push(adj);
check(&format!("collapse + adjustment {depth:?}"), compare_at(&s, opts(), Tick::ZERO), 0.0);
}
}
+9 -3
View File
@@ -352,8 +352,8 @@ fn draw_precomp(e: &mut Enc, r: &Renderer, ctx: &EvalCtx, layer: &Layer, canvas:
/// Adjustment layer (`Renderer::draw_adjustment`): the effect stack runs on the comp below,
/// resident on the GPU (non-GPU effects read back, run on the CPU and upload), and the result
/// replaces the canvas inside the layer's footprint × track matte × opacity. `None` = draw it
/// on the CPU.
/// replaces the canvas inside the layer's footprint × track matte × opacity, or blends onto it in
/// the layer's blend mode when that isn't Normal. `None` = draw it on the CPU.
fn draw_adjustment(e: &mut Enc, r: &Renderer, ctx: &EvalCtx, layer: &Layer, canvas: &mut GpuImage) -> Option<()> {
let opacity = r.layer_opacity(ctx, layer);
let Some(foot) = r.adjustment_footprint(ctx, layer) else { return Some(()) };
@@ -379,7 +379,13 @@ fn draw_adjustment(e: &mut Enc, r: &Renderer, ctx: &EvalCtx, layer: &Layer, canv
if let Some(c) = pipe.to_blend() {
adjusted = ops::convert(e, &adjusted, &c);
}
*canvas = ops::adjust_mix(e, canvas, &adjusted, &matte, opacity);
*canvas = if layer.blend_mode == BlendMode::Normal {
ops::adjust_mix(e, canvas, &adjusted, &matte, opacity)
} else {
// The adjusted comp is a layer in that mode over the comp below (#2618).
let iso = ops::matte(e, &adjusted, &matte, effectcraft_project::MatteKind::Alpha);
ops::blend_full(e, canvas, &iso, layer.blend_mode, opacity, layer.id.0 as u32, None)
};
Some(())
}