168 lines
3.4 KiB
GLSL
168 lines
3.4 KiB
GLSL
#version 150
|
|
uniform sampler2D tex0;
|
|
in vec2 vTexCoord;
|
|
out vec4 FragColor;
|
|
|
|
uniform float colors; // 12.0
|
|
uniform float sat_levels; // 4.0
|
|
uniform float bri_levels; // 4.0
|
|
uniform float edge_thres; // 0.2;
|
|
uniform float edge_thres2; // 5.0;
|
|
|
|
vec3 RGBtoHSV( float r, float g, float b)
|
|
{
|
|
float minv, maxv, delta;
|
|
vec3 res;
|
|
|
|
minv = min(min(r, g), b);
|
|
maxv = max(max(r, g), b);
|
|
res.z = maxv; // v
|
|
|
|
delta = maxv - minv;
|
|
|
|
if( maxv != 0.0 )
|
|
res.y = delta / maxv; // s
|
|
else {
|
|
// r = g = b = 0 // s = 0, v is undefined
|
|
res.y = 0.0;
|
|
res.x = -1.0;
|
|
return res;
|
|
}
|
|
|
|
if( r == maxv )
|
|
res.x = ( g - b ) / delta; // between yellow & magenta
|
|
else if( g == maxv )
|
|
res.x = 2.0 + ( b - r ) / delta; // between cyan & yellow
|
|
else
|
|
res.x = 4.0 + ( r - g ) / delta; // between magenta & cyan
|
|
|
|
res.x = res.x * 60.0; // degrees
|
|
if( res.x < 0.0 )
|
|
res.x = res.x + 360.0;
|
|
|
|
return res;
|
|
}
|
|
|
|
vec3 HSVtoRGB(float h, float s, float v )
|
|
{
|
|
int i;
|
|
float f, p, q, t;
|
|
vec3 res;
|
|
|
|
if( s == 0.0 )
|
|
{
|
|
// achromatic (grey)
|
|
res.x = v;
|
|
res.y = v;
|
|
res.z = v;
|
|
return res;
|
|
}
|
|
|
|
h /= 60.0; // sector 0 to 5
|
|
i = int(floor( h ));
|
|
f = h - float(i); // factorial part of h
|
|
p = v * ( 1.0 - s );
|
|
q = v * ( 1.0 - s * f );
|
|
t = v * ( 1.0 - s * ( 1.0 - f ) );
|
|
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
res.x = v;
|
|
res.y = t;
|
|
res.z = p;
|
|
break;
|
|
case 1:
|
|
res.x = q;
|
|
res.y = v;
|
|
res.z = p;
|
|
break;
|
|
case 2:
|
|
res.x = p;
|
|
res.y = v;
|
|
res.z = t;
|
|
break;
|
|
case 3:
|
|
res.x = p;
|
|
res.y = q;
|
|
res.z = v;
|
|
break;
|
|
case 4:
|
|
res.x = t;
|
|
res.y = p;
|
|
res.z = v;
|
|
break;
|
|
default: // case 5:
|
|
res.x = v;
|
|
res.y = p;
|
|
res.z = q;
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// averaged pixel intensity from 3 color channels
|
|
float avg_intensity(vec4 pix)
|
|
{
|
|
return (pix.r + pix.g + pix.b)/3.;
|
|
}
|
|
|
|
vec4 get_pixel(vec2 coords, float dx, float dy)
|
|
{
|
|
return texture(tex0,coords + vec2(dx, dy));
|
|
}
|
|
|
|
// returns pixel color
|
|
float IsEdge(in vec2 coords)
|
|
{
|
|
float dxtex = 1.0 /float(textureSize(tex0,0)) ;
|
|
float dytex = 1.0 /float(textureSize(tex0,0));
|
|
float pix[9];
|
|
int k = -1;
|
|
float delta;
|
|
|
|
// read neighboring pixel intensities
|
|
for (int i=-1; i<2; i++) {
|
|
for(int j=-1; j<2; j++) {
|
|
k++;
|
|
pix[k] = avg_intensity(get_pixel(coords,float(i)*dxtex,
|
|
float(j)*dytex));
|
|
}
|
|
}
|
|
|
|
// average color differences around neighboring pixels
|
|
delta = (abs(pix[1]-pix[7])+
|
|
abs(pix[5]-pix[3]) +
|
|
abs(pix[0]-pix[8])+
|
|
abs(pix[2]-pix[6])
|
|
)/4.;
|
|
|
|
//return clamp(5.5*delta,0.0,1.0);
|
|
return clamp(edge_thres2*delta,0.0,1.0);
|
|
}
|
|
|
|
void main() {
|
|
vec2 uv = vTexCoord.xy;
|
|
vec4 tc = vec4(1.0, 0.0, 0.0, 1.0);
|
|
vec3 colorOrg = texture(tex0, uv).rgb;
|
|
vec3 vHSV = RGBtoHSV(colorOrg.r,colorOrg.g,colorOrg.b);
|
|
|
|
// hue limiting
|
|
if (colors == 0.0) {
|
|
vHSV.y = 0.0;
|
|
} else {
|
|
float hue_divider = (360.0/colors);
|
|
vHSV.x = round(vHSV.x/hue_divider)*hue_divider;
|
|
|
|
float sat_divider = 100.0/sat_levels;
|
|
vHSV.y = round((vHSV.y*100.0)/sat_divider)*sat_divider/100.0;
|
|
}
|
|
|
|
float bri_divider = 100.0/bri_levels;
|
|
vHSV.z = round((vHSV.z*100.0)/bri_divider)*bri_divider/100.0;
|
|
|
|
float edg = IsEdge(uv);
|
|
vec3 vRGB = (edg >= (1.0-((edge_thres-1.0)*0.01)))? vec3(0.0,0.0,0.0):HSVtoRGB(vHSV.x,vHSV.y,vHSV.z);
|
|
tc = vec4(vRGB.x,vRGB.y,vRGB.z, 1);
|
|
FragColor = tc;
|
|
} |