mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Original implementation of Smooth Image filters
Smoothing and noise reduction filters + noise generators.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
FILTER_RESAMPLE,
|
||||
FILTER_BLUR,
|
||||
FILTER_SHARPEN,
|
||||
FILTER_SMOOTH,
|
||||
FILTER_EDGE,
|
||||
FILTER_ALPHA,
|
||||
FILTER_IMAGE,
|
||||
|
||||
121
ImGuiVisitor.cpp
121
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<std::string, float> 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) <<param->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<std::string, float> 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<std::string, float> 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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ///
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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&) {}
|
||||
|
||||
Binary file not shown.
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,33 +21,33 @@ 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];
|
||||
vec4 m[4];
|
||||
vec4 s[4];
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
m[k] = vec3(0.0);
|
||||
s[k] = vec3(0.0);
|
||||
m[k] = vec4(0.0);
|
||||
s[k] = vec4(0.0);
|
||||
}
|
||||
float R = 0.1;
|
||||
float D = length(vec2(rad));
|
||||
@@ -55,7 +55,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
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;
|
||||
vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step);
|
||||
m[0] += c;
|
||||
s[0] += c * c;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
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;
|
||||
vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step);
|
||||
m[1] += c;
|
||||
s[1] += c * c;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
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;
|
||||
vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step);
|
||||
m[2] += c;
|
||||
s[2] += c * c;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
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;
|
||||
vec4 c = texture(iChannel0, uv + delta * smoothstep(R, D, length(delta)) * uv_step);
|
||||
m[3] += c;
|
||||
s[3] += c * c;
|
||||
}
|
||||
@@ -95,7 +95,7 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
float sigma2 = s[k].r + s[k].g + s[k].b;
|
||||
if (sigma2 < min_sigma2) {
|
||||
min_sigma2 = sigma2;
|
||||
outpix = vec4(m[k], 1.0);
|
||||
outpix = m[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user