From: Steinar H. Gunderson Date: Fri, 5 Oct 2012 10:43:35 +0000 (+0200) Subject: Add a diffusion effect, and hook it up in the GUI. X-Git-Tag: 1.0~384 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=05ae48a62f4a507c1eef75b9220f88f2b9fda563 Add a diffusion effect, and hook it up in the GUI. --- diff --git a/Makefile b/Makefile index 1b6bdd5..e17e229 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX=g++ CXXFLAGS=-Wall -g LDFLAGS=-lSDL -lSDL_image -lGL OBJS=main.o util.o widgets.o effect.o effect_chain.o -OBJS += lift_gamma_gain_effect.o gamma_expansion_effect.o gamma_compression_effect.o colorspace_conversion_effect.o saturation_effect.o vignette_effect.o mirror_effect.o blur_effect.o sandbox_effect.o +OBJS += lift_gamma_gain_effect.o gamma_expansion_effect.o gamma_compression_effect.o colorspace_conversion_effect.o saturation_effect.o vignette_effect.o mirror_effect.o blur_effect.o diffusion_effect.o sandbox_effect.o test: $(OBJS) $(CXX) -o test $(OBJS) $(LDFLAGS) diff --git a/diffusion_effect.cpp b/diffusion_effect.cpp new file mode 100644 index 0000000..cf3188b --- /dev/null +++ b/diffusion_effect.cpp @@ -0,0 +1,46 @@ +#include +#include + +#include "diffusion_effect.h" +#include "blur_effect.h" +#include "effect_chain.h" +#include "util.h" + +DiffusionEffect::DiffusionEffect() + : blur(new BlurEffect), + overlay_matte(new OverlayMatteEffect) +{ +} + +std::string DiffusionEffect::output_fragment_shader() +{ + return read_file("sandbox_effect.frag"); +} + +void DiffusionEffect::add_self_to_effect_chain(EffectChain *chain, const std::vector &inputs) { + assert(inputs.size() == 1); + blur->add_self_to_effect_chain(chain, inputs); + + std::vector overlay_matte_inputs; + overlay_matte_inputs.push_back(inputs[0]); + overlay_matte_inputs.push_back(chain->get_last_added_effect()); // FIXME + overlay_matte->add_self_to_effect_chain(chain, overlay_matte_inputs); +} + +bool DiffusionEffect::set_float(const std::string &key, float value) { + if (key == "blurred_mix_amount") { + return overlay_matte->set_float(key, value); + } + return blur->set_float(key, value); +} + +OverlayMatteEffect::OverlayMatteEffect() + : blurred_mix_amount(0.3f) +{ + register_float("blurred_mix_amount", &blurred_mix_amount); +} + +std::string OverlayMatteEffect::output_fragment_shader() +{ + return read_file("overlay_matte_effect.frag"); +} diff --git a/diffusion_effect.h b/diffusion_effect.h new file mode 100644 index 0000000..4223d22 --- /dev/null +++ b/diffusion_effect.h @@ -0,0 +1,47 @@ +#ifndef _DIFFUSION_EFFECT_H +#define _DIFFUSION_EFFECT_H 1 + +// There are many different effects that go under the name of "diffusion", +// seemingly all of the inspired by the effect you get when you put a +// diffusion filter in front of your camera lens. The effect most people +// want is a general flattening/smoothing of the light, and reduction of +// fine detail (most notably, blemishes in people's skin), without ruining +// edges, which a regular blur would do. +// +// We do a relatively simple version, sometimes known as "white diffusion", +// where we first blur the picture, and then overlay it on the original +// using the original as a matte. + +#include "effect.h" + +class BlurEffect; +class OverlayMatteEffect; + +class DiffusionEffect : public Effect { +public: + DiffusionEffect(); + std::string output_fragment_shader(); + + virtual void add_self_to_effect_chain(EffectChain *chain, const std::vector &input); + virtual bool set_float(const std::string &key, float value); + +private: + BlurEffect *blur; + OverlayMatteEffect *overlay_matte; +}; + +// Used internally by DiffusionEffect; combines the blurred and the original +// version using the original as a matte. +class OverlayMatteEffect : public Effect { +public: + OverlayMatteEffect(); + std::string output_fragment_shader(); + + unsigned num_inputs() const { return 2; } + +private: + float blurred_mix_amount; +}; + + +#endif // !defined(_DIFFUSION_EFFECT_H) diff --git a/effect_chain.cpp b/effect_chain.cpp index 1244ecb..fdc08cf 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -21,6 +21,7 @@ #include "mirror_effect.h" #include "vignette_effect.h" #include "blur_effect.h" +#include "diffusion_effect.h" EffectChain::EffectChain(unsigned width, unsigned height) : width(width), @@ -81,6 +82,8 @@ Effect *instantiate_effect(EffectId effect) return new VignetteEffect(); case EFFECT_BLUR: return new BlurEffect(); + case EFFECT_DIFFUSION: + return new DiffusionEffect(); } assert(false); } diff --git a/effect_id.h b/effect_id.h index bed27f5..545a7be 100644 --- a/effect_id.h +++ b/effect_id.h @@ -16,6 +16,7 @@ enum EffectId { EFFECT_MIRROR, EFFECT_VIGNETTE, EFFECT_BLUR, + EFFECT_DIFFUSION, }; #endif // !defined(_EFFECT_ID_H) diff --git a/main.cpp b/main.cpp index abc0a38..bbc7752 100644 --- a/main.cpp +++ b/main.cpp @@ -33,9 +33,10 @@ float gamma_theta = 0.0f, gamma_rad = 0.0f, gamma_v = 0.5f; float gain_theta = 0.0f, gain_rad = 0.0f, gain_v = 0.25f; float saturation = 1.0f; -float radius = 0.3f; -float inner_radius = 0.3f; -float blur_radius = 3.0f; +//float radius = 0.3f; +// float inner_radius = 0.3f; +float blur_radius = 20.0f; +float blurred_mix_amount = 0.5f; void update_hsv(Effect *lift_gamma_gain_effect, Effect *saturation_effect) { @@ -72,12 +73,16 @@ void mouse(int x, int y) read_colorwheel(xf, yf - 0.4f, &gain_rad, &gain_theta, &gain_v); } else if (yf >= 0.6f && yf < 0.62f && xf < 0.2f) { saturation = (xf / 0.2f) * 4.0f; +#if 0 } else if (yf >= 0.65f && yf < 0.67f && xf < 0.2f) { radius = (xf / 0.2f); } else if (yf >= 0.70f && yf < 0.72f && xf < 0.2f) { inner_radius = (xf / 0.2f); +#endif } else if (yf >= 0.75f && yf < 0.77f && xf < 0.2f) { blur_radius = (xf / 0.2f) * 100.0f; + } else if (yf >= 0.80f && yf < 0.82f && xf < 0.2f) { + blurred_mix_amount = (xf / 0.2f); } } @@ -162,8 +167,8 @@ int main(int argc, char **argv) chain.add_input(inout_format); Effect *lift_gamma_gain_effect = chain.add_effect(EFFECT_LIFT_GAMMA_GAIN); Effect *saturation_effect = chain.add_effect(EFFECT_SATURATION); - Effect *blur_effect = chain.add_effect(EFFECT_BLUR); - Effect *vignette_effect = chain.add_effect(EFFECT_VIGNETTE); + Effect *diffusion_effect = chain.add_effect(EFFECT_DIFFUSION); + //Effect *vignette_effect = chain.add_effect(EFFECT_VIGNETTE); //Effect *sandbox_effect = chain.add_effect(EFFECT_SANDBOX); //sandbox_effect->set_float("parm", 42.0f); //chain.add_effect(EFFECT_MIRROR); @@ -205,11 +210,12 @@ int main(int argc, char **argv) ++frame; update_hsv(lift_gamma_gain_effect, saturation_effect); - vignette_effect->set_float("radius", radius); - vignette_effect->set_float("inner_radius", inner_radius); + //vignette_effect->set_float("radius", radius); + //vignette_effect->set_float("inner_radius", inner_radius); //vignette_effect->set_vec2("center", (float[]){ 0.7f, 0.5f }); - blur_effect->set_float("radius", blur_radius); + diffusion_effect->set_float("radius", blur_radius); + diffusion_effect->set_float("blurred_mix_amount", blurred_mix_amount); chain.render_to_screen(src_img); @@ -225,9 +231,12 @@ int main(int argc, char **argv) draw_hsv_wheel(0.2f, gamma_rad, gamma_theta, gamma_v); draw_hsv_wheel(0.4f, gain_rad, gain_theta, gain_v); draw_saturation_bar(0.6f, saturation / 4.0f); +#if 0 draw_saturation_bar(0.65f, radius); draw_saturation_bar(0.70f, inner_radius); +#endif draw_saturation_bar(0.75f, blur_radius / 100.0f); + draw_saturation_bar(0.80f, blurred_mix_amount); SDL_GL_SwapBuffers(); check_error(); diff --git a/overlay_matte_effect.frag b/overlay_matte_effect.frag new file mode 100644 index 0000000..f80f0b1 --- /dev/null +++ b/overlay_matte_effect.frag @@ -0,0 +1,5 @@ +vec4 FUNCNAME(vec2 tc) { + vec4 orig = INPUT1(tc); + vec4 blurred = INPUT2(tc); + return mix(orig, blurred, orig * vec4(PREFIX(blurred_mix_amount))); +}