Add a inverse flag to LumaMixEffect.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 27 Mar 2014 00:38:43 +0000 (01:38 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 27 Mar 2014 00:38:43 +0000 (01:38 +0100)
This is mainly a convenience so that you can change e.g. a left-to-right
wipe into a right-to-left wipe without having to add a separate inverting
effect to the luma. Suggested by Dan Dennedy.

luma_mix_effect.cpp
luma_mix_effect.frag
luma_mix_effect.h
luma_mix_effect_test.cpp

index e34d87f..92c599e 100644 (file)
@@ -7,10 +7,11 @@ using namespace std;
 namespace movit {
 
 LumaMixEffect::LumaMixEffect()
-       : transition_width(1.0f), progress(0.5f)
+       : transition_width(1.0f), progress(0.5f), inverse(0)
 {
        register_float("transition_width", &transition_width);
        register_float("progress", &progress);
+       register_int("inverse", &inverse);
 }
 
 string LumaMixEffect::output_fragment_shader()
@@ -22,6 +23,7 @@ void LumaMixEffect::set_gl_state(GLuint glsl_program_num, const string &prefix,
 {
        Effect::set_gl_state(glsl_program_num, prefix, sampler_num);
        set_uniform_float(glsl_program_num, prefix, "progress_mul_w_plus_one", progress * (transition_width + 1.0));
+       set_uniform_int(glsl_program_num, prefix, "inverse", inverse);
 }
 
 }  // namespace movit
index bf0833e..709d192 100644 (file)
@@ -1,4 +1,5 @@
 uniform float PREFIX(progress_mul_w_plus_one);
+uniform bool PREFIX(inverse);
 
 vec4 FUNCNAME(vec2 tc) {
        vec4 first = INPUT1(tc);
@@ -36,8 +37,11 @@ vec4 FUNCNAME(vec2 tc) {
        // So clearly, it should move (w+1) units to the right, and apart from that
        // just stay a simple mapping.
        float w = PREFIX(transition_width);
-       float luma = INPUT3(tc).x * w;
-       float m = clamp((luma - w) + PREFIX(progress_mul_w_plus_one), 0.0, 1.0);
+       float luma = INPUT3(tc).x;
+       if (PREFIX(inverse)) {
+               luma = 1.0f - luma;
+       }
+       float m = clamp((luma * w - w) + PREFIX(progress_mul_w_plus_one), 0.0, 1.0);
 
        return mix(first, second, m);
 }
index 8bd3c50..ce890df 100644 (file)
@@ -2,8 +2,10 @@
 #define _MOVIT_LUMA_MIX_EFFECT_H 1
 
 // Fade between two images based on a third monochrome one; lighter pixels
-// will be faded before darker pixels. This allows a wide range of different
-// video wipes implemented using a single effect.
+// will be faded before darker pixels (unless the inverse flag is set,
+// in which case darker pixels will be faded before lighter pixels).
+// This allows a wide range of different video wipes implemented using
+// a single effect.
 //
 // Note that despite the name, the third input's _red_ channel is what's used
 // for transitions; there is no luma calculation done. If you need that,
@@ -28,6 +30,7 @@ public:
 
 private:
        float transition_width, progress;
+       int inverse;  // 0 or 1.
 };
 
 }  // namespace movit
index 618b733..07829cc 100644 (file)
@@ -96,4 +96,44 @@ TEST(LumaMixEffectTest, SoftWipeHalfWayThrough) {
        expect_equal(expected_data, out_data, 2, 2);
 }
 
+TEST(LumaMixEffectTest, Inverse) {
+       float data_a[] = {
+               0.0f, 0.25f,
+               0.75f, 1.0f,
+       };
+       float data_b[] = {
+               1.0f, 0.5f,
+               0.65f, 0.6f,
+       };
+       float data_luma[] = {
+               0.0f, 0.25f,
+               0.5f, 0.75f,
+       };
+
+       EffectChainTester tester(data_a, 2, 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       Effect *input1 = tester.get_chain()->last_added_effect();
+       Effect *input2 = tester.add_input(data_b, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       Effect *input3 = tester.add_input(data_luma, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+
+       Effect *luma_mix_effect = tester.get_chain()->add_effect(new LumaMixEffect(), input1, input2, input3);
+       ASSERT_TRUE(luma_mix_effect->set_float("transition_width", 100000.0f));
+       ASSERT_TRUE(luma_mix_effect->set_int("inverse", 1));
+
+       // Inverse is not the same as reverse, so progress=0 should behave identically
+       // as HardWipe, ie. everything should be from A.
+       float out_data[4];
+       ASSERT_TRUE(luma_mix_effect->set_float("progress", 0.0f));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(data_a, out_data, 2, 2);
+
+       // Lower two from A, the rest from B.
+       float expected_data_049[] = {
+               1.0f, 0.5f,
+               0.75f, 1.0f,
+       };
+       ASSERT_TRUE(luma_mix_effect->set_float("progress", 0.49f));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data_049, out_data, 2, 2);
+}
+
 }  // namespace movit