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)
--- /dev/null
+#include <math.h>
+#include <assert.h>
+
+#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<Effect *> &inputs) {
+ assert(inputs.size() == 1);
+ blur->add_self_to_effect_chain(chain, inputs);
+
+ std::vector<Effect *> 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");
+}
--- /dev/null
+#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<Effect *> &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)
#include "mirror_effect.h"
#include "vignette_effect.h"
#include "blur_effect.h"
+#include "diffusion_effect.h"
EffectChain::EffectChain(unsigned width, unsigned height)
: width(width),
return new VignetteEffect();
case EFFECT_BLUR:
return new BlurEffect();
+ case EFFECT_DIFFUSION:
+ return new DiffusionEffect();
}
assert(false);
}
EFFECT_MIRROR,
EFFECT_VIGNETTE,
EFFECT_BLUR,
+ EFFECT_DIFFUSION,
};
#endif // !defined(_EFFECT_ID_H)
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)
{
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);
}
}
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);
++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);
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();
--- /dev/null
+vec4 FUNCNAME(vec2 tc) {
+ vec4 orig = INPUT1(tc);
+ vec4 blurred = INPUT2(tc);
+ return mix(orig, blurred, orig * vec4(PREFIX(blurred_mix_amount)));
+}