201 lines
8.2 KiB
Rust
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))],
|
|
);
|
|
}
|