mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-10 20:41:25 +00:00
Layer-space reads of a 3D text or shape layer get the whole layer (#1388)
Review: effects that take another layer as a parameter (Set Matte, Displacement Map, time effects…) read it through Renderer::nested in layer space, and the motion tracker reads layer_source; both could get only the part of the layer the frame shows. The nested renderer and layer_source now rasterise whole. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ba04ab70a0
commit
3ac9a82378
2 files changed
+33
-1
No files matched your search
@@ -766,6 +766,9 @@ impl<'a> Renderer<'a> {
|
||||
top: false,
|
||||
through: [None; MAX_THROUGH],
|
||||
through_lost: false,
|
||||
// Effects read other layers through it in layer space (layer parameters, Echo…):
|
||||
// they need the whole layer, not the part this frame shows (see `raster_clip`).
|
||||
whole_raster: true,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
@@ -1573,7 +1576,8 @@ impl<'a> Renderer<'a> {
|
||||
/// (what the motion tracker analyses, like After Effects' Layer panel). `None` for layers
|
||||
/// without pixels.
|
||||
pub fn layer_source(&self, ctx: &EvalCtx, layer: &Layer) -> Option<Buf> {
|
||||
self.source(ctx, layer)
|
||||
// The whole layer, not the part the frame shows (see `raster_clip`).
|
||||
Renderer { whole_raster: true, ..*self }.source(ctx, layer)
|
||||
}
|
||||
|
||||
/// Layer pixels after source → masks → effects (no layer styles).
|
||||
|
||||
@@ -268,6 +268,34 @@ fn a_camera_moving_any_way_renders_every_frame_as_the_whole_layer() {
|
||||
moving("text turning near the camera", &[(0.0, [cx, cy, z])], &still, &[(0.0, [cx, cy, z + 70.0])], &[(0.0, -70.0), (1.0, 70.0)]);
|
||||
}
|
||||
|
||||
/// Reads of a layer in its own space get the whole layer, not the part the frame shows: an effect
|
||||
/// taking another layer as a parameter (Set Matte, stretched to fit, from hidden text close to the
|
||||
/// camera), and the source the motion tracker analyses.
|
||||
#[test]
|
||||
fn layer_space_reads_get_the_whole_layer() {
|
||||
let (mut p, cid, comp) = setup();
|
||||
let mut text = text3(&mut p, &comp, [W as f64 / 2.0, H as f64 / 2.0, -zoom() + 40.0], 0.0);
|
||||
text.switches.video = false;
|
||||
let text_id = text.id;
|
||||
let sid =
|
||||
p.add_item("Solid", Label::Red, None, ItemKind::Solid(effectcraft_project::Solid { color: [0.2, 0.6, 1.0], width: W, height: H, pixel_aspect: 1.0 }));
|
||||
let mut solid = build::layer(&mut p, &comp, "Solid", LayerSource::Solid { item: sid }, (W, H), None);
|
||||
let spec = effectcraft_effects::find("ec.channel.setmatte").unwrap();
|
||||
let mut next = p.next_id;
|
||||
let mut g = effectcraft_effects::instantiate(spec, &mut Ids(&mut next), spec.name, [W as f64, H as f64]);
|
||||
p.next_id = next;
|
||||
g.prop_mut("takeMatteFromLayer").unwrap().value = Value::Layer(Some(text_id.0));
|
||||
solid.props.sub_mut("effects").unwrap().children.push(g.into());
|
||||
p.comp_mut(cid).unwrap().layers = vec![text, solid];
|
||||
assert_eq!(frame(&p, cid, false).data, frame(&p, cid, true).data, "Set Matte from the text");
|
||||
let r = Renderer::new(&p, &NoFootage, RenderOpts::default());
|
||||
let ctx = r.eval_ctx(cid, Tick::ZERO).unwrap();
|
||||
let layer = &p.comp(cid).unwrap().layers[0];
|
||||
let mut whole = Renderer::new(&p, &NoFootage, RenderOpts::default());
|
||||
whole.whole_raster = true;
|
||||
assert_eq!(r.layer_source(&ctx, layer).unwrap().img, whole.layer_source(&ctx, layer).unwrap().img, "the tracker's source");
|
||||
}
|
||||
|
||||
/// A layer whose pixels outside the frame can matter (an effect here) is rasterised whole.
|
||||
#[test]
|
||||
fn layers_with_effects_rasterise_whole() {
|
||||
|
||||
Reference in new issue
Block a user