From 222282dced0603a559e5cac6ce4d411ef57a5500 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sat, 7 May 2022 13:39:08 +0200 Subject: [PATCH] Populating CloneSource with many preset ImageFilters --- CMakeLists.txt | 15 +++- CloneSource.cpp | 2 + ImageFilter.cpp | 16 +++- rsc/shaders/filters/bilinear.glsl | 53 ++++++++++++ rsc/shaders/filters/blur_1.glsl | 19 ++--- rsc/shaders/filters/blur_2.glsl | 22 ++--- rsc/shaders/filters/denoise.glsl | 6 +- rsc/shaders/filters/dithering.glsl | 44 ++++++++++ rsc/shaders/filters/edge.glsl | 40 ++++----- rsc/shaders/filters/grain.glsl | 117 +++++++++++++++++++++++++++ rsc/shaders/filters/noise.glsl | 94 +++++++++++++++++++++ rsc/shaders/filters/pixelate.glsl | 18 ++--- rsc/shaders/filters/sharp.glsl | 23 ++++++ rsc/shaders/filters/sharpen.glsl | 29 ++----- rsc/shaders/filters/sharpen_1.glsl | 30 +++++++ rsc/shaders/filters/sharpen_2.glsl | 37 +++++++++ rsc/shaders/filters/sharpenedge.glsl | 13 ++- rsc/shaders/filters/sobel.glsl | 20 ++--- rsc/shaders/filters/stippling.glsl | 53 ++++++++++++ 19 files changed, 549 insertions(+), 102 deletions(-) create mode 100644 rsc/shaders/filters/bilinear.glsl create mode 100644 rsc/shaders/filters/dithering.glsl create mode 100644 rsc/shaders/filters/grain.glsl create mode 100644 rsc/shaders/filters/noise.glsl create mode 100644 rsc/shaders/filters/sharp.glsl create mode 100644 rsc/shaders/filters/sharpen_1.glsl create mode 100644 rsc/shaders/filters/sharpen_2.glsl create mode 100644 rsc/shaders/filters/stippling.glsl diff --git a/CMakeLists.txt b/CMakeLists.txt index c60a5aa..5dd81d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,19 +561,28 @@ set(VMIX_RSC_FILES ./rsc/shaders/filters/bokeh.glsl ./rsc/shaders/filters/talk.glsl ./rsc/shaders/filters/fisheye.glsl - ./rsc/shaders/filters/hashedblur.glsl ./rsc/shaders/filters/blur.glsl ./rsc/shaders/filters/blur_1.glsl ./rsc/shaders/filters/blur_2.glsl + ./rsc/shaders/filters/hashedblur.glsl + ./rsc/shaders/filters/sharp.glsl ./rsc/shaders/filters/sharpen.glsl + ./rsc/shaders/filters/sharpen_1.glsl + ./rsc/shaders/filters/sharpen_2.glsl ./rsc/shaders/filters/sharpenedge.glsl ./rsc/shaders/filters/chromakey.glsl - ./rsc/shaders/filters/kuwahara.glsl - ./rsc/shaders/filters/freichen.glsl + ./rsc/shaders/filters/bilinear.glsl + ./rsc/shaders/filters/edge.glsl ./rsc/shaders/filters/sobel.glsl + ./rsc/shaders/filters/freichen.glsl + ./rsc/shaders/filters/kuwahara.glsl ./rsc/shaders/filters/pixelate.glsl ./rsc/shaders/filters/focus.glsl ./rsc/shaders/filters/denoise.glsl + ./rsc/shaders/filters/noise.glsl + ./rsc/shaders/filters/grain.glsl + ./rsc/shaders/filters/stippling.glsl + ./rsc/shaders/filters/dithering.glsl ) # Include the CMake RC module diff --git a/CloneSource.cpp b/CloneSource.cpp index 30e30ac..b747cc7 100644 --- a/CloneSource.cpp +++ b/CloneSource.cpp @@ -260,6 +260,8 @@ void CloneSource::play (bool on) bool CloneSource::playable () const { + if (filter_render_->enabled()) + return true; if (origin_) return origin_->playable(); return true; diff --git a/ImageFilter.cpp b/ImageFilter.cpp index 3f5e602..e144520 100644 --- a/ImageFilter.cpp +++ b/ImageFilter.cpp @@ -80,15 +80,22 @@ std::list< ImageFilter > ImageFilter::presets = { ImageFilter("Blur", "shaders/filters/blur_1.glsl", "shaders/filters/blur_2.glsl", { { "Amount", 0.5} }), ImageFilter("HashBlur", "shaders/filters/hashedblur.glsl", "", { { "Radius", 0.5}, { "Iterations", 0.5 } }), ImageFilter("Unfocus", "shaders/filters/focus.glsl", "", { { "Factor", 0.5} }), + ImageFilter("Smooth", "shaders/filters/bilinear.glsl", "", { }), ImageFilter("Denoise", "shaders/filters/denoise.glsl", "", { { "Threshold", 0.5} }), + ImageFilter("Noise", "shaders/filters/noise.glsl", "", { { "Amount", 0.25} }), + ImageFilter("Grain", "shaders/filters/grain.glsl", "", { { "Amount", 0.5} }), ImageFilter("Bloom", "shaders/filters/bloom.glsl", "", { { "Intensity", 0.5} }), ImageFilter("Bokeh", "shaders/filters/bokeh.glsl", "", { { "Radius", 1.0} }), ImageFilter("Kuwahara", "shaders/filters/kuwahara.glsl", "", { { "Radius", 1.0} }), ImageFilter("Chalk", "shaders/filters/talk.glsl", "", { { "Factor", 1.0} }), - ImageFilter("Sharpen", "shaders/filters/sharpen.glsl", "", { { "Strength", 1.0} }), - ImageFilter("Sharp Edge", "shaders/filters/sharpenedge.glsl", "", { { "Strength", 0.5} }), - ImageFilter("Freichen", "shaders/filters/freichen.glsl", "", { { "Factor", 0.5} }), + ImageFilter("Sharpen", "shaders/filters/sharp.glsl", "", { { "Amount", 0.5} }), + ImageFilter("Unsharp Mask", "shaders/filters/sharpen_1.glsl", "shaders/filters/sharpen_2.glsl", { { "Amount", 0.5} }), + ImageFilter("Sharp Edge", "shaders/filters/bilinear.glsl", "shaders/filters/sharpenedge.glsl", { { "Strength", 0.5} }), + ImageFilter("Edge", "shaders/filters/bilinear.glsl", "shaders/filters/edge.glsl", { { "Threshold", 0.5} }), ImageFilter("Sobel", "shaders/filters/sobel.glsl", "", { { "Factor", 0.5} }), + ImageFilter("Freichen", "shaders/filters/freichen.glsl", "", { { "Factor", 0.5} }), + ImageFilter("Stippling","shaders/filters/stippling.glsl", "", { { "Factor", 0.5} }), + ImageFilter("Dithering","shaders/filters/dithering.glsl", "", { { "Factor", 0.5} }), ImageFilter("Pixelate", "shaders/filters/pixelate.glsl", "", { { "Size", 0.5}, { "Sharpen", 0.5} }), ImageFilter("Chromakey","shaders/filters/chromakey.glsl", "", { { "Red", 0.05}, { "Green", 0.63}, { "Blue", 0.14}, { "Tolerance", 0.54} }), ImageFilter("Fisheye", "shaders/filters/fisheye.glsl", "", { { "Factor", 0.5} }), @@ -313,6 +320,9 @@ ImageFilterRenderer::~ImageFilterRenderer() void ImageFilterRenderer::setInputTexture(uint t) { surfaces_.first->setTextureIndex( t ); + shaders_.first->mask_texture = t; + if (surfaces_.second && shaders_.second) + shaders_.second->mask_texture = t; } uint ImageFilterRenderer::getOutputTexture() const diff --git a/rsc/shaders/filters/bilinear.glsl b/rsc/shaders/filters/bilinear.glsl new file mode 100644 index 0000000..8f5d572 --- /dev/null +++ b/rsc/shaders/filters/bilinear.glsl @@ -0,0 +1,53 @@ +#define SIGMA 10.0 +#define BSIGMA 0.1 + +float kernel[15]; + +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) +{ + 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; + + kernel[0] = 0.031225216; + kernel[1] = 0.033322271; + kernel[2] = 0.035206333; + kernel[3] = 0.036826804; + kernel[4] = 0.038138565; + kernel[5] = 0.039104044; + kernel[6] = 0.039695028; + kernel[7] = 0.039894000; + kernel[8] = 0.039695028; + kernel[9] = 0.039104044; + kernel[10] = 0.038138565; + kernel[11] = 0.036826804; + kernel[12] = 0.035206333; + kernel[13] = 0.033322271; + kernel[14] = 0.031225216; + + vec3 final_colour = vec3(0.0); + float Z = 0.0; + vec3 cc; + float f; + float bZ = 1.0/normpdf(0.0, mix(BSIGMA, 1.0, .0) ); + + for (int i = -7; i <= 7; ++i) + { + for (int j = -7; j <= 7; ++j) + { + cc = texture(iChannel0, (fragCoord.xy+vec2(float(i),float(j))) / iResolution.xy).rgb; + f = normpdf3(cc-c, mix(BSIGMA, 1.0, .0) ) * bZ * kernel[7+j] * kernel[7+i]; + Z += f; + final_colour += f*cc; + } + } + fragColor = vec4(final_colour/Z, 1.0); +} diff --git a/rsc/shaders/filters/blur_1.glsl b/rsc/shaders/filters/blur_1.glsl index b2e8b52..0fbd96a 100644 --- a/rsc/shaders/filters/blur_1.glsl +++ b/rsc/shaders/filters/blur_1.glsl @@ -1,22 +1,22 @@ +#define RADIUS 0.2 + 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 A = vec3(0.0); +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 / radius; + float radiusMultiplier = 1.0 / max(1.0, radius); - for (float y = -radius; y <= radius; y++) - { - A = texture(source, uv + vec2(0.0, y * step)).rgb; + // loop on pixels in Y to apply vertical blur + for (float y = -radius; y <= radius; y++) { weight = SCurve(1.0 - (abs(y) * radiusMultiplier)); - C += A * weight; + C += texture(source, uv + vec2(0.0, y * step)).rgb * weight; divisor += weight; } @@ -25,9 +25,10 @@ vec3 BlurV (sampler2D source, vec2 uv, float step, float radius) { void mainImage( out vec4 fragColor, in vec2 fragCoord ) { + // downsample the image to benefit from (free) linear subsampling of colors float subsampling = 1.0 - ( Amount * 0.9 ); vec2 uv = fragCoord.xy / ( iResolution.xy * subsampling ); - // Apply vertical blur on downsampled image (allows to divide radius) - fragColor = vec4( BlurV(iChannel0, uv, 1.0 / (iResolution.y * subsampling), Amount * 100.0 * subsampling), 1.0); + // Apply vertical blur on downsampled image (allows to use smaller radius) + fragColor = vec4( BlurV(iChannel0, uv, 1.0 / (iResolution.y * subsampling), RADIUS * iResolution.y * Amount * subsampling), 1.0); } diff --git a/rsc/shaders/filters/blur_2.glsl b/rsc/shaders/filters/blur_2.glsl index 5e7ee2d..dcb228a 100644 --- a/rsc/shaders/filters/blur_2.glsl +++ b/rsc/shaders/filters/blur_2.glsl @@ -1,3 +1,5 @@ +#define RADIUS 0.2 + uniform float Amount; float SCurve (float x) { @@ -6,18 +8,15 @@ float SCurve (float x) { } vec3 BlurH (sampler2D source, vec2 uv, float step, float radius) { - - vec3 A = vec3(0.0); vec3 C = vec3(0.0); float divisor = 0.0; float weight = 0.0; - float radiusMultiplier = 1.0 / radius; + float radiusMultiplier = 1.0 / max(1.0, radius); - for (float x = -radius; x <= radius; x++) - { - A = texture(source, uv + vec2(x * step, 0.0)).rgb; + // loop on pixels in X to apply horizontal blur: note optimization of +2 increment + for (float x = -radius; x <= radius; x+=2.0) { weight = SCurve(1.0 - (abs(x) * radiusMultiplier)); - C += A * weight; + C += texture(source, uv + vec2(x * step, 0.0)).rgb * weight; divisor += weight; } @@ -26,9 +25,10 @@ vec3 BlurH (sampler2D source, vec2 uv, float step, float radius) { void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - float subsampling = 1.0 - ( Amount * 0.9 ); - vec2 uv = (fragCoord.xy * subsampling) / iResolution.xy; + // upsample the image from blur_1 + float upsampling = 1.0 - ( Amount * 0.9 ); + vec2 uv = (fragCoord.xy * upsampling) / iResolution.xy; - // Apply horizontal blur - fragColor = vec4( BlurH(iChannel0, uv, subsampling / iResolution.x, Amount * 100.0), 1.0); + // Apply horizontal blur on restored resolution image + fragColor = vec4( BlurH(iChannel0, uv, upsampling / iResolution.x, RADIUS * iResolution.y * Amount), 1.0); } diff --git a/rsc/shaders/filters/denoise.glsl b/rsc/shaders/filters/denoise.glsl index bdcccb4..49a7403 100644 --- a/rsc/shaders/filters/denoise.glsl +++ b/rsc/shaders/filters/denoise.glsl @@ -49,7 +49,7 @@ vec4 smartDeNoise(sampler2D tex, vec2 uv, float sigma, float kSigma, float thres for(float y=-pt; y <= pt; y++) { vec2 d = vec2(x,y); - float blurFactor = exp( -dot(d , d) * invSigmaQx2 ) * invSigmaQx2PI; + float blurFactor = exp( -dot(d, d) * invSigmaQx2 ) * invSigmaQx2PI; vec4 walkPx = texture(tex,uv+d/size); @@ -133,9 +133,9 @@ vec4 smartDeNoise(sampler2D tex, vec2 uv, float sigma, float kSigma, float thres void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - // Normalized pixel coordinates (from 0 to 1) + // Normalized pixel coordinates vec2 uv = fragCoord/iResolution.xy; - fragColor = smartDeNoise(iChannel0, uv, 5.0, 2.0, mix(0.01, 0.1, Threshold)); + fragColor = smartDeNoise(iChannel0, uv, 2.0, 4.0, mix(0.01, 0.2, Threshold)); } diff --git a/rsc/shaders/filters/dithering.glsl b/rsc/shaders/filters/dithering.glsl new file mode 100644 index 0000000..49b3cf7 --- /dev/null +++ b/rsc/shaders/filters/dithering.glsl @@ -0,0 +1,44 @@ +uniform float Factor; + +const float mult = 1.0 / 17.0; +const mat4 adjustments = (mat4( + 1, 13, 4, 16, + 9, 5, 12, 8, + 3, 15, 2, 14, + 11, 7, 10, 6 +) - 8.) * mult; + +float getLuminance( vec4 color ) { + return (0.2126*color.r + 0.7152*color.g + 0.0722*color.b); +} + +float adjustFrag( float val, vec2 coord ) { + vec2 coordMod = mod(coord, 4.0); + int xMod = int(coordMod.x); + int yMod = int(coordMod.y); + + vec4 col; + if (xMod == 0) col = adjustments[0]; + else if (xMod == 1) col = adjustments[1]; + else if (xMod == 2) col = adjustments[2]; + else if (xMod == 3) col = adjustments[3]; + + float adjustment; + if (yMod == 0) adjustment = col.x; + else if (yMod == 1) adjustment = col.y; + else if (yMod == 2) adjustment = col.z; + else if (yMod == 3) adjustment = col.w; + + return val + (val * adjustment); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy; + vec4 videoColor = texture(iChannel0, uv); + + float vidLum = getLuminance(videoColor); + vidLum = adjustFrag(vidLum, fragCoord.xy); + + fragColor = step( Factor - vidLum , vec4(0, 0, 0, 1) ); +} diff --git a/rsc/shaders/filters/edge.glsl b/rsc/shaders/filters/edge.glsl index 31320c7..4161d90 100644 --- a/rsc/shaders/filters/edge.glsl +++ b/rsc/shaders/filters/edge.glsl @@ -1,22 +1,24 @@ + +uniform float Threshold; + void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec3 c[16]; - for (int i=0; i < 4; ++i) - for (int j=0; j < 4; ++j) - { - c[4*i+j] = texture(iChannel0, (fragCoord.xy+vec2(i-2,j-2)) / iResolution.xy).rgb; - } - - vec3 Lx = 2.0*(c[14]-c[2]) + 2.0*(c[13]-c[1]) + c[15] - c[3] + c[12] - c[0]; - Lx += 0.5 * (2.0*(c[10]-c[6]) + 2.0*(c[9]-c[5]) + c[11] - c[7] + c[8] - c[4] ); - - vec3 Ly = 2.0*(c[8]-c[11]) + 2.0*(c[4]-c[7]) + c[12] + c[0] - c[15] - c[3]; - Ly += 0.5 * (2.0*(c[9]-c[10]) + 2.0*(c[5]-c[6]) + c[13] + c[1] - c[14] - c[2] ); - - //vec3 G = sqrt(Lx*Lx+Ly*Ly); - vec3 G = abs(Lx)+abs(Ly); - - fragColor = vec4( mix(vec3(1.0), vec3(0.0), pow(length(G),2) ), 1.0); - -} + vec3 c[16]; + for (int i=0; i < 4; ++i) + for (int j=0; j < 4; ++j) + { + c[4*i+j] = texture(iChannel0, (fragCoord.xy+vec2(i-2,j-2)) / iResolution.xy).rgb; + } + // pseudo Scharr masks 4 x 4 + vec3 Lx = 10.0*(c[14]-c[2] + c[13]-c[1]) + 3.0*(c[15]-c[3] + c[12]-c[0]); + Lx += 2.0*(c[10]-c[6] + c[9]-c[5]) + (c[11]-c[7] + c[8]-c[4]); + + vec3 Ly = 10.0*(c[8]-c[11]+ c[4]-c[7]) + 3.0*(c[12]-c[15] + c[0]-c[3]); + Ly += 2.0*(c[9]-c[10] + c[5]-c[6]) + (c[13]-c[14] + c[1]-c[2]); + + vec3 G = sqrt(Lx*Lx+Ly*Ly); + //vec3 G = abs(Lx)+abs(Ly); + + fragColor = vec4( vec3( step( mix( 1.0, 10.0, Threshold), length(G)) ), 1.0); +} diff --git a/rsc/shaders/filters/grain.glsl b/rsc/shaders/filters/grain.glsl new file mode 100644 index 0000000..0b61468 --- /dev/null +++ b/rsc/shaders/filters/grain.glsl @@ -0,0 +1,117 @@ +uniform float Amount; + +const float permTexUnit = 1.0/256.0; // Perm texture texel-size +const float permTexUnitHalf = 0.5/256.0; // Half perm texture texel-size + +#define width float(iResolution.x) +#define height float(iResolution.y) + +const float grainamount = 0.5; //grain amount +float coloramount = 0.6; +float grainsize = 2.0; //grain particle size (1.5 - 2.5) +float lumamount = 0.3; + +//a random texture generator, but you can also use a pre-computed perturbation texture +vec4 rnm(in vec2 tc) +{ + float timer = iTime; + float noise = sin(dot(tc + vec2(timer,timer),vec2(12.9898,78.233))) * 43758.5453; + float noiseR = fract(noise)*2.0-1.0; + float noiseG = fract(noise*1.2154)*2.0-1.0; + float noiseB = fract(noise*1.3453)*2.0-1.0; + float noiseA = fract(noise*1.3647)*2.0-1.0; + + return vec4(noiseR,noiseG,noiseB,noiseA); +} + +float fade(in float t) { + return t*t*t*(t*(t*6.0-15.0)+10.0); +} + +float pnoise3D(in vec3 p) +{ + vec3 pi = permTexUnit*floor(p)+permTexUnitHalf; + vec3 pf = fract(p); // Fractional part for interpolation + + // Noise contributions from (x=0, y=0), z=0 and z=1 + float perm00 = rnm(pi.xy).a ; + vec3 grad000 = rnm(vec2(perm00, pi.z)).rgb * 4.0 - 1.0; + float n000 = dot(grad000, pf); + vec3 grad001 = rnm(vec2(perm00, pi.z + permTexUnit)).rgb * 4.0 - 1.0; + float n001 = dot(grad001, pf - vec3(0.0, 0.0, 1.0)); + + // Noise contributions from (x=0, y=1), z=0 and z=1 + float perm01 = rnm(pi.xy + vec2(0.0, permTexUnit)).a ; + vec3 grad010 = rnm(vec2(perm01, pi.z)).rgb * 4.0 - 1.0; + float n010 = dot(grad010, pf - vec3(0.0, 1.0, 0.0)); + vec3 grad011 = rnm(vec2(perm01, pi.z + permTexUnit)).rgb * 4.0 - 1.0; + float n011 = dot(grad011, pf - vec3(0.0, 1.0, 1.0)); + + // Noise contributions from (x=1, y=0), z=0 and z=1 + float perm10 = rnm(pi.xy + vec2(permTexUnit, 0.0)).a ; + vec3 grad100 = rnm(vec2(perm10, pi.z)).rgb * 4.0 - 1.0; + float n100 = dot(grad100, pf - vec3(1.0, 0.0, 0.0)); + vec3 grad101 = rnm(vec2(perm10, pi.z + permTexUnit)).rgb * 4.0 - 1.0; + float n101 = dot(grad101, pf - vec3(1.0, 0.0, 1.0)); + + // Noise contributions from (x=1, y=1), z=0 and z=1 + float perm11 = rnm(pi.xy + vec2(permTexUnit, permTexUnit)).a ; + vec3 grad110 = rnm(vec2(perm11, pi.z)).rgb * 4.0 - 1.0; + float n110 = dot(grad110, pf - vec3(1.0, 1.0, 0.0)); + vec3 grad111 = rnm(vec2(perm11, pi.z + permTexUnit)).rgb * 4.0 - 1.0; + float n111 = dot(grad111, pf - vec3(1.0, 1.0, 1.0)); + + // Blend contributions along x + vec4 n_x = mix(vec4(n000, n001, n010, n011), vec4(n100, n101, n110, n111), fade(pf.x)); + + // Blend contributions along y + vec2 n_xy = mix(n_x.xy, n_x.zw, fade(pf.y)); + + // Blend contributions along z + float n_xyz = mix(n_xy.x, n_xy.y, fade(pf.z)); + + // We're done, return the final noise value. + return n_xyz; +} + +//2d coordinate orientation thing +vec2 coordRot(in vec2 tc, in float angle) +{ + float aspect = width/height; + vec2 uv = (tc*2.0)-1.0; + float rotX = (uv.x*aspect*cos(angle)) - (uv.y*sin(angle)); + float rotY = (uv.y*cos(angle)) + (uv.x*aspect*sin(angle)); + rotX = ((rotX/aspect)*0.5+0.5); + rotY = rotY*0.5+0.5; + return vec2(rotX,rotY); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + float timer = iTime; + vec2 texCoord = fragCoord.rg / vec2(iResolution.x, iResolution.y); + + vec3 rotOffset = vec3(1.425,3.892,5.835); //rotation offset values + vec2 rotCoordsR = coordRot(texCoord, timer + rotOffset.x); + vec3 noise = vec3(pnoise3D(vec3(rotCoordsR*vec2(width/grainsize,height/grainsize),0.0))); + + vec2 rotCoordsG = coordRot(texCoord, timer + rotOffset.y); + vec2 rotCoordsB = coordRot(texCoord, timer + rotOffset.z); + 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; + + //noisiness response curve based on scene luminance + vec3 lumcoeff = vec3(0.299,0.587,0.114); + float luminance = lumamount * dot(col, 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); +} + + diff --git a/rsc/shaders/filters/noise.glsl b/rsc/shaders/filters/noise.glsl new file mode 100644 index 0000000..7927ede --- /dev/null +++ b/rsc/shaders/filters/noise.glsl @@ -0,0 +1,94 @@ +uniform float Amount; + +// Feel free to steal this :^) +// Consider it MIT licensed, you can link to this page if you want to. + +#define SRGB 1 +// 0: Addition, 1: Screen, 2: Overlay, 3: Soft Light, 4: Lighten-Only +#define BLEND_MODE 2 +#define SPEED 1.5 +// What gray level noise should tend to. +#define MEAN 0.0 +// 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)); +} + +float hash11(float p) +{ + p = fract(p * .1031); + p *= p + 33.33; + p *= p + p; + return fract(p); +} +float hash12(vec2 p) +{ + vec3 p3 = fract(vec3(p.xyx) * .1031); + 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) { + 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); +} + +vec3 overlay(vec3 a, vec3 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) + ), 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); +} + +void mainImage(out vec4 color, vec2 coord) { + vec2 uv = coord / iResolution.xy; + color = texture(iChannel0, uv); + #if SRGB + color = pow(color, vec4(2.2)); + #endif + + float t = iTime * float(SPEED); + float seed = dot(uv, vec2(12.9898, 78.233)); + float noise = fract(sin(seed) * 43758.5453 + t + hash12(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); + + #if BLEND_MODE == 0 + color.rgb += grain * w; + #elif BLEND_MODE == 1 + color.rgb = screen(color.rgb, grain, w); + #elif BLEND_MODE == 2 + color.rgb = overlay(color.rgb, grain, w); + #elif BLEND_MODE == 3 + color.rgb = soft_light(color.rgb, grain, w); + #elif BLEND_MODE == 4 + color.rgb = max(color.rgb, grain * w); + #endif + + #if SRGB + color = pow(color, vec4(1.0 / 2.2)); + #endif +} diff --git a/rsc/shaders/filters/pixelate.glsl b/rsc/shaders/filters/pixelate.glsl index 69b5523..077dd91 100644 --- a/rsc/shaders/filters/pixelate.glsl +++ b/rsc/shaders/filters/pixelate.glsl @@ -1,24 +1,20 @@ uniform float Size; -uniform float Edge; +uniform float Sharpen; -const mat3 I = mat3( 0, 0, 0, 0, 1, 0, 0, 0, 0); const mat3 G = mat3( 0.0625, 0.125, 0.0625, 0.125, 0.25, 0.125, 0.0625, 0.125, 0.0625); void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 size = vec2(3.0 * iResolution.x / iResolution.y, 3.0 ); - size = mix( size, iResolution.xy, pow(1.0 - Size, 3) ) ; + size = mix( size, iResolution.xy, pow(1.0 - Size, 3.0) ) ; vec2 vUv = size / iResolution.xy; - vec4 blur = vec4(0,0,0,0); + vec3 blur = vec3(0,0,0); for (int i=0; i<3; i++) - for (int j=0; j<3; j++) { - blur += G[i][j] * texture(iChannel0, floor(vUv * (fragCoord + vec2(i-1,j-1))) / size ); - } + for (int j=0; j<3; j++) { + blur += G[i][j] * texture(iChannel0, round( (vUv * fragCoord) + vec2(i-1,j-1) ) / size ).rgb; + } - vec4 sample = texture(iChannel0, floor(vUv * fragCoord) / size ); - sample += Edge * (sample - blur); - - fragColor = sample; + fragColor = vec4( mix( blur, texture(iChannel0, round(vUv * fragCoord) / size ).rgb, Sharpen), 1.0); } diff --git a/rsc/shaders/filters/sharp.glsl b/rsc/shaders/filters/sharp.glsl new file mode 100644 index 0000000..383069e --- /dev/null +++ b/rsc/shaders/filters/sharp.glsl @@ -0,0 +1,23 @@ +uniform float Amount; + +vec4 sharp(sampler2D sampler, vec2 fc, vec2 re) +{ + float strength = mix( 2.0, 20.0, Amount); + vec2 uv = fc / re; + vec4 c0 = texture(sampler,uv); + vec4 c1 = texture(sampler,uv-vec2( 1./re.x,.0)); + vec4 c2 = texture(sampler,uv+vec2( 1./re.x,.0)); + vec4 c3 = texture(sampler,uv-vec2(.0, 1./re.y)); + vec4 c4 = texture(sampler,uv+vec2(.0, 1./re.y)); + vec4 c5 = c0+c1+c2+c3+c4; + c5*=0.2; + vec4 mi = min(c0,c1); mi = min(mi,c2); mi = min(mi,c3); mi = min(mi,c4); + vec4 ma = max(c0,c1); ma = max(ma,c2); ma = max(ma,c3); ma = max(ma,c4); + return clamp(mi,(strength+1.0)*c0-c5*strength,ma); +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + fragColor = sharp(iChannel0, fragCoord.xy, iResolution.xy); +} + diff --git a/rsc/shaders/filters/sharpen.glsl b/rsc/shaders/filters/sharpen.glsl index d9af99b..8948e9e 100644 --- a/rsc/shaders/filters/sharpen.glsl +++ b/rsc/shaders/filters/sharpen.glsl @@ -1,23 +1,10 @@ -uniform float Strength; - vec3 texSample(const int x, const int y, in vec2 fragCoord) { - vec2 uv = fragCoord.xy / iResolution.xy * iChannelResolution[0].xy; - uv = (uv + vec2(x, y)) / iChannelResolution[0].xy; - return texture(iChannel0, uv).xyz; + vec2 uv = fragCoord.xy / iResolution.xy * iChannelResolution[0].xy; + uv = (uv + vec2(x, y)) / iChannelResolution[0].xy; + return texture(iChannel0, uv).xyz; } -void blur( out vec3 rgb, in vec2 fragCoord ) -{ - vec3 tot = vec3(0.0); - - for( int j=0; j<9; j++ ) - for( int i=0; i<9; i++ ) - tot += pow( texSample(i-4, j-4, fragCoord), vec3(2.2)); - - rgb = pow(tot/81.0,vec3(1.0/2.2)); -} - void sharpen( out vec3 rgb, in vec2 fragCoord ) { rgb = @@ -34,17 +21,11 @@ void sharpen( out vec3 rgb, in vec2 fragCoord ) void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec3 original = texSample( 0, 0, fragCoord); // sharpen mask vec3 sharped; sharpen(sharped, fragCoord); - // sharpen by subtracting blurred image to original - vec3 blurred; - blur(blurred, fragCoord); - blurred = original + (original-blurred); - // progressive mix from original to most sharpen - sharped = mix(sharped, blurred, Strength); - fragColor = vec4( mix(original, sharped, Strength * 2.0), 1.0); + + fragColor = vec4( sharped, 1.0); } diff --git a/rsc/shaders/filters/sharpen_1.glsl b/rsc/shaders/filters/sharpen_1.glsl new file mode 100644 index 0000000..afde1f9 --- /dev/null +++ b/rsc/shaders/filters/sharpen_1.glsl @@ -0,0 +1,30 @@ +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; + } + + return C / divisor; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy; + + // Apply vertical blur + fragColor = vec4( BlurV(iChannel0, uv, 1.0 / iResolution.y, mix(1.0, 0.1*iResolution.y, Amount)), 1.0); +} diff --git a/rsc/shaders/filters/sharpen_2.glsl b/rsc/shaders/filters/sharpen_2.glsl new file mode 100644 index 0000000..1415e87 --- /dev/null +++ b/rsc/shaders/filters/sharpen_2.glsl @@ -0,0 +1,37 @@ +uniform float Amount; + +float SCurve (float x) { + x = x * 2.0 - 1.0; + return -x * abs(x) * 0.5 + x + 0.5; +} + +vec3 BlurH (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 X to apply horizontal blur + for (float x = -radius; x <= radius; x++) { + weight = SCurve(1.0 - (abs(x) * radiusMultiplier)); + C += texture(source, uv + vec2(x * step, 0.0)).rgb * weight; + divisor += weight; + } + + return C / divisor; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy / iResolution.xy; + + // get original image + vec3 c = texture(iChannel1, uv).rgb; + + // Remove blurred image to original image + vec3 lumcoeff = vec3(0.299,0.587,0.114); + float luminance = dot( c - BlurH(iChannel0, uv, 1.0 / iResolution.x, mix(1.0, 0.1*iResolution.y, Amount) ), lumcoeff); + + // composition + fragColor = vec4( c + vec3(luminance), 1.0); +} diff --git a/rsc/shaders/filters/sharpenedge.glsl b/rsc/shaders/filters/sharpenedge.glsl index 146f34c..4c6f6e5 100644 --- a/rsc/shaders/filters/sharpenedge.glsl +++ b/rsc/shaders/filters/sharpenedge.glsl @@ -11,8 +11,8 @@ vec3 blurSample(in vec2 uv, in vec2 xoff, in vec2 yoff) vec3 edgeStrength(in vec2 uv) { - const float spread = 0.5; - vec2 offset = vec2(1.0) / iChannelResolution[0].xy; + const float spread = 0.5; + vec2 offset = vec2(1.0) / iChannelResolution[0].xy; vec2 up = vec2(0.0, offset.y) * spread; vec2 right = vec2(offset.x, 0.0) * spread; const float frad = 3.0; @@ -29,15 +29,14 @@ vec3 edgeStrength(in vec2 uv) vec3 v33 = blurSample(uv - up + right, right, up); vec3 laplacian_of_g = v11 * 0.0 + v12 * 1.0 + v13 * 0.0 - + v21 * 1.0 + v22 * -4.0 + v23 * 1.0 - + v31 * 0.0 + v32 * 1.0 + v33 * 0.0; - laplacian_of_g = laplacian_of_g * 1.0; + + v21 * 1.0 + v22 * -4.0 + v23 * 1.0 + + v31 * 0.0 + v32 * 1.0 + v33 * 0.0; + laplacian_of_g = laplacian_of_g * 1.0; return laplacian_of_g.xyz; } - void mainImage( out vec4 fragColor, in vec2 fragCoord ) { - vec2 uv = fragCoord.xy / iResolution.xy; + vec2 uv = fragCoord.xy / iResolution.xy; fragColor = vec4(texture(iChannel0, uv).xyz - edgeStrength(uv) * Strength * (iResolution.y*0.05), 1.0); } diff --git a/rsc/shaders/filters/sobel.glsl b/rsc/shaders/filters/sobel.glsl index 4f1c49a..7d91fec 100644 --- a/rsc/shaders/filters/sobel.glsl +++ b/rsc/shaders/filters/sobel.glsl @@ -1,8 +1,8 @@ uniform float Factor; const mat3 G[2] = mat3[]( - mat3( 3.0, 10.0, 3.0, 0.0, 0.0, 0.0, -3.0, -10.0, -3.0 ), - mat3( 3.0, 0.0, -3.0, 10.0, 0.0, -10.0, 3.0, 0.0, -3.0 ) + mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 ), + mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 ) ); void sobel( out vec3 rgb, in vec2 fragCoord ) @@ -13,24 +13,20 @@ void sobel( out vec3 rgb, in vec2 fragCoord ) for (int i=0; i<3; i++) for (int j=0; j<3; j++) { sample = texture(iChannel0, (fragCoord + vec2(i-1,j-1)) / iResolution.xy ).rgb; - I[i][j] = length(sample); + I[i][j] = length(sample) * mix(1.0, 3.0, Factor); } for (int i=0; i<2; i++) { - float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]); - cnv[i] = dp3 * dp3; + float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]); + cnv[i] = dp3 * dp3; } - // rgb = vec3( (0.1 + 4.0 * Factor) * sqrt(cnv[0]*cnv[0]+cnv[1]*cnv[1]) ); - - rgb = vec3( step( Factor, 2.0 * ( abs(cnv[0]) + abs(cnv[1]) ) ) ); + //rgb = vec3( 1.0 - sqrt(cnv[0]*cnv[0]+cnv[1]*cnv[1]) ); + rgb = vec3( 1.0 - ( abs(cnv[0]) + abs(cnv[1]) ) ); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec3 v; sobel(v, fragCoord); - fragColor = vec4( vec3(1.0) - v, 1.0); + fragColor = vec4(v, 1.0); } - - - diff --git a/rsc/shaders/filters/stippling.glsl b/rsc/shaders/filters/stippling.glsl new file mode 100644 index 0000000..0477b04 --- /dev/null +++ b/rsc/shaders/filters/stippling.glsl @@ -0,0 +1,53 @@ +uniform float Factor; + +#define SEED1 -0.5775604999999985 +#define SEED2 6.440483302499992 + +vec2 stepnoise(vec2 p, float size) { + p += 10.0; + float x = floor(p.x/size)*size; + float y = floor(p.y/size)*size; + + x = fract(x*0.1) + 1.0 + x*0.0002; + y = fract(y*0.1) + 1.0 + y*0.0003; + + float a = fract(1.0 / (0.000001*x*y + 0.00001)); + a = fract(1.0 / (0.000001234*a + 0.00001)); + + float b = fract(1.0 / (0.000002*(x*y+x) + 0.00001)); + b = fract(1.0 / (0.0000235*b + 0.00001)); + + return vec2(a, b); +} + +float tent(float f) { + return 1.0 - abs(fract(f)-0.5)*2.0; +} + +float mask(vec2 p) { + vec2 r = stepnoise(p, 8.423424); + p[0] += r[0]; + p[1] += r[1]; + + float f1 = tent(p[0]*SEED1 + p[1]/(SEED1+0.5)); + float f2 = tent(p[1]*SEED2 + p[0]/(SEED2+0.5)); + float f = sqrt( f1*f2 ); + + return f; +} + +float saturation(vec3 color) { + return (min(color.r, min(color.g, color.b)) + max(color.r, max(color.g, color.b))) * 0.5; +} + +void mainImage( out vec4 fragColor, in vec2 fragCoord ) +{ + vec2 uv = fragCoord.xy; + vec2 uv2 = fragCoord.xy / iResolution.x; + + float f = saturation( texture(iChannel0, fragCoord.xy / iResolution.xy).rgb ); + float c = mask(uv); + c = float( f > mix( 0.6 * c, 1.4 * c, Factor) ); + + fragColor = vec4(c, c, c, 1.0); +}