diff --git a/CloneSource.cpp b/CloneSource.cpp index 1155a56..741487d 100644 --- a/CloneSource.cpp +++ b/CloneSource.cpp @@ -163,6 +163,9 @@ void CloneSource::setFilter(FrameBufferFilter::Type T) case FrameBufferFilter::FILTER_SHARPEN: filter_ = new SharpenFilter; break; + case FrameBufferFilter::FILTER_SMOOTH: + filter_ = new SmoothFilter; + break; case FrameBufferFilter::FILTER_EDGE: filter_ = new EdgeFilter; break; diff --git a/FrameBufferFilter.cpp b/FrameBufferFilter.cpp index 4ee7b0f..efcd847 100644 --- a/FrameBufferFilter.cpp +++ b/FrameBufferFilter.cpp @@ -6,7 +6,7 @@ #include "FrameBufferFilter.h" const char* FrameBufferFilter::type_label[FrameBufferFilter::FILTER_INVALID] = { - "None", "Delay", "Resample", "Blur", "Sharpen", "Edge", "Transparency", "Shader code" + "None", "Delay", "Resample", "Blur", "Sharpen", "Smooth & Noise", "Edge", "Transparency", "Custom shader" }; FrameBufferFilter::FrameBufferFilter() : enabled_(true), input_(nullptr) diff --git a/FrameBufferFilter.h b/FrameBufferFilter.h index faad623..11a0743 100644 --- a/FrameBufferFilter.h +++ b/FrameBufferFilter.h @@ -23,6 +23,7 @@ public: FILTER_RESAMPLE, FILTER_BLUR, FILTER_SHARPEN, + FILTER_SMOOTH, FILTER_EDGE, FILTER_ALPHA, FILTER_IMAGE, diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 6ca8087..c8b2712 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -851,6 +851,51 @@ void ImGuiVisitor::visit (SharpenFilter& f) } } +void ImGuiVisitor::visit (SmoothFilter& f) +{ + std::ostringstream oss; + oss << "Smooth "; + + // Method selection + if (ImGuiToolkit::IconButton(14, 8)) { + f.setMethod( 0 ); + oss << SmoothFilter::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, SmoothFilter::method_label, IM_ARRAYSIZE(SmoothFilter::method_label) )) { + f.setMethod( m ); + oss << SmoothFilter::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 << EdgeFilter::method_label[ f.method() ]; + oss << " : " << param->first << " " << std::setprecision(3) <second; + Action::manager().store(oss.str()); + } + ImGui::PopID(); + } +} + + void ImGuiVisitor::visit (EdgeFilter& f) { std::ostringstream oss; @@ -988,47 +1033,47 @@ void ImGuiVisitor::visit (ImageFilter& f) FilteringProgram target; f.setProgram( target ); } - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("Algorithm", f.program().name().c_str()) ) - { - for (auto p = FilteringProgram::presets.begin(); p != FilteringProgram::presets.end(); ++p){ - if (ImGui::Selectable( p->name().c_str() )) { - // apply the selected filter to the source - f.setProgram( *p ); - } - } - ImGui::EndCombo(); - } +// ImGui::SameLine(0, IMGUI_SAME_LINE); +// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); +// if (ImGui::BeginCombo("Algorithm", f.program().name().c_str()) ) +// { +// for (auto p = FilteringProgram::presets.begin(); p != FilteringProgram::presets.end(); ++p){ +// if (ImGui::Selectable( p->name().c_str() )) { +// // apply the selected filter to the source +// f.setProgram( *p ); +// } +// } +// ImGui::EndCombo(); +// } - // 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()) { - // TODO UNDO - // std::ostringstream oss; - // oss << "Delay " << std::setprecision(3) << d << " s"; - // Action::manager().store(oss.str()); - } - ImGui::PopID(); - } +// // 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()) { +// // TODO UNDO +// // std::ostringstream oss; +// // oss << "Delay " << std::setprecision(3) << d << " s"; +// // Action::manager().store(oss.str()); +// } +// ImGui::PopID(); +// } // Open Editor - ImGuiToolkit::IconButton(18, 18); +// ImGuiToolkit::IconButton(18, 18); ImGui::SameLine(0, IMGUI_SAME_LINE); - if ( ImGui::Button( ICON_FA_CODE " Edit", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) + if ( ImGui::Button( ICON_FA_CODE " Open editor", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) Settings::application.widget.shader_editor = true; ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("Code"); @@ -1068,7 +1113,7 @@ void ImGuiVisitor::visit (CloneSource& s) ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); int type = (int) s.filter()->type(); - if (ImGui::Combo("Filter", &type, FrameBufferFilter::type_label, IM_ARRAYSIZE(FrameBufferFilter::type_label) )) { + if (ImGui::Combo("Filter", &type, FrameBufferFilter::type_label, IM_ARRAYSIZE(FrameBufferFilter::type_label), FrameBufferFilter::FILTER_INVALID)) { s.setFilter( FrameBufferFilter::Type(type) ); oss << ": Filter " << FrameBufferFilter::type_label[type]; Action::manager().store(oss.str()); diff --git a/ImGuiVisitor.h b/ImGuiVisitor.h index be93dd8..2026e75 100644 --- a/ImGuiVisitor.h +++ b/ImGuiVisitor.h @@ -42,6 +42,7 @@ public: void visit (ResampleFilter&) override; void visit (BlurFilter&) override; void visit (SharpenFilter&) override; + void visit (SmoothFilter&) override; void visit (EdgeFilter&) override; void visit (AlphaFilter&) override; void visit (ImageFilter&) override; diff --git a/ImageFilter.cpp b/ImageFilter.cpp index 900b88f..3658682 100644 --- a/ImageFilter.cpp +++ b/ImageFilter.cpp @@ -78,23 +78,13 @@ std::string fragmentFooter = "void main() {\n" std::list< FilteringProgram > FilteringProgram::presets = { FilteringProgram(), - FilteringProgram("Unfocus", "shaders/filters/focus.glsl", "", { { "Factor", 0.5} }), - FilteringProgram("Smooth", "shaders/filters/bilinear.glsl", "", { }), - FilteringProgram("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 1.0} }), - FilteringProgram("Denoise", "shaders/filters/denoise.glsl", "", { { "Threshold", 0.5} }), - FilteringProgram("Noise", "shaders/filters/noise.glsl", "", { { "Amount", 0.25} }), - FilteringProgram("Grain", "shaders/filters/grain.glsl", "", { { "Amount", 0.5} }), + FilteringProgram("Bilateral","shaders/filters/bilinear.glsl", "", { }), FilteringProgram("Pixelate", "shaders/filters/pixelate.glsl", "", { { "Size", 0.5}, { "Sharpen", 0.5} }), - FilteringProgram("Erosion", "shaders/filters/erosion.glsl", "", { { "Radius", 0.5} }), - FilteringProgram("Dilation", "shaders/filters/dilation.glsl", "", { { "Radius", 0.5} }), - FilteringProgram("Openning", "shaders/filters/erosion.glsl", "shaders/filters/dilation.glsl", { { "Radius", 0.5} }), - FilteringProgram("Closing", "shaders/filters/dilation.glsl", "shaders/filters/erosion.glsl", { { "Radius", 0.5} }), FilteringProgram("Bloom", "shaders/filters/bloom.glsl", "", { { "Intensity", 0.5} }), FilteringProgram("Bokeh", "shaders/filters/bokeh.glsl", "", { { "Radius", 1.0} }), FilteringProgram("Chalk", "shaders/filters/talk.glsl", "", { { "Factor", 1.0} }), FilteringProgram("Stippling","shaders/filters/stippling.glsl", "", { { "Factor", 0.5} }), FilteringProgram("Dithering","shaders/filters/dithering.glsl", "", { { "Factor", 0.5} }), - FilteringProgram("Chromakey","shaders/filters/chromakey.glsl", "", { { "Red", 0.05}, { "Green", 0.63}, { "Blue", 0.14}, { "Tolerance", 0.54} }), FilteringProgram("Fisheye", "shaders/filters/fisheye.glsl", "", { { "Factor", 0.35} }), }; @@ -693,7 +683,7 @@ const char* SharpenFilter::method_label[SharpenFilter::SHARPEN_INVALID] = { }; std::vector< FilteringProgram > SharpenFilter::programs_ = { - FilteringProgram("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }), + FilteringProgram("UnsharpMask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }), FilteringProgram("Sharpen", "shaders/filters/sharpen.glsl", "", { { "Amount", 0.5} }), FilteringProgram("Sharp Edge", "shaders/filters/sharpenedge.glsl","", { { "Amount", 0.5} }), FilteringProgram("TopHat", "shaders/filters/erosion.glsl", "shaders/filters/tophat.glsl", { { "Radius", 0.5} }), @@ -726,6 +716,55 @@ void SharpenFilter::accept (Visitor& v) } + +//////////////////////////////////////// +///// // +//// SMOOTHING FILTERS /// +/// //// +//////////////////////////////////////// + +const char* SmoothFilter::method_label[SmoothFilter::SMOOTH_INVALID] = { + "Bilateral", "Kuwahara", "Opening", "Closing", "Erosion", "Dilation", "Remove noise", "Add noise", "Add grain" +}; + +std::vector< FilteringProgram > SmoothFilter::programs_ = { + FilteringProgram("Bilateral","shaders/filters/focus.glsl", "", { { "Factor", 0.5} }), + FilteringProgram("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 1.0} }), + FilteringProgram("Opening", "shaders/filters/erosion.glsl", "shaders/filters/dilation.glsl", { { "Radius", 0.5} }), + FilteringProgram("Closing", "shaders/filters/dilation.glsl", "shaders/filters/erosion.glsl", { { "Radius", 0.5} }), + FilteringProgram("Erosion", "shaders/filters/erosion.glsl", "", { { "Radius", 0.5} }), + FilteringProgram("Dilation", "shaders/filters/dilation.glsl", "", { { "Radius", 0.5} }), + FilteringProgram("Denoise", "shaders/filters/denoise.glsl", "", { { "Threshold", 0.5} }), + FilteringProgram("Noise", "shaders/filters/noise.glsl", "", { { "Amount", 0.25} }), + FilteringProgram("Grain", "shaders/filters/grain.glsl", "", { { "Amount", 0.5} }) +}; + +SmoothFilter::SmoothFilter (): ImageFilter(), method_(SMOOTH_INVALID) +{ +} + +void SmoothFilter::setMethod(int method) +{ + method_ = (SmoothMethod) CLAMP(method, SMOOTH_BILINEAR, SMOOTH_INVALID-1); + setProgram( programs_[ (int) method_] ); +} + +void SmoothFilter::draw (FrameBuffer *input) +{ + // Default + if (method_ == SMOOTH_INVALID) + setMethod( SMOOTH_BILINEAR ); + + ImageFilter::draw( input ); +} + +void SmoothFilter::accept (Visitor& v) +{ + FrameBufferFilter::accept(v); + v.visit(*this); +} + + //////////////////////////////////////// ///// // //// EDGE FILTERS /// diff --git a/ImageFilter.h b/ImageFilter.h index 5569fc8..ca4c9b7 100644 --- a/ImageFilter.h +++ b/ImageFilter.h @@ -198,6 +198,41 @@ private: }; +class SmoothFilter : public ImageFilter +{ +public: + + SmoothFilter(); + + // Algorithms used for smoothing + typedef enum { + SMOOTH_BILINEAR = 0, + SMOOTH_KUWAHARA, + SMOOTH_OPENING, + SMOOTH_CLOSING, + SMOOTH_EROSION, + SMOOTH_DILATION, + SMOOTH_DENOISE, + SMOOTH_ADDNOISE, + SMOOTH_ADDGRAIN, + SMOOTH_INVALID + } SmoothMethod; + static const char* method_label[SMOOTH_INVALID]; + SmoothMethod method () const { return method_; } + void setMethod(int method); + + // implementation of FrameBufferFilter + Type type() const override { return FrameBufferFilter::FILTER_SMOOTH; } + + void draw (FrameBuffer *input) override; + void accept (Visitor& v) override; + +private: + SmoothMethod method_; + static std::vector< FilteringProgram > programs_; +}; + + class EdgeFilter : public ImageFilter { public: diff --git a/SessionCreator.cpp b/SessionCreator.cpp index 600543d..3de0f1d 100644 --- a/SessionCreator.cpp +++ b/SessionCreator.cpp @@ -1275,6 +1275,30 @@ void SessionLoader::visit (SharpenFilter& f) f.setProgramParameters(filter_params); } +void SessionLoader::visit (SmoothFilter& f) +{ + int m = 0; + xmlCurrent_->QueryIntAttribute("method", &m); + f.setMethod(m); + + std::map< std::string, float > filter_params; + XMLElement* parameters = xmlCurrent_->FirstChildElement("parameters"); + if (parameters) { + XMLElement* param = parameters->FirstChildElement("uniform"); + for( ; param ; param = param->NextSiblingElement()) + { + float val = 0.f; + param->QueryFloatAttribute("value", &val); + const char * name; + param->QueryStringAttribute("name", &name); + if (name) + filter_params[name] = val; + } + } + + f.setProgramParameters(filter_params); +} + void SessionLoader::visit (EdgeFilter& f) { int m = 0; diff --git a/SessionCreator.h b/SessionCreator.h index e971bfd..12bc38f 100644 --- a/SessionCreator.h +++ b/SessionCreator.h @@ -68,6 +68,7 @@ public: void visit (BlurFilter&) override; void visit (SharpenFilter&) override; void visit (EdgeFilter&) override; + void visit (SmoothFilter&) override; void visit (AlphaFilter&) override; void visit (ImageFilter&) override; diff --git a/SessionVisitor.cpp b/SessionVisitor.cpp index ebecfe3..336d24d 100644 --- a/SessionVisitor.cpp +++ b/SessionVisitor.cpp @@ -725,6 +725,22 @@ void SessionVisitor::visit (SharpenFilter& f) } } +void SessionVisitor::visit (SmoothFilter& f) +{ + xmlCurrent_->SetAttribute("method", (int) f.method()); + + std::map< std::string, float > filter_params = f.program().parameters(); + XMLElement *parameters = xmlDoc_->NewElement( "parameters" ); + xmlCurrent_->InsertEndChild(parameters); + for (auto p = filter_params.begin(); p != filter_params.end(); ++p) + { + XMLElement *param = xmlDoc_->NewElement( "uniform" ); + param->SetAttribute("name", p->first.c_str() ); + param->SetAttribute("value", p->second ); + parameters->InsertEndChild(param); + } +} + void SessionVisitor::visit (EdgeFilter& f) { xmlCurrent_->SetAttribute("method", (int) f.method()); diff --git a/SessionVisitor.h b/SessionVisitor.h index 3a39c19..fcd05ce 100644 --- a/SessionVisitor.h +++ b/SessionVisitor.h @@ -75,6 +75,7 @@ public: void visit (ResampleFilter&) override; void visit (BlurFilter&) override; void visit (SharpenFilter&) override; + void visit (SmoothFilter&) override; void visit (EdgeFilter&) override; void visit (AlphaFilter&) override; void visit (ImageFilter&) override; diff --git a/Visitor.h b/Visitor.h index d751ebc..da425b7 100644 --- a/Visitor.h +++ b/Visitor.h @@ -47,6 +47,7 @@ class DelayFilter; class ResampleFilter; class BlurFilter; class SharpenFilter; +class SmoothFilter; class EdgeFilter; class AlphaFilter; class ImageFilter; @@ -112,6 +113,7 @@ public: virtual void visit (ResampleFilter&) {} virtual void visit (BlurFilter&) {} virtual void visit (SharpenFilter&) {} + virtual void visit (SmoothFilter&) {} virtual void visit (EdgeFilter&) {} virtual void visit (AlphaFilter&) {} virtual void visit (ImageFilter&) {} diff --git a/rsc/images/icons.dds b/rsc/images/icons.dds index cf10a2a..6c8a230 100644 Binary files a/rsc/images/icons.dds and b/rsc/images/icons.dds differ diff --git a/rsc/shaders/filters/dilation.glsl b/rsc/shaders/filters/dilation.glsl index 7196bac..537dd22 100644 --- a/rsc/shaders/filters/dilation.glsl +++ b/rsc/shaders/filters/dilation.glsl @@ -1,9 +1,9 @@ uniform float Radius; #define MAX_SIZE 5 -vec3 dilation (sampler2D source, vec2 uv, vec2 uv_step, float rad) { +vec4 dilation (sampler2D source, vec2 uv, vec2 uv_step, float rad) { - vec3 maxValue = vec3(0.0); + vec4 maxValue = vec4(0.0); float R = length(vec2(rad)) ; float D = rad; @@ -12,7 +12,7 @@ vec3 dilation (sampler2D source, vec2 uv, vec2 uv_step, float rad) { for (float j=-rad; j <= rad; ++j) { vec2 delta = vec2(i, j); - maxValue = max(texture(source, uv + delta * smoothstep(R, D, length(delta)) * uv_step ).rgb, maxValue); + maxValue = max(texture(source, uv + delta * smoothstep(R, D, length(delta)) * uv_step ), maxValue); } } @@ -22,5 +22,5 @@ vec3 dilation (sampler2D source, vec2 uv, vec2 uv_step, float rad) { void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; - fragColor = vec4( dilation(iChannel0, uv, 1.0 / iResolution.xy, mix(1., MAX_SIZE, Radius)), 1.0); + fragColor = dilation(iChannel0, uv, 1.0 / iResolution.xy, mix(1., MAX_SIZE, Radius)); } diff --git a/rsc/shaders/filters/erosion.glsl b/rsc/shaders/filters/erosion.glsl index 3993964..fe42629 100644 --- a/rsc/shaders/filters/erosion.glsl +++ b/rsc/shaders/filters/erosion.glsl @@ -1,9 +1,9 @@ uniform float Radius; #define MAX_SIZE 5 -vec3 erosion (sampler2D source, vec2 uv, vec2 uv_step, float rad) +vec4 erosion (sampler2D source, vec2 uv, vec2 uv_step, float rad) { - vec3 minValue = vec3(1.0); + vec4 minValue = vec4(1.0); float R = length(vec2(rad)) ; float D = rad; @@ -12,7 +12,7 @@ vec3 erosion (sampler2D source, vec2 uv, vec2 uv_step, float rad) for (float j=-rad; j <= rad; ++j) { vec2 delta = vec2(i, j); - minValue = min(texture(source, uv + delta * smoothstep(R, D, length(delta)) * uv_step ).rgb, minValue); + minValue = min(texture(source, uv + delta * smoothstep(R, D, length(delta)) * uv_step ), minValue); } } @@ -22,5 +22,5 @@ vec3 erosion (sampler2D source, vec2 uv, vec2 uv_step, float rad) void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; - fragColor = vec4( erosion(iChannel0, uv, 1.0 / iResolution.xy, mix(1., MAX_SIZE, Radius)), 1.0); + fragColor = erosion(iChannel0, uv, 1.0 / iResolution.xy, mix(1., MAX_SIZE, Radius)); } diff --git a/rsc/shaders/filters/focus.glsl b/rsc/shaders/filters/focus.glsl index a54aff2..5368037 100644 --- a/rsc/shaders/filters/focus.glsl +++ b/rsc/shaders/filters/focus.glsl @@ -11,18 +11,18 @@ float normpdf(in float x, in float sigma) return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma; } -float normpdf3(in vec3 v, in float sigma) +float normpdf3(in vec4 v, in float sigma) { return 0.39894*exp(-0.5*dot(v,v)/(sigma*sigma))/sigma; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec3 c = texture(iChannel0, (fragCoord.xy / iResolution.xy) ).rgb; + vec4 c = texture(iChannel0, (fragCoord.xy / iResolution.xy) ); const int kSize = (MSIZE-1)/2; float kernel[MSIZE]; - vec3 final_colour = vec3(0.0); + vec4 final_colour = vec4(0.0); //create the 1-D kernel float Z = 0.0; @@ -31,7 +31,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), SIGMA); } - vec3 cc; + vec4 cc; float fac; float bsigma = mix(0.01, 1.2, Factor); float bZ = 1.0/normpdf(0.0, bsigma); @@ -39,14 +39,13 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) { for (int j=-kSize; j <= kSize; ++j) { - cc = texture(iChannel0, (fragCoord.xy+vec2(float(i),float(j))) / iResolution.xy).rgb; + cc = texture(iChannel0, (fragCoord.xy+vec2(float(i),float(j))) / iResolution.xy); fac = normpdf3(cc-c, bsigma)*bZ*kernel[kSize+j]*kernel[kSize+i]; Z += fac; final_colour += fac*cc; - } } - fragColor = vec4(final_colour/Z, 1.0); + fragColor = final_colour/Z; } diff --git a/rsc/shaders/filters/grain.glsl b/rsc/shaders/filters/grain.glsl index 0b61468..a73b89a 100644 --- a/rsc/shaders/filters/grain.glsl +++ b/rsc/shaders/filters/grain.glsl @@ -100,18 +100,16 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) noise.g = mix(noise.r,pnoise3D(vec3(rotCoordsG*vec2(width/grainsize,height/grainsize),1.0)),coloramount); noise.b = mix(noise.r,pnoise3D(vec3(rotCoordsB*vec2(width/grainsize,height/grainsize),2.0)),coloramount); - vec3 col = texture(iChannel0, texCoord).rgb; + vec4 col = texture(iChannel0, texCoord); //noisiness response curve based on scene luminance vec3 lumcoeff = vec3(0.299,0.587,0.114); - float luminance = lumamount * dot(col, lumcoeff); + float luminance = lumamount * dot(col.rgb, lumcoeff); float lum = smoothstep(0.2,0.0,luminance); lum += luminance; noise = mix(noise,vec3(0.0),pow(lum,4.0)); - col += noise * mix(0.02, 0.4, Amount); - - fragColor = vec4(col,1.0); + fragColor = col + vec4(noise * mix(0.02, 0.4, Amount), col.a); } diff --git a/rsc/shaders/filters/kuwahara.glsl b/rsc/shaders/filters/kuwahara.glsl index f706ab5..6427dec 100644 --- a/rsc/shaders/filters/kuwahara.glsl +++ b/rsc/shaders/filters/kuwahara.glsl @@ -21,83 +21,83 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) //////////////////////////////////////////////////////////////////////////////// // Bilateral difference-check, to speed up the processing of large flat areas // //////////////////////////////////////////////////////////////////////////////// - vec3 compare = texture(iChannel0, uv).rgb; + vec4 compare = texture(iChannel0, uv); bool diffpix = false; for (int j = -rad; j <= rad; ++j) { - if (texture(iChannel0, uv + vec2(0,j) * uv_step).rgb != compare) { + if (texture(iChannel0, uv + vec2(0,j) * uv_step) != compare) { diffpix = true; break; } } if (!diffpix) { for (int i = -rad; i <= rad; ++i) { - if (texture(iChannel0, uv + vec2(i,0) * uv_step).rgb != compare) { + if (texture(iChannel0, uv + vec2(i,0) * uv_step) != compare) { diffpix = true; break; } } } if (!diffpix) { - outpix = vec4( texture(iChannel0, uv).rgb, 1.0); + outpix = compare; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// - else { - vec3 m[4]; - vec3 s[4]; - for (int k = 0; k < 4; ++k) { - m[k] = vec3(0.0); - s[k] = vec3(0.0); - } - float R = 0.1; - float D = length(vec2(rad)); - - for (int j = -rad; j <= 0; ++j) { - for (int i = -rad; i <= 0; ++i) { + else { + vec4 m[4]; + vec4 s[4]; + for (int k = 0; k < 4; ++k) { + m[k] = vec4(0.0); + s[k] = vec4(0.0); + } + float R = 0.1; + float D = length(vec2(rad)); + + for (int j = -rad; j <= 0; ++j) { + for (int i = -rad; i <= 0; ++i) { vec2 delta = vec2(i, j); - vec3 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step).rgb; - m[0] += c; - s[0] += c * c; - } - } - - for (int j = -rad; j <= 0; ++j) { - for (int i = 0; i <= rad; ++i) { + vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step); + m[0] += c; + s[0] += c * c; + } + } + + for (int j = -rad; j <= 0; ++j) { + for (int i = 0; i <= rad; ++i) { vec2 delta = vec2(i, j); - vec3 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step).rgb; - m[1] += c; - s[1] += c * c; - } - } - - for (int j = 0; j <= rad; ++j) { - for (int i = 0; i <= rad; ++i) { + vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step); + m[1] += c; + s[1] += c * c; + } + } + + for (int j = 0; j <= rad; ++j) { + for (int i = 0; i <= rad; ++i) { vec2 delta = vec2(i, j); - vec3 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step).rgb; - m[2] += c; - s[2] += c * c; - } - } - - for (int j = 0; j <= rad; ++j) { - for (int i = -rad; i <= 0; ++i) { + vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step); + m[2] += c; + s[2] += c * c; + } + } + + for (int j = 0; j <= rad; ++j) { + for (int i = -rad; i <= 0; ++i) { vec2 delta = vec2(i, j); - vec3 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step).rgb; - m[3] += c; - s[3] += c * c; - } - } - - float min_sigma2 = 1e+2; - for (int k = 0; k < 4; ++k) { - m[k] /= n; - s[k] = abs(s[k] / n - m[k] * m[k]); - float sigma2 = s[k].r + s[k].g + s[k].b; - if (sigma2 < min_sigma2) { - min_sigma2 = sigma2; - outpix = vec4(m[k], 1.0); - } - } + vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step); + m[3] += c; + s[3] += c * c; + } + } + + float min_sigma2 = 1e+2; + for (int k = 0; k < 4; ++k) { + m[k] /= n; + s[k] = abs(s[k] / n - m[k] * m[k]); + float sigma2 = s[k].r + s[k].g + s[k].b; + if (sigma2 < min_sigma2) { + min_sigma2 = sigma2; + outpix = m[k]; + } + } } fragColor = outpix; diff --git a/rsc/shaders/filters/noise.glsl b/rsc/shaders/filters/noise.glsl index 7927ede..f14692d 100644 --- a/rsc/shaders/filters/noise.glsl +++ b/rsc/shaders/filters/noise.glsl @@ -12,8 +12,8 @@ uniform float Amount; // Controls the contrast/variance of noise. #define VARIANCE 0.5 -vec3 channel_mix(vec3 a, vec3 b, vec3 w) { - return vec3(mix(a.r, b.r, w.r), mix(a.g, b.g, w.g), mix(a.b, b.b, w.b)); +vec4 channel_mix(vec4 a, vec4 b, vec4 w) { + return vec4(mix(a.r, b.r, w.r), mix(a.g, b.g, w.g), mix(a.b, b.b, w.b), mix(a.a, b.a, w.a)); } float hash11(float p) @@ -29,38 +29,33 @@ float hash12(vec2 p) p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } -float hash13(vec3 p3) -{ - p3 = fract(p3 * .1031); - p3 += dot(p3, p3.zyx + 31.32); - return fract((p3.x + p3.y) * p3.z); -} float gaussian(float z, float u, float o) { return (1.0 / (o * sqrt(2.0 * 3.1415))) * exp(-(((z - u) * (z - u)) / (2.0 * (o * o)))); } -vec3 madd(vec3 a, vec3 b, float w) { +vec4 madd(vec4 a, vec4 b, float w) { return a + a * b * w; } -vec3 screen(vec3 a, vec3 b, float w) { - return mix(a, vec3(1.0) - (vec3(1.0) - a) * (vec3(1.0) - b), w); +vec4 screen(vec4 a, vec4 b, float w) { + return mix(a, vec4(1.0) - (vec4(1.0) - a) * (vec4(1.0) - b), w); } -vec3 overlay(vec3 a, vec3 b, float w) { +vec4 overlay(vec4 a, vec4 b, float w) { return mix(a, channel_mix( 2.0 * a * b, - vec3(1.0) - 2.0 * (vec3(1.0) - a) * (vec3(1.0) - b), - step(vec3(0.5), a) + vec4(1.0) - 2.0 * (vec4(1.0) - a) * (vec4(1.0) - b), + step(vec4(0.5), a) ), w); } -vec3 soft_light(vec3 a, vec3 b, float w) { - return mix(a, pow(a, pow(vec3(2.0), 2.0 * (vec3(0.5) - b))), w); +vec4 soft_light(vec4 a, vec4 b, float w) { + return mix(a, pow(a, pow(vec4(2.0), 2.0 * (vec4(0.5) - b))), w); } -void mainImage(out vec4 color, vec2 coord) { +void mainImage(out vec4 color, in vec2 coord) +{ vec2 uv = coord / iResolution.xy; color = texture(iChannel0, uv); #if SRGB @@ -73,19 +68,19 @@ void mainImage(out vec4 color, vec2 coord) { noise = gaussian(noise, float(MEAN), float(VARIANCE) * float(VARIANCE)); - float w = mix(0.05, 0.5, Amount ); - vec3 grain = vec3(noise) * (1.0 - color.rgb); + float w = mix(0.05, 0.8, Amount ); + vec4 grain = vec4(noise) * (1.0 - color); #if BLEND_MODE == 0 - color.rgb += grain * w; + color += grain * w; #elif BLEND_MODE == 1 - color.rgb = screen(color.rgb, grain, w); + color = screen(color, grain, w); #elif BLEND_MODE == 2 - color.rgb = overlay(color.rgb, grain, w); + color = overlay(color, grain, w); #elif BLEND_MODE == 3 - color.rgb = soft_light(color.rgb, grain, w); + color = soft_light(color, grain, w); #elif BLEND_MODE == 4 - color.rgb = max(color.rgb, grain * w); + color = max(color, grain * w); #endif #if SRGB