120 lines
5.5 KiB
Rust
120 lines
5.5 KiB
Rust
//! Distort / stylize GPU effects vs the CPU effects (the oracle): see `fx_distort.rs`.
|
||
|
||
use effectcraft_keyframe::Value;
|
||
use effectcraft_project::BitDepth;
|
||
use effectcraft_render::RenderOpts;
|
||
use effectcraft_time::Tick;
|
||
|
||
use crate::tests::{Scene, check, compare_at, effect_case, n, opts, set};
|
||
|
||
fn e(v: u32) -> Value {
|
||
Value::Enum(v)
|
||
}
|
||
|
||
fn on() -> Value {
|
||
Value::Bool(true)
|
||
}
|
||
|
||
#[test]
|
||
fn twirl_bulge_ripple_wave_warp() {
|
||
effect_case("ec.distort.twirl", &[("angle", n(120.0)), ("radius", n(40.0))]);
|
||
effect_case("ec.distort.twirl", &[("angle", n(-400.0)), ("radius", n(70.0)), ("center", Value::Vec2([25.0, 18.0]))]);
|
||
effect_case("ec.distort.bulge", &[("hradius", n(30.0)), ("vradius", n(20.0)), ("height", n(1.8))]);
|
||
effect_case("ec.distort.bulge", &[("height", n(-2.5)), ("taperRadius", n(60.0)), ("pinAllEdges", on()), ("center", Value::Vec2([30.0, 25.0]))]);
|
||
effect_case("ec.distort.ripple", &[("radius", n(80.0)), ("waveWidth", n(9.0)), ("waveHeight", n(4.0))]);
|
||
effect_case("ec.distort.ripple", &[("conversion", e(1)), ("phase", n(70.0)), ("speed", n(3.0)), ("center", Value::Vec2([20.0, 30.0]))]);
|
||
effect_case("ec.distort.wavewarp", &[("height", n(6.0)), ("width", n(25.0)), ("direction", n(30.0))]);
|
||
effect_case("ec.distort.wavewarp", &[("waveType", e(2)), ("pinning", e(1)), ("phase", n(400.0)), ("speed", n(-2.0))]);
|
||
effect_case("ec.distort.wavewarp", &[("waveType", e(8)), ("pinning", e(2)), ("height", n(-5.0)), ("direction", n(200.0))]);
|
||
effect_case("ec.distort.wavewarp", &[("waveType", e(4)), ("pinning", e(7)), ("width", n(33.0))]);
|
||
}
|
||
|
||
#[test]
|
||
fn turbulent_displace_and_cc_lens() {
|
||
effect_case("ec.distort.turbulentdisplace", &[("size", n(30.0)), ("amount", n(20.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())],
|
||
);
|
||
effect_case(
|
||
"ec.distort.turbulentdisplace",
|
||
&[
|
||
("displacement", e(5)),
|
||
("evolutionOptions/cycleEvolution", on()),
|
||
("evolutionOptions/cycle", n(2.0)),
|
||
("evolution", n(500.0)),
|
||
("evolutionOptions/randomSeed", n(7.0)),
|
||
("pinning", e(0)),
|
||
("amount", n(-30.0)),
|
||
],
|
||
);
|
||
effect_case("ec.distort.turbulentdisplace", &[("displacement", e(8)), ("size", n(15.0)), ("pinning", e(6))]);
|
||
effect_case("ec.distort.cclens", &[("size", n(70.0))]);
|
||
effect_case("ec.distort.cclens", &[("size", n(45.0)), ("convergence", n(60.0)), ("center", Value::Vec2([30.0, 20.0]))]);
|
||
effect_case("ec.distort.cclens", &[("convergence", n(-70.0))]);
|
||
}
|
||
|
||
#[test]
|
||
fn mesh_warp() {
|
||
// 2 rows × 3 columns: 12 vertices.
|
||
let mesh = "0,0 0,0 0,0 0,0 0,0 6,-4 -5,3 0,0 0,0 0,0 0,0 0,0";
|
||
effect_case("ec.distort.meshwarp", &[("rows", n(2.0)), ("columns", n(3.0)), ("quality", n(3.0)), ("mesh", Value::Str(mesh.into()))]);
|
||
let mesh = "-4,-3 2,0 8,5 0,-2 9,9 1,0 -3,4 2,2 4,-6";
|
||
effect_case("ec.distort.meshwarp", &[("rows", n(2.0)), ("columns", n(2.0)), ("quality", n(5.0)), ("mesh", Value::Str(mesh.into()))]);
|
||
}
|
||
|
||
#[test]
|
||
fn mosaic_find_edges_emboss() {
|
||
effect_case("ec.stylize.mosaic", &[]);
|
||
effect_case("ec.stylize.mosaic", &[("horizontal", n(7.0)), ("vertical", n(3.0))]);
|
||
effect_case("ec.stylize.mosaic", &[("horizontal", n(13.0)), ("vertical", n(9.0)), ("sharpColors", on())]);
|
||
effect_case("ec.stylize.findedges", &[]);
|
||
effect_case("ec.stylize.findedges", &[("invert", on()), ("blend", n(30.0))]);
|
||
effect_case("ec.stylize.emboss", &[]);
|
||
effect_case("ec.stylize.emboss", &[("direction", n(160.0)), ("relief", n(4.0)), ("contrast", n(250.0)), ("blend", n(20.0))]);
|
||
}
|
||
|
||
#[test]
|
||
fn displacement_map_self() {
|
||
effect_case("ec.distort.displacementmap", &[("maxHorizontal", n(8.0)), ("maxVertical", n(-5.0))]);
|
||
effect_case("ec.distort.displacementmap", &[("useForHorizontal", e(4)), ("useForVertical", e(3)), ("wrapPixelsAround", on())]);
|
||
effect_case(
|
||
"ec.distort.displacementmap",
|
||
&[("useForHorizontal", e(10)), ("useForVertical", e(6)), ("maxVertical", n(12.0)), ("expandOutput", Value::Bool(false))],
|
||
);
|
||
}
|
||
|
||
/// Displacement Map reading another layer (Center / Stretch / Tile), composited.
|
||
#[test]
|
||
fn displacement_map_layer() {
|
||
for depth in [BitDepth::Bpc8, BitDepth::Bpc32] {
|
||
for (behavior, wrap) in [(0, false), (1, false), (2, true), (2, false)] {
|
||
let mut s = Scene::new(depth);
|
||
let bg = s.solid([0.15, 0.1, 0.2], 97, 61);
|
||
s.push(bg);
|
||
let mut map = s.footage(50, 36);
|
||
map.switches.video = false;
|
||
let mid = s.push(map);
|
||
let mut l = s.footage(70, 44);
|
||
s.effect(
|
||
&mut l,
|
||
"ec.distort.displacementmap",
|
||
&[
|
||
("displacementMapLayer", Value::Layer(Some(mid.0))),
|
||
("useForHorizontal", e(0)),
|
||
("useForVertical", e(4)),
|
||
("maxHorizontal", n(9.0)),
|
||
("maxVertical", n(6.0)),
|
||
("displacementMapBehavior", e(behavior)),
|
||
("wrapPixelsAround", Value::Bool(wrap)),
|
||
],
|
||
);
|
||
set(&mut l, "transform/rotation", Value::Scalar(8.0));
|
||
s.push(l);
|
||
let label = format!("displacement map {behavior} {wrap} {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);
|
||
}
|
||
}
|
||
}
|