Shadertoy-Shaders/Image-Filtering/Convolution-Filter/Image.glsl

137 lines
3.1 KiB
GLSL

vec3 conv(in sampler2D tex, in vec2 uv, in mat3 ker);
vec3 edges(in sampler2D tex, in vec2 uv)
{
mat3 ker = mat3(
vec3(-1, -2, -1),
vec3(-2, 12, -2),
vec3(-1, -2, -1)
);
return conv(tex, uv, ker)+.5;
}
// can be used to remove high frequency noise
vec3 median(in sampler2D tex, in vec2 uv)
{
float k = 1./8.;
mat3 ker = mat3(
vec3(k, k, k),
vec3(k, 0, k),
vec3(k, k, k)
);
return conv(tex, uv, ker);
}
// sharpen filter including diagonals
vec3 laplace(in sampler2D tex, in vec2 uv, in float strength)
{
float k = -strength;
mat3 ker = mat3(
vec3(k, k, k),
vec3(k, 8.*strength+1., k),
vec3(k, k, k)
);
return conv(tex, uv, ker);
}
// subtracts high frequency edges from the source image
vec3 unsharp(in sampler2D tex, in vec2 uv)
{
float k = 1./9.;
mat3 ker = mat3(
vec3(k, k, k),
vec3(k, k, k),
vec3(k, k, k)
);
vec3 blurred = conv(tex, uv, ker);
return texture(iChannel0, uv).rgb - (texture(iChannel0, uv).rgb - blurred);
}
vec3 emboss(in sampler2D tex, in vec2 uv, in float theta)
{
// init kernel
mat3 ker = mat3(
vec3(0),
vec3(0),
vec3(0)
);
// direction of edge detection
vec2 dir = vec2(sin(theta), cos(theta));
// fill kernel with values
for (int x = -1; x < 2; x++)
for (int y = -1; y < 2; y++)
ker[x+1][y+1] = dot(dir, vec2(x,y));
return conv(tex, uv, ker)+.5;
}
vec3 sobelFeldmann(in sampler2D tex, in vec2 uv)
{
// init horizontal kernel
mat3 ker0 = mat3(
vec3(1, 0, -1),
vec3(2, 0, -2),
vec3(1, 0, -1)
);
// init vertical kernel
mat3 ker1 = mat3(
vec3(1, 2, 1),
vec3(0, 0, 0),
vec3(-1, -2, -1)
);
vec3 c0 = conv(tex, uv, ker0);// convolute horizontal
vec3 c1 = conv(tex, uv, ker1);// convolute vertical
// pythagoras
return sqrt(c0*c0+c1*c1);
}
vec3 conv(in sampler2D tex, in vec2 uv, in mat3 ker)
{
vec3 sum = vec3(0);
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
{
vec2 off = (vec2(x,y)*.3333-.5)/iResolution.xy;
sum += texture(tex, uv + off).rgb * ker[x][y];
}
return sum;
}
bool sector(in vec2 uv, in vec2 hor, in vec2 ver)
{
vec2 delta = 1./vec2(hor[1], ver[1]);
vec2 low = delta * vec2(hor[0], ver[0]);
vec2 high = low + delta;
return low.x < uv.x && low.y < uv.y && high.x > uv.x && high.y > uv.y;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy;
vec3 col = texture(iChannel0, uv).rgb;
if (sector(uv, vec2(0,4), vec2(1,2))) col = unsharp(iChannel0, uv);
if (sector(uv, vec2(1,4), vec2(0,2))) col = laplace(iChannel0, uv, 2.0);
if (sector(uv, vec2(1,2), vec2(0,2))) col = emboss(iChannel0, uv, iTime);
if (sector(uv, vec2(1,2), vec2(1,2))) col = sobelFeldmann(iChannel0, uv);
if (sector(uv, vec2(1,4), vec2(1,2))) col = median(iChannel0, uv);
if (sector(uv, vec2(1,4), vec2(1,2))) col = edges(iChannel0, uv);
fragColor = vec4(col,1.0);
}