mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 13:37:37 -06:00
fix(render): preserve preceding effects in GPU Echo (#1120)
This commit is contained in:
@@ -203,6 +203,28 @@ fn echo_and_posterize_time() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn echo_after_star_burst_preserves_the_stars() {
|
||||
for depth in [BitDepth::Bpc8, BitDepth::Bpc32] {
|
||||
for operator in 0..7 {
|
||||
for posterize in [false, true] {
|
||||
let mut s = Scene::new(depth);
|
||||
let mut l = s.solid([1.0; 3], 97, 61);
|
||||
s.effect(&mut l, "ec.sim.ccstarburst", &[("gridSpacing", n(8.0)), ("size", n(40.0))]);
|
||||
s.effect(&mut l, "ec.time.echo", &[("numberOfEchoes", n(2.0)), ("echoTime", n(-0.1)), ("decay", n(0.6)), ("echoOperator", e(operator))]);
|
||||
if posterize {
|
||||
s.effect(&mut l, "ec.time.posterizetime", &[("frameRate", n(4.0))]);
|
||||
}
|
||||
s.push(l);
|
||||
let t = Tick::from_seconds_f64(0.6);
|
||||
let label = format!("Star Burst + Echo {operator} posterize={posterize} {depth:?}");
|
||||
check(&label, compare_at(&s, opts(), t), 0.0);
|
||||
check(&format!("{label} half"), compare_at(&s, RenderOpts { scale: 0.5, ..opts() }, t), 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn median_levels_match_cpu_division() {
|
||||
let Some(g) = crate::tests::gpu() else { return };
|
||||
|
||||
@@ -216,7 +216,7 @@ struct FxHost<'r, 'a, 'c> {
|
||||
/// whose effects run on the comp below).
|
||||
origin: [f64; 2],
|
||||
/// Index of the effect being rendered (bounds `self_at` to effects before it).
|
||||
index: std::sync::atomic::AtomicUsize,
|
||||
index: usize,
|
||||
original: Option<&'c Buf>,
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ impl EffectHost for FxHost<'_, '_, '_> {
|
||||
if self.r.depth > MAX_FX_DEPTH || self.layer.switches.adjustment {
|
||||
return None;
|
||||
}
|
||||
let n = effects.min(self.index.load(std::sync::atomic::Ordering::Relaxed));
|
||||
let n = effects.min(self.index);
|
||||
let t = self.layer.comp_time(Tick::from_seconds_f64(layer_time));
|
||||
let sub = self.r.nested();
|
||||
sub.layer_input(&self.ctx.at(t), self.layer, n).map(|b| (*b).clone())
|
||||
@@ -337,8 +337,7 @@ impl EffectHost for FxHost<'_, '_, '_> {
|
||||
}
|
||||
|
||||
fn params_at(&self, layer_time: f64) -> Option<Params> {
|
||||
let i = self.index.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let g = self.layer.effects()?.groups().nth(i)?;
|
||||
let g = self.layer.effects()?.groups().nth(self.index)?;
|
||||
let ctx = self.ctx.at(self.layer.comp_time(Tick::from_seconds_f64(layer_time)));
|
||||
Some(effectcraft_effects::flatten_params(g, &mut |pr| ctx.value(self.layer, pr)))
|
||||
}
|
||||
@@ -1158,7 +1157,7 @@ impl<'a> Renderer<'a> {
|
||||
buf
|
||||
});
|
||||
}
|
||||
let host = FxHost { r: self, ctx, layer, origin, index: Default::default(), original: original.as_ref() };
|
||||
let host = FxHost { r: self, ctx, layer, origin, index: 0, original: original.as_ref() };
|
||||
let env = EffectEnv {
|
||||
masks: &mask_shapes,
|
||||
host: Some(&host),
|
||||
@@ -1192,12 +1191,21 @@ impl<'a> Renderer<'a> {
|
||||
{
|
||||
let run: Vec<_> = stack[k..].iter().take_while(|(_, _, s)| s.gpu && a.supports_effect(s.id)).collect();
|
||||
let params: Vec<Params> = run.iter().map(|(_, g, _)| self.effect_params(ctx, layer, g)).collect();
|
||||
let hosts: Vec<_> = run.iter().map(|(i, _, _)| FxHost { index: *i, ..host }).collect();
|
||||
let steps: Vec<FxStep> = run
|
||||
.iter()
|
||||
.zip(¶ms)
|
||||
.map(|((i, g, s), params)| FxStep {
|
||||
.zip(&hosts)
|
||||
.map(|(((i, g, s), params), host)| FxStep {
|
||||
spec: s,
|
||||
ctx: EffectCtx { params, time: lt.seconds(), layer_size, seed: g.uid as u32, adjustment, env: EffectEnv { effect_index: *i, ..env } },
|
||||
ctx: EffectCtx {
|
||||
params,
|
||||
time: lt.seconds(),
|
||||
layer_size,
|
||||
seed: g.uid as u32,
|
||||
adjustment,
|
||||
env: EffectEnv { host: Some(host), effect_index: *i, ..env },
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
let t0 = web_time::Instant::now();
|
||||
@@ -1212,8 +1220,8 @@ impl<'a> Renderer<'a> {
|
||||
}
|
||||
k += 1;
|
||||
let params = self.effect_params(ctx, layer, g);
|
||||
host.index.store(i, std::sync::atomic::Ordering::Relaxed);
|
||||
let env = EffectEnv { effect_index: i, ..env };
|
||||
let host = FxHost { index: i, ..host };
|
||||
let env = EffectEnv { host: Some(&host), effect_index: i, ..env };
|
||||
let ectx = EffectCtx { params: ¶ms, time: lt.seconds(), layer_size, seed: g.uid as u32, adjustment, env };
|
||||
let t0 = web_time::Instant::now();
|
||||
target.cpu(&mut |buf| {
|
||||
|
||||
Reference in New Issue
Block a user