diff --git a/CloneSource.cpp b/CloneSource.cpp index 2a63827..f24a87d 100644 --- a/CloneSource.cpp +++ b/CloneSource.cpp @@ -150,6 +150,9 @@ void CloneSource::setFilter(FrameBufferFilter::Type T) case FrameBufferFilter::FILTER_BLUR: filter_ = new BlurFilter; break; + case FrameBufferFilter::FILTER_SHARPEN: + filter_ = new SharpenFilter; + break; case FrameBufferFilter::FILTER_IMAGE: filter_ = new ImageFilter; break; diff --git a/FrameBufferFilter.cpp b/FrameBufferFilter.cpp index a2d642d..85564d1 100644 --- a/FrameBufferFilter.cpp +++ b/FrameBufferFilter.cpp @@ -6,7 +6,7 @@ #include "FrameBufferFilter.h" const char* FrameBufferFilter::type_label[FrameBufferFilter::FILTER_INVALID] = { - "None", "Delay", "Blur", "Shader code" + "None", "Delay", "Blur", "Sharpen", "Shader code" }; FrameBufferFilter::FrameBufferFilter() : enabled_(true), input_(nullptr) diff --git a/FrameBufferFilter.h b/FrameBufferFilter.h index 0b499b8..0eae509 100644 --- a/FrameBufferFilter.h +++ b/FrameBufferFilter.h @@ -21,6 +21,7 @@ public: FILTER_PASSTHROUGH = 0, FILTER_DELAY, FILTER_BLUR, + FILTER_SHARPEN, FILTER_IMAGE, FILTER_INVALID } Type; diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 8c85d0f..ed82e7d 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -818,6 +818,51 @@ void ImGuiVisitor::visit (BlurFilter& f) } +void ImGuiVisitor::visit (SharpenFilter& f) +{ + std::ostringstream oss; + oss << "Blur "; + + // Method selection + if (ImGuiToolkit::IconButton(7, 16)) { + f.setMethod( 0 ); + oss << SharpenFilter::method_label[0]; + Action::manager().store(oss.str()); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + int m = (int) f.method(); + if (ImGui::Combo("Method", &m, SharpenFilter::method_label, IM_ARRAYSIZE(SharpenFilter::method_label) )) { + f.setMethod( m ); + oss << SharpenFilter::method_label[m]; + Action::manager().store(oss.str()); + } + + + // List of parameters + std::map filter_parameters = f.program().parameters(); + for (auto param = filter_parameters.begin(); param != filter_parameters.end(); ++param) + { + ImGui::PushID( param->first.c_str() ); + float v = param->second; + if (ImGuiToolkit::IconButton(13, 14)) { + v = 0.f; + f.setProgramParameter(param->first, v); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + if (ImGui::SliderFloat( param->first.c_str(), &v, 0.f, 1.f, "%.2f")) { + f.setProgramParameter(param->first, v); + } + if (ImGui::IsItemDeactivatedAfterEdit()) { + oss << SharpenFilter::method_label[ f.method() ]; + oss << " : " << param->first << " " << std::setprecision(3) <second; + Action::manager().store(oss.str()); + } + ImGui::PopID(); + } +} + void ImGuiVisitor::visit (ImageFilter& f) { // Selection of Algorithm diff --git a/ImGuiVisitor.h b/ImGuiVisitor.h index f127167..fac88c9 100644 --- a/ImGuiVisitor.h +++ b/ImGuiVisitor.h @@ -40,6 +40,7 @@ public: void visit (PassthroughFilter&) override; void visit (DelayFilter&) override; void visit (BlurFilter&) override; + void visit (SharpenFilter&) override; void visit (ImageFilter&) override; }; diff --git a/ImageFilter.cpp b/ImageFilter.cpp index 9aad120..3fc2623 100644 --- a/ImageFilter.cpp +++ b/ImageFilter.cpp @@ -485,15 +485,15 @@ void ImageFilter::setProgramParameter(const std::string &p, float value) //////////////////////////////////////// const char* BlurFilter::method_label[BlurFilter::BLUR_INVALID] = { - "Gaussian", "Hash", "Openning", "Closing", "Fast 2x2" + "Gaussian", "Scattered", "Opening", "Closing", "Fast" }; std::vector< FilteringProgram > BlurFilter::programs_ = { - FilteringProgram("Gaussian", "shaders/filters/blur_1.glsl", "shaders/filters/blur_2.glsl", { { "Radius", 0.5} }), - FilteringProgram("Hashed", "shaders/filters/hashedblur.glsl", "", { { "Iterations", 0.5 }, { "Radius", 0.5} }), - FilteringProgram("Openning", "shaders/filters/hashederosion.glsl", "shaders/filters/hasheddilation.glsl", { { "Radius", 0.5} }), - FilteringProgram("Closing", "shaders/filters/hasheddilation.glsl", "shaders/filters/hashederosion.glsl", { { "Radius", 0.5} }), - FilteringProgram("Fast 2x2", "shaders/filters/blur.glsl", "", { }) + FilteringProgram("Gaussian", "shaders/filters/blur_1.glsl", "shaders/filters/blur_2.glsl", { { "Radius", 0.5} }), + FilteringProgram("Scattered","shaders/filters/hashedblur.glsl", "", { { "Radius", 0.5}, { "Iterations", 0.25 } }), + FilteringProgram("Opening", "shaders/filters/hashederosion.glsl", "shaders/filters/hasheddilation.glsl", { { "Radius", 0.5} }), + FilteringProgram("Closing", "shaders/filters/hasheddilation.glsl","shaders/filters/hashederosion.glsl", { { "Radius", 0.5} }), + FilteringProgram("Fast", "shaders/filters/blur.glsl", "", { }) }; BlurFilter::BlurFilter (): ImageFilter(), method_(BLUR_INVALID), mipmap_buffer_(nullptr) @@ -588,4 +588,37 @@ void BlurFilter::accept (Visitor& v) } +//////////////////////////////////////// +///// // +//// SHARPENING FILTERS /// +/// //// +//////////////////////////////////////// + +const char* SharpenFilter::method_label[SharpenFilter::SHARPEN_INVALID] = { + "Unsharp mask", "Convolution", "Edge" +}; + +std::vector< FilteringProgram > SharpenFilter::programs_ = { + FilteringProgram("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }), + FilteringProgram("Sharpen", "shaders/filters/sharp.glsl", "", { { "Amount", 0.5} }), + FilteringProgram("Sharp Edge", "shaders/filters/bilinear.glsl", "shaders/filters/sharpenedge.glsl", { { "Strength", 0.5} }), +}; + +SharpenFilter::SharpenFilter (): ImageFilter(), method_(SHARPEN_INVALID) +{ +} + +void SharpenFilter::setMethod(int method) +{ + method_ = (SharpenMethod) CLAMP(method, SHARPEN_MASK, SHARPEN_INVALID-1); + setProgram( programs_[ (int) method_] ); +} + +void SharpenFilter::accept (Visitor& v) +{ + FrameBufferFilter::accept(v); + v.visit(*this); +} + + diff --git a/ImageFilter.h b/ImageFilter.h index 7d1068c..862d9b8 100644 --- a/ImageFilter.h +++ b/ImageFilter.h @@ -137,6 +137,33 @@ private: }; +class SharpenFilter : public ImageFilter +{ +public: + + SharpenFilter(); + + // Algorithms used for sharpen + typedef enum { + SHARPEN_MASK = 0, + SHARPEN_CONVOLUTION, + SHARPEN_EDGE, + SHARPEN_INVALID + } SharpenMethod; + static const char* method_label[SHARPEN_INVALID]; + SharpenMethod method () const { return method_; } + void setMethod(int method); + + // implementation of FrameBufferFilter + Type type() const override { return FrameBufferFilter::FILTER_SHARPEN; } + + void accept (Visitor& v) override; + +private: + SharpenMethod method_; + static std::vector< FilteringProgram > programs_; +}; + #endif // IMAGEFILTER_H diff --git a/Visitor.h b/Visitor.h index 7b5b6be..9bafd86 100644 --- a/Visitor.h +++ b/Visitor.h @@ -45,6 +45,7 @@ class FrameBufferFilter; class PassthroughFilter; class DelayFilter; class BlurFilter; +class SharpenFilter; class ImageFilter; class SourceCallback; @@ -106,6 +107,7 @@ public: virtual void visit (PassthroughFilter&) {} virtual void visit (DelayFilter&) {} virtual void visit (BlurFilter&) {} + virtual void visit (SharpenFilter&) {} virtual void visit (ImageFilter&) {} virtual void visit (SourceCallback&) {} diff --git a/rsc/shaders/filters/hasheddilation.glsl b/rsc/shaders/filters/hasheddilation.glsl index df7cef5..a432813 100644 --- a/rsc/shaders/filters/hasheddilation.glsl +++ b/rsc/shaders/filters/hasheddilation.glsl @@ -37,10 +37,10 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) float ar = iResolution.y / iResolution.x ; float R = 0.25 * Radius ; - vec4 O = vec4(1.); + vec4 O = vec4(1.); float N = 17; for (float i = 0.; i < N; i++) { - vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * Hash01(uv, floatBitsToUint(i)); + vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * (0.1 + 0.9 * Hash01(uv, floatBitsToUint(i))); // vec2 q = vec2(cos(TWOPI*((i+.5)/N)) * ar, sin(TWOPI*(i+.5)/N)) * hash(vec2(i + 12., uv.x * uv.y + 24.)); O = min( texture(iChannel0, uv + q*R), O ); } diff --git a/rsc/shaders/filters/hashederosion.glsl b/rsc/shaders/filters/hashederosion.glsl index 0d0592c..f558e62 100644 --- a/rsc/shaders/filters/hashederosion.glsl +++ b/rsc/shaders/filters/hashederosion.glsl @@ -38,10 +38,10 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) float ar = iResolution.y / iResolution.x ; float R = 0.25 * Radius ; - vec4 O = vec4(0.); + vec4 O = vec4(0.); float N = 17; for (float i = 0.; i < N; i++) { - vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * Hash01(uv, floatBitsToUint(i) ); + vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * (0.1 + 0.9 * Hash01(uv, floatBitsToUint(i))); // vec2 q = vec2(cos(TWOPI*i/N) * ar, sin(TWOPI*i/N)) * hash(vec2(i, uv.x + uv.y)); O = max( texture(iChannel0, uv + q*R), O ); } diff --git a/rsc/shaders/filters/sharpen_1.glsl b/rsc/shaders/filters/sharpen_1.glsl index afde1f9..9ae4eaf 100644 --- a/rsc/shaders/filters/sharpen_1.glsl +++ b/rsc/shaders/filters/sharpen_1.glsl @@ -1,30 +1,22 @@ uniform float Amount; -float SCurve (float x) { - x = x * 2.0 - 1.0; - return -x * abs(x) * 0.5 + x + 0.5; -} - -vec3 BlurV (sampler2D source, vec2 uv, float step, float radius) { - vec3 C = vec3(0.0); - float divisor = 0.0; - float weight = 0.0; - float radiusMultiplier = 1.0 / max(1.0, radius); - - // loop on pixels in Y to apply vertical blur - for (float y = -radius; y <= radius; y++) { - weight = SCurve(1.0 - (abs(y) * radiusMultiplier)); - C += texture(source, uv + vec2(0.0, y * step)).rgb * weight; - divisor += weight; +#define N 7 +vec4 blur1D(vec2 U, vec2 D, float rad) +{ + float w = rad * iResolution.y; + float z = ceil(max(0.,log2(w/float(N)))); // LOD N/w = res/2^z + vec4 O = vec4(0); + float r = float(N-1)/2., g, t=0., x; + for( int k=0; k