mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-12 21:32:52 +00:00
#3470, #3472, #3473, #3474, #3475, #3476, #3477, #3480, #3483, #3484, #3487-#3491: test the ends of the new ranges on the GPU
CPU / GPU comparisons at the new ends for Venetian Blinds (width 1, width and feather 32000), Radial Wipe (feather 32000), Grid (border 2000), Scatter (1000), Beam (4000), Change Color (1710 degrees) and Turbulent Displace (seed 100000). The comparison counts infinity on both sides as equal, so Levels (Individual Controls) gets a direct check that the GPU's output is finite at the ends of its ranges. The Noise HLS test asserts the spec's ranges, so it fails without them.
This commit is contained in:
6 files changed
+49
No files matched your search
@@ -978,6 +978,10 @@ mod tests {
|
||||
*p = premul([0.6, 0.3, (i % 7) as f32 / 7.0], 1.0);
|
||||
}
|
||||
for id in ["ec.noise.noisehls", "ec.noise.noisehlsauto"] {
|
||||
for (param, lo, hi) in [("hue", 0.0, 1000.0), ("lightness", 0.0, 1000.0), ("saturation", 0.0, 1000.0), ("grainSize", 0.0, 100.0)] {
|
||||
let ui = &crate::find(id).unwrap().params.iter().find(|p| p.id == param).unwrap().ui;
|
||||
assert!(matches!(ui, ParamUi::Slider { min, max, .. } if *min == lo && *max == hi), "{id} {param}: {ui:?}");
|
||||
}
|
||||
let at = |amount: f64, grain: f64| {
|
||||
let vals =
|
||||
[("noise", Value::Enum(2)), ("hue", num(amount)), ("lightness", num(amount)), ("saturation", num(amount)), ("grainSize", num(grain))];
|
||||
|
||||
@@ -38,6 +38,8 @@ fn twirl_bulge_ripple_wave_warp() {
|
||||
#[test]
|
||||
fn turbulent_displace_and_cc_lens() {
|
||||
effect_case("ec.distort.turbulentdisplace", &[("size", n(30.0)), ("amount", n(20.0))]);
|
||||
// #3470: After Effects' maximum Random Seed.
|
||||
effect_case("ec.distort.turbulentdisplace", &[("size", n(30.0)), ("amount", n(20.0)), ("evolutionOptions/randomSeed", n(100000.0))]);
|
||||
effect_case(
|
||||
"ec.distort.turbulentdisplace",
|
||||
&[("displacement", e(1)), ("complexity", n(3.5)), ("evolution", n(90.0)), ("size", n(25.0)), ("pinning", e(2)), ("resizeLayer", on())],
|
||||
|
||||
@@ -40,6 +40,8 @@ fn closed_form() {
|
||||
env_case("ec.generate.beam", &[]);
|
||||
env_case("ec.generate.beam", &[("length", n(70.0)), ("time", n(40.0)), ("softness", n(0.0)), ("perspective3d", off()), ("compositeOnOriginal", off())]);
|
||||
env_case("ec.generate.beam", &[("startThickness", n(3.0)), ("endThickness", n(20.0)), ("insideColor", c(0.3, 0.9, 1.0))]);
|
||||
// #3475: After Effects' maximum thickness.
|
||||
env_case("ec.generate.beam", &[("startThickness", n(0.0)), ("endThickness", n(4000.0))]);
|
||||
env_case("ec.generate.lensflare", &[]);
|
||||
env_case("ec.generate.lensflare", &[("lensType", e(1)), ("flareCenter", pt(50.0, 30.0)), ("blendWithOriginal", n(30.0))]);
|
||||
env_case("ec.generate.lensflare", &[("lensType", e(2)), ("flareBrightness", n(160.0))]);
|
||||
|
||||
@@ -83,6 +83,11 @@ fn wipes() {
|
||||
effect_case("ec.transition.radialwipe", &[("completion", n(45.0)), ("wipe", e(1)), ("center", pt(30.2, 19.6))]);
|
||||
effect_case("ec.transition.radialwipe", &[("completion", n(60.0)), ("wipe", e(2)), ("startAngle", n(-40.0)), ("feather", n(3.0))]);
|
||||
effect_case("ec.transition.radialwipe", &[("completion", n(0.0)), ("feather", n(20.0))]);
|
||||
// #3472-#3474: the ends of After Effects' ranges (a Feather wider than 8 blinds is the CPU's
|
||||
// even veil).
|
||||
effect_case("ec.transition.venetian", &[("completion", n(40.0)), ("width", n(1.0)), ("feather", n(6.0))]);
|
||||
effect_case("ec.transition.venetian", &[("completion", n(40.0)), ("width", n(32000.0)), ("feather", n(32000.0))]);
|
||||
effect_case("ec.transition.radialwipe", &[("completion", n(40.0)), ("feather", n(32000.0))]);
|
||||
effect_case("ec.transition.gradientwipe", &[("completion", n(40.0))]);
|
||||
effect_case("ec.transition.gradientwipe", &[("completion", n(55.0)), ("softness", n(30.0)), ("invert", b(true))]);
|
||||
effect_case("ec.transition.gradientwipe", &[("completion", n(100.0))]);
|
||||
@@ -147,6 +152,8 @@ fn generators() {
|
||||
);
|
||||
effect_case("ec.generate.checkerboard", &[("sizeFrom", e(0)), ("corner", pt(16.0, 11.0)), ("color", c(0.9, 0.3, 0.1)), ("blendingMode", e(1))]);
|
||||
effect_case("ec.generate.grid", &[("width", n(12.0)), ("border", n(3.0))]);
|
||||
// #3476: a border wider than the cells (After Effects' maximum).
|
||||
effect_case("ec.generate.grid", &[("width", n(12.0)), ("border", n(2000.0))]);
|
||||
effect_case(
|
||||
"ec.generate.grid",
|
||||
&[
|
||||
|
||||
@@ -109,6 +109,8 @@ fn arbitrary_map_signed_fractional_and_near_zero_wraps() {
|
||||
#[test]
|
||||
fn scatter_brush_strokes() {
|
||||
effect_case("ec.stylize.scatter", &[("amount", n(5.0))]);
|
||||
// #3477: After Effects' maximum, far beyond the layer.
|
||||
effect_case("ec.stylize.scatter", &[("amount", n(1000.0))]);
|
||||
effect_case("ec.stylize.scatter", &[("amount", n(3.0)), ("grain", e(1))]);
|
||||
effect_case("ec.stylize.scatter", &[("amount", n(7.0)), ("grain", e(2)), ("randomizeEveryFrame", on())]);
|
||||
effect_case("ec.stylize.brushstrokes", &[]);
|
||||
|
||||
@@ -81,6 +81,8 @@ fn colour_replacement() {
|
||||
&[("amount", n(100.0)), ("color", c(0.8, 0.4, 0.3)), ("matchColors", e(1)), ("tolerance", n(5.0)), ("edgeSoftness", n(30.0))],
|
||||
);
|
||||
effect_case("ec.color.changecolor", &[("hueTransform", n(90.0)), ("colorToChange", c(0.7, 0.5, 0.4)), ("matchingSoftness", n(20.0))]);
|
||||
// #3480: near the top of After Effects' range (four and three quarter turns).
|
||||
effect_case("ec.color.changecolor", &[("hueTransform", n(1710.0)), ("colorToChange", c(0.7, 0.5, 0.4)), ("matchingSoftness", n(20.0))]);
|
||||
effect_case(
|
||||
"ec.color.changecolor",
|
||||
&[
|
||||
@@ -199,3 +201,33 @@ fn color_stabilizer() {
|
||||
fn gradient_ramp_matches_the_cpu() {
|
||||
effect_case("ec.generate.gradientramp", &[]);
|
||||
}
|
||||
|
||||
/// #3487-#3491: at the ends of the valid ranges the GPU's Levels (Individual Controls) output is
|
||||
/// finite (the CPU / GPU comparison counts infinity on both sides as equal).
|
||||
#[test]
|
||||
fn levels_ic_is_finite_at_the_ends_of_its_ranges() {
|
||||
let Some(g) = crate::tests::gpu() else { return };
|
||||
let spec = effectcraft_effects::find("ec.color.levelsic").unwrap();
|
||||
let size = [16.0, 8.0];
|
||||
let mut params =
|
||||
effectcraft_effects::Params { values: spec.params.iter().map(|ps| (ps.id.to_string(), effectcraft_effects::default_value(ps, size))).collect() };
|
||||
for (k, v) in [
|
||||
("rgb/rgbInWhite", n(0.2)),
|
||||
("rgb/rgbGamma", n(0.0)),
|
||||
("red/redOutBlack", n(-10000.0)),
|
||||
("blue/blueOutWhite", n(10000.0)),
|
||||
("green/greenOutWhite", n(0.0)),
|
||||
("clipToOutputWhite", e(0)),
|
||||
] {
|
||||
params.values.insert(k.to_string(), v);
|
||||
}
|
||||
let mut img = crate::tests::pattern(7, 16, 8);
|
||||
for p in &mut img.data {
|
||||
*p = p.map(|v| v * 3.0);
|
||||
}
|
||||
let buf = effectcraft_effects::Buf { img, offset: [0.0, 0.0], scale: 1.0 };
|
||||
let ctx = effectcraft_effects::EffectCtx { params: ¶ms, time: 0.0, layer_size: size, seed: 1, adjustment: false, env: Default::default() };
|
||||
let out = effectcraft_render::Accelerator::effects(g, &[effectcraft_render::FxStep { spec, ctx }], &buf, None)
|
||||
.expect("the GPU runs Levels (Individual Controls)");
|
||||
assert!(out.img.data.iter().flatten().all(|v| v.is_finite()), "{:?}", out.img.data.iter().find(|p| p.iter().any(|v| !v.is_finite())));
|
||||
}
|
||||
Reference in new issue
Block a user