effectcraft/crates/gpu/src/tests_fx_generate.rs

201 lines
8.2 KiB
Rust

//! GPU vs CPU for the blur, transition and generate family (`fx_generate`).
use effectcraft_keyframe::Value;
use effectcraft_project::BitDepth;
use effectcraft_render::RenderOpts;
use effectcraft_time::Tick;
use crate::tests::{Scene, c, check, compare_at, effect_case, n, opts, set};
fn e(v: u32) -> Value {
Value::Enum(v)
}
fn b(v: bool) -> Value {
Value::Bool(v)
}
fn pt(x: f64, y: f64) -> Value {
Value::Vec2([x, y])
}
#[test]
fn radial_blur() {
effect_case("ec.blur.radial", &[("amount", n(12.0))]);
effect_case("ec.blur.radial", &[("amount", n(30.0)), ("type", e(1)), ("center", pt(20.3, 14.7))]);
effect_case("ec.blur.radial", &[("amount", n(-45.0)), ("center", pt(50.0, 30.0))]);
}
#[test]
fn cc_radial_fast_blur() {
effect_case("ec.blur.ccradialfast", &[("amount", n(40.0))]);
effect_case("ec.blur.ccradialfast", &[("amount", n(70.0)), ("zoom", e(1)), ("center", pt(22.4, 16.1))]);
effect_case("ec.blur.ccradialfast", &[("amount", n(25.0)), ("zoom", e(2))]);
}
#[test]
fn camera_lens_blur() {
effect_case("ec.blur.cameralens", &[("blurRadius", n(5.0))]);
effect_case(
"ec.blur.cameralens",
&[
("blurRadius", n(7.5)),
("irisProperties/irisShape", e(2)),
("irisProperties/irisRotation", n(20.0)),
("irisProperties/irisAspectRatio", n(1.6)),
("repeatEdge", b(true)),
],
);
effect_case(
"ec.blur.cameralens",
&[
("blurRadius", n(4.0)),
("irisProperties/irisShape", e(8)),
("highlight/specularBrightness", n(60.0)),
("highlight/specularThreshold", n(150.0)),
("highlight/highlightSaturation", n(40.0)),
("useLinear", b(true)),
],
);
// Large iris: per-row prefix sums.
effect_case("ec.blur.cameralens", &[("blurRadius", n(14.0)), ("irisProperties/irisRoundness", n(60.0))]);
effect_case("ec.blur.cameralens", &[("blurRadius", n(12.0)), ("repeatEdge", b(true)), ("useLinear", b(true))]);
}
#[test]
fn wipes() {
effect_case("ec.transition.linearwipe", &[("completion", n(40.0)), ("angle", n(30.0)), ("feather", n(12.0))]);
effect_case("ec.transition.linearwipe", &[("completion", n(55.0)), ("angle", n(-120.0))]);
effect_case("ec.transition.linearwipe", &[("completion", n(20.0)), ("angle", n(90.0)), ("feather", n(3.0))]);
effect_case("ec.transition.venetian", &[("completion", n(35.0)), ("direction", n(30.0)), ("width", n(11.0)), ("feather", n(2.0))]);
effect_case("ec.transition.venetian", &[("completion", n(60.0)), ("width", n(17.0))]);
effect_case("ec.transition.venetian", &[("completion", n(25.0)), ("direction", n(-70.0)), ("width", n(9.0)), ("feather", n(0.5))]);
effect_case("ec.transition.radialwipe", &[("completion", n(30.0)), ("startAngle", n(25.0)), ("feather", n(10.0))]);
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))]);
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))]);
}
/// Gradient Wipe driven by another layer (fetched through the effect host, placed on the CPU).
#[test]
fn gradient_wipe_with_a_gradient_layer() {
for depth in [BitDepth::Bpc8, BitDepth::Bpc32] {
for placement in 0..3 {
let mut s = Scene::new(depth);
let bg = s.solid([0.15, 0.1, 0.2], 97, 61);
s.push(bg);
let grad = s.footage(40, 30);
let gid = s.push(grad);
let mut l = s.footage(70, 44);
s.effect(
&mut l,
"ec.transition.gradientwipe",
&[("completion", n(45.0)), ("softness", n(20.0)), ("gradientLayer", Value::Layer(Some(gid.0))), ("gradientPlacement", e(placement))],
);
set(&mut l, "transform/rotation", Value::Scalar(8.0));
s.push(l);
let label = format!("gradient wipe layer {placement} {depth:?}");
check(&label, compare_at(&s, opts(), Tick::ZERO), 0.0);
check(&format!("{label} half"), compare_at(&s, RenderOpts { scale: 0.5, ..opts() }, Tick::ZERO), 0.0);
}
}
}
#[test]
fn generators() {
effect_case("ec.generate.cellpattern", &[("size", n(14.0))]);
effect_case("ec.generate.cellpattern", &[("cellPattern", e(2)), ("size", n(11.0)), ("evolution", n(130.0)), ("overflow", e(1)), ("contrast", n(150.0))]);
effect_case(
"ec.generate.cellpattern",
&[
("cellPattern", e(11)),
("size", n(9.0)),
("tilingOptions/enableTiling", b(true)),
("tilingOptions/cellsHorizontal", n(4.0)),
("tilingOptions/cellsVertical", n(3.0)),
("overflow", e(2)),
("contrast", n(250.0)),
("invert", b(true)),
("evolutionOptions/randomSeed", n(17.0)),
],
);
effect_case("ec.generate.cellpattern", &[("cellPattern", e(5)), ("size", n(16.0)), ("disperse", n(0.6)), ("offset", pt(3.3, -7.1))]);
effect_case("ec.generate.checkerboard", &[("width", n(9.0))]);
effect_case(
"ec.generate.checkerboard",
&[
("sizeFrom", e(2)),
("width", n(13.0)),
("height", n(7.0)),
("feather/featherWidth", n(4.0)),
("anchor", pt(5.3, 2.2)),
("blendingMode", e(5)),
("opacity", n(70.0)),
],
);
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))]);
effect_case(
"ec.generate.grid",
&[
("sizeFrom", e(2)),
("width", n(15.0)),
("height", n(9.0)),
("border", n(2.5)),
("feather/featherWidth", n(3.0)),
("feather/featherHeight", n(2.0)),
("invertGrid", b(true)),
("blendingMode", e(4)),
],
);
effect_case(
"ec.generate.grid",
&[("sizeFrom", e(0)), ("corner", pt(11.0, 8.0)), ("anchor", pt(2.5, 3.5)), ("blendingMode", e(14)), ("color", c(0.2, 0.8, 0.4))],
);
effect_case("ec.generate.fourcolor", &[]);
effect_case("ec.generate.fourcolor", &[("blend", n(40.0)), ("jitter", n(50.0)), ("opacity", n(80.0)), ("blendingMode", e(3))]);
effect_case("ec.generate.fourcolor", &[("blend", n(600.0)), ("blendingMode", e(16)), ("positionsColors/point2", pt(30.0, 20.0))]);
}
#[test]
fn noise_and_grain() {
effect_case("ec.noise.noise", &[("amount", n(30.0))]);
effect_case("ec.noise.noise", &[("amount", n(50.0)), ("color", b(false))]);
effect_case("ec.noise.noise", &[("amount", n(40.0)), ("clip", b(false))]);
effect_case("ec.noise.addgrain", &[("tweaking/intensity", n(2.0))]);
effect_case(
"ec.noise.addgrain",
&[
("tweaking/intensity", n(3.0)),
("tweaking/size", n(2.5)),
("tweaking/softness", n(1.5)),
("tweaking/aspectRatio", n(1.4)),
("tweaking/channelSize/redSize", n(0.6)),
("color/saturation", n(0.5)),
("color/tintAmount", n(0.4)),
("color/tintColor", c(1.0, 0.6, 0.2)),
("application/blendingMode", e(4)),
],
);
effect_case(
"ec.noise.addgrain",
&[
("tweaking/intensity", n(1.5)),
("color/monochromatic", b(true)),
("application/blendingMode", e(3)),
("application/shadows", n(0.3)),
("application/highlights", n(1.8)),
("application/midpoint", n(0.35)),
("animation/randomSeed", n(42.0)),
("animation/animationSpeed", n(2.0)),
],
);
effect_case(
"ec.noise.addgrain",
&[("tweaking/intensity", n(2.0)), ("application/blendingMode", e(1)), ("tweaking/channelIntensities/blueIntensity", n(2.5))],
);
}