| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- shader_type canvas_item;
- // 输入参数
- uniform int PaletteCount;
- uniform vec4 BasicColor[8] : source_color;
- uniform vec4 ModulateColor[8] : source_color;
- uniform float Tolerance[8];
- uniform int BlendMode[8];
- //#define DEBUG
- #ifdef DEBUG
- uniform sampler2D BlendTexture : source_color;
- #endif
- // ################################################################################################
- // ################################################################################################
- // ################################################################################################
- // ClusteringColor by CIEDE2000
- // https://www.shadertoy.com/view/msXyz8
- const float epsilon = 0.00001;
- float my_sin(float x) { return sin(radians(x)); }
- float my_cos(float x) { return cos(radians(x)); }
- float my_atan(float y, float x) {
- float v = degrees(atan(y, x));
- return (v < 0.0) ? v + 360.0 : v;
- }
- float get_h(float a, float b) {
- bool a_and_b_are_zeros = (abs(a) < epsilon)&&(abs(b) < epsilon);
- return a_and_b_are_zeros ? 0.0 : my_atan(b, a);
- }
- float get_delta_h(float C1, float C2, float h1, float h2) {
- float diff = h2 - h1;
- return (C1 * C2 < epsilon) ? 0.0 :
- (abs(diff) <= 180.0) ? diff :
- (diff > 180.0) ? diff - 360.0 :
- diff + 360.0;
- }
- float get_h_bar(float C1, float C2, float h1, float h2) {
- float dist = abs(h1 - h2);
- float sum = h1 + h2;
- return (C1 * C2 < epsilon) ? h1 + h2 :
- (dist <= 180.0) ? 0.5 * sum :
- (sum < 360.0) ? 0.5 * (sum + 360.0) :
- 0.5 * (sum - 360.0);
- }
- float calculate_CIEDE2000(vec3 Lab1, vec3 Lab2) {
- float L1 = Lab1.x;
- float a1 = Lab1.y;
- float b1 = Lab1.z;
- float L2 = Lab2.x;
- float a2 = Lab2.y;
- float b2 = Lab2.z;
- float C1_ab = sqrt(a1 * a1 + b1 * b1);
- float C2_ab = sqrt(a2 * a2 + b2 * b2);
- float C_ab_bar = 0.5 * (C1_ab + C2_ab);
- float G = 0.5 * (1.0 - sqrt(pow(C_ab_bar, 7.0) / (pow(C_ab_bar, 7.0) + pow(25.0, 7.0))));
- float a_1 = (1.0 + G) * a1;
- float a_2 = (1.0 + G) * a2;
- float C1 = sqrt(a_1 * a_1 + b1 * b1);
- float C2 = sqrt(a_2 * a_2 + b2 * b2);
- float h1 = get_h(a_1, b1);
- float h2 = get_h(a_2, b2);
- float delta_L = L2 - L1;
- float delta_C = C2 - C1;
- float delta_h = get_delta_h(C1, C2, h1, h2);
- float delta_H = 2.0 * sqrt(C1 * C2) * my_sin(0.5 * delta_h);
- float L_bar = 0.5 * (L1 + L2);
- float C_bar = 0.5 * (C1 + C2);
- float h_bar = get_h_bar(C1, C2, h1, h2);
- float T = 1.0 - 0.17 * my_cos(h_bar - 30.0) + 0.24 * my_cos(2.0 * h_bar) +
- 0.32 * my_cos(3.0 * h_bar + 6.0) - 0.20 * my_cos(4.0 * h_bar - 63.0);
- float delta_theta = 30.0 * exp(-((h_bar - 275.0) / 25.0) * ((h_bar - 275.0) / 25.0));
- float R_C = 2.0 * sqrt(pow(C_bar, 7.0) / (pow(C_bar, 7.0) + pow(25.0, 7.0)));
- float S_L = 1.0 + (0.015 * (L_bar - 50.0) * (L_bar - 50.0)) / sqrt(20.0 + (L_bar - 50.0) * (L_bar - 50.0));
- float S_C = 1.0 + 0.045 * C_bar;
- float S_H = 1.0 + 0.015 * C_bar * T;
- float R_T = -my_sin(2.0 * delta_theta) * R_C;
- const float k_L = 1.0;
- const float k_C = 1.0;
- const float k_H = 1.0;
- float deltaL = delta_L / (k_L * S_L);
- float deltaC = delta_C / (k_C * S_C);
- float deltaH = delta_H / (k_H * S_H);
- float delta_E_squared = deltaL * deltaL + deltaC * deltaC + deltaH * deltaH + R_T * deltaC * deltaH;
- return sqrt(delta_E_squared);
- }
- //--- RGB2Lab
- vec3 rgb2xyz(vec3 c) {
- vec3 tmp;
- tmp.x = (c.r > 0.04045) ? pow((c.r + 0.055) / 1.055, 2.4) : c.r / 12.92;
- tmp.y = (c.g > 0.04045) ? pow((c.g + 0.055) / 1.055, 2.4) : c.g / 12.92;
- tmp.z = (c.b > 0.04045) ? pow((c.b + 0.055) / 1.055, 2.4) : c.b / 12.92;
- return 100.0 * tmp * mat3(vec3(0.4124, 0.3576, 0.1805), vec3(0.2126, 0.7152, 0.0722), vec3(0.0193, 0.1192, 0.9505));
- }
- vec3 xyz2lab(vec3 c) {
- vec3 n = c / vec3(95.047, 100.0, 108.883);
- vec3 v;
- v.x = (n.x > 0.008856) ? pow(n.x, 1.0 / 3.0) : (7.787 * n.x) + (16.0 / 116.0);
- v.y = (n.y > 0.008856) ? pow(n.y, 1.0 / 3.0) : (7.787 * n.y) + (16.0 / 116.0);
- v.z = (n.z > 0.008856) ? pow(n.z, 1.0 / 3.0) : (7.787 * n.z) + (16.0 / 116.0);
- return vec3((116.0 * v.y) - 16.0, 500.0 * (v.x - v.y), 200.0 * (v.y - v.z));
- }
- vec3 rgb2lab(vec3 c) {
- vec3 lab = xyz2lab(rgb2xyz(c));
- return vec3(lab.x / 100.0, 0.5 + 0.5 * (lab.y / 127.0), 0.5 + 0.5 * (lab.z / 127.0));
- }
- float colorCompare(vec3 rgb1, vec3 rgb2) {
- vec3 lab1 = rgb2lab(rgb1);
- vec3 lab2 = rgb2lab(rgb2);
- return calculate_CIEDE2000(lab1, lab2);
- }
- // ################################################################################################
- // ################################################################################################
- // ################################################################################################
- // blends modes
- // https://en.wikipedia.org/wiki/Blend_modes
- // pdf page 389 blend mode: https://developer.adobe.com/document-services/docs/assets/5b15559b96303194340b99820d3a70fa/PDF_ISO_32000-2.pdf
- // functions
- #define VEC3(C, FUNC) vec3(FUNC(C.r), FUNC(C.g), FUNC(C.b))
- #define MAKE_VEC3(BASE, BLEND, FUNC) vec3(FUNC(BASE.r, BLEND.r), FUNC(BASE.g, BLEND.g), FUNC(BASE.b, BLEND.b))
- #define CMIN(C) min(C.r, min(C.g, C.b))
- #define CMAX(C) max(C.r, max(C.g, C.b))
- float unionAlpha(float b, float s) { return b + s * (1.0 - b); }
- float getLum(vec3 c) { return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b; } // Luminosity
- vec3 clipColor(vec3 c)
- {
- float l = getLum(c);
- float n = CMIN(c);
- float x = CMAX(c);
- if (n < 0.0) return l + (((c - l) * l) / (l - n));
- if (x > 1.0) return l + (((c - l) * (1.0 - l)) / (l - n));
- return c;
- }
- vec3 setLum(vec3 c, float l)
- {
- float d = l - getLum(c);
- c += d;
- return clipColor(c);
- }
- float getSat(vec3 c) { return CMAX(c) - CMIN(c); } // Saturation
- vec3 setSat(vec3 C, float s)
- {
- // subscripts for Cmin, Cmid, and Cmax
- int indices[3];
- if (C.x <= C.y) {
- if (C.y <= C.z) indices = int[3](0, 1, 2); // x <= y <= z
- else if (C.x <= C.z) indices = int[3](0, 2, 1); // x <= z < y
- else indices = int[3](2, 0, 1); // z < x <= y
- } else {
- if (C.x <= C.z) indices = int[3](1, 0, 2); // y < x <= z
- else if (C.y <= C.z)indices = int[3](1, 2, 0); // y <= z < x
- else indices = int[3](2, 1, 0); // z < y < x
- }
- // set Saturation
- if (C[indices[2]] > C[indices[0]])
- {
- C[indices[1]] = (((C[indices[1]] - C[indices[0]]) * s) / (C[indices[2]] - C[indices[0]]));
- C[indices[2]] = s;
- } else {
- C[indices[1]] = 0.0;
- C[indices[2]] = 0.0;
- }
- C[indices[0]] = 0.0;
- return C;
- }
- // 正常
- vec3 normal( vec3 Cb, vec3 Cs ) { return Cs; }
- // 正片叠底
- float _multiply( float Cb, float Cs ) { return Cb * Cs; }
- vec3 multiply( vec3 Cb, vec3 Cs ) { return Cb * Cs; }
- // 滤色
- float _screen( float Cb, float Cs ) { return Cb + Cs - Cb * Cs; }
- vec3 screen( vec3 Cb, vec3 Cs ) { return Cb + Cs - Cb * Cs; }
- // 变暗
- vec3 darken( vec3 Cb, vec3 Cs ) { return min(Cb, Cs); }
- // 变亮
- vec3 lighten( vec3 Cb, vec3 Cs ) { return max(Cb, Cs); }
- // 颜色减淡
- float _colorDodge( float Cb, float Cs )
- {
- if(Cb <= 0.0) return 0.0;
- else if (Cb >= (1.0 - Cs)) return 1.0;
- else return Cb / (1.0 - Cs);
- }
- vec3 colorDodge( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _colorDodge); }
- // 颜色加深
- float _colorBurn(float Cb, float Cs)
- {
- if (Cb >= 1.0) return 1.0;
- if ((1.0 - Cb) >= Cs) return 0.0;
- else return 1.0 - ((1.0 - Cb) / Cs);
- }
- vec3 colorBurn( vec3 Cb, vec3 Cs) { return MAKE_VEC3(Cb, Cs, _colorBurn); }
- // 强光
- float _hardLight( float Cb, float Cs ) { return (Cs <= 0.5) ? _multiply(Cb, 2.0 * Cs): _screen(Cb, 2.0 * Cs - 1.0); }
- vec3 hardLight( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _hardLight); }
- // 柔光
- float _softLight( float Cb, float Cs )
- {
- if(Cs <= 0.5) return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
- else
- {
- float d = (Cb <= 0.25) ? ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb : sqrt(Cb);
- return Cb + (2.0 * Cs - 1.0) * (d - Cb);
- }
- }
- vec3 softLight( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _softLight); }
- // 叠加
- vec3 overlay( vec3 Cb, vec3 Cs ) { return hardLight(Cs, Cb); }
- // 差值
- vec3 difference( vec3 Cb, vec3 Cs ) { return abs(Cb - Cs); }
- // 排除
- vec3 exclusion( vec3 Cb, vec3 Cs ) { return Cb + Cs - 2.0 * Cb * Cs; }
- // 色相
- vec3 hue( vec3 Cb, vec3 Cs ) { return setLum(setSat(Cs, getSat(Cb)), getLum(Cb)); }
- // 颜色
- vec3 color( vec3 Cb, vec3 Cs ) { return setLum(Cs, getLum(Cb)); }
- // 饱和度
- vec3 saturation( vec3 Cb, vec3 Cs ) { return setLum(setSat(Cb, getSat(Cs)), getLum(Cb)); }
- // 明度
- vec3 luminosity( vec3 Cb, vec3 Cs ) { return setLum(Cb, getLum(Cs)); }
- // 剩下的不在pdf标准中
- // 线性加深
- float _linearBurn(float Cb, float Cs) { return max(0, Cb + Cs - 1.0); }
- vec3 linearBurn( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _linearBurn); }
- // 深色
- vec3 darkerColor( vec3 Cb, vec3 Cs ) { return getLum(Cb) < getLum(Cs)? Cb: Cs; }
- // 线性减淡(添加)
- float _linearDodge(float Cb, float Cs) { return min(1.0, Cb + Cs); }
- vec3 linearDodge( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _linearDodge); }
- // 浅色
- vec3 lighterColor( vec3 Cb, vec3 Cs ) { return getLum(Cb) > getLum(Cs)? Cb: Cs; }
- // 亮光
- float _vividLight( float Cb, float Cs ) { return (Cs <= 0.5) ? _colorBurn(Cb, 2.0 * Cs): _colorDodge(Cb, 2.0 * (Cs - 0.5)); }
- vec3 vividLight( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _vividLight); }
- // 线性光
- float _linearLight( float Cb, float Cs ) { return (Cs <= 0.5) ? _linearBurn(Cb, 2.0 * Cs): _linearDodge(Cb, 2.0 * (Cs - 0.5)); }
- vec3 linearLight( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _linearLight); }
- // 点光
- float _pinLight( float Cb, float Cs ) { return (Cs <= 0.5) ? min(Cb,2.0 * Cs) : max(Cb,2.0 * (Cs - 0.5)); }
- vec3 pinLight( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _pinLight); }
- // 实色混合
- float _hardMix( float Cb, float Cs ) { return (Cb + Cs >= 1.0) ? 1.0 : 0.0; }
- vec3 hardMix( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _hardMix); }
- // 减去
- vec3 subtract( vec3 Cb, vec3 Cs ) { return max(vec3(0.0), Cb - Cs); }
- // 划分
- float _divide( float Cb, float Cs ) { return Cs > 0.0 ? min(1.0, Cb / Cs) : 1.0; }
- vec3 divide( vec3 Cb, vec3 Cs ) { return MAKE_VEC3(Cb, Cs, _divide); }
- vec3 blendFunctions( vec3 Cb, vec3 Cs, int id )
- {
- if(id==0) return normal(Cb,Cs); // 正常
- if(id==1) return darken(Cb,Cs); // 变暗
- if(id==2) return multiply(Cb,Cs); // 正片叠底
- if(id==3) return colorBurn(Cb,Cs); // 颜色加深
- if(id==4) return linearBurn(Cb,Cs); // 线性加深
- if(id==5) return darkerColor(Cb,Cs); // 深色
- if(id==6) return lighten(Cb,Cs); // 变亮
- if(id==7) return screen(Cb,Cs); // 滤色
- if(id==8) return colorDodge(Cb,Cs); // 颜色减淡
- if(id==9) return linearDodge(Cb,Cs); // 线性减淡(添加)
- if(id==10) return lighterColor(Cb,Cs); // 浅色
- if(id==11) return overlay(Cb,Cs); // 叠加
- if(id==12) return softLight(Cb,Cs); // 柔光
- if(id==13) return hardLight(Cb,Cs); // 强光
- if(id==14) return vividLight(Cb,Cs); // 亮光
- if(id==15) return linearLight(Cb,Cs); // 线性光
- if(id==16) return pinLight(Cb,Cs); // 点光
- if(id==17) return hardMix(Cb,Cs); // 实色混合
- if(id==18) return difference(Cb,Cs); // 差值
- if(id==19) return exclusion(Cb,Cs); // 排除
- if(id==20) return subtract(Cb,Cs); // 减去
- if(id==21) return divide(Cb,Cs); // 划分
- if(id==22) return hue(Cb,Cs); // 色相
- if(id==23) return saturation(Cb,Cs); // 饱和度
- if(id==24) return color(Cb,Cs); // 颜色
- if(id==25) return luminosity(Cb,Cs); // 明度
- return vec3(0.0);
- }
- // ################################################################################################
- // ################################################################################################
- // ################################################################################################
- // gd shader script
- void fragment() {
- COLOR = texture(TEXTURE, UV);
- for (int i =0; i< PaletteCount; i++)
- {
- vec4 modulate_color = ModulateColor[i];
- vec4 basic_color = BasicColor[i];
- int blend_mode = BlendMode[i];
- float tolerance = Tolerance[i];
- // 将容差转换为0-1范围的阈值
- float tolerance_factor = tolerance / 100.0;
- // Backdrop colour 背景色
- vec3 Cb = COLOR.rgb;
- float Ab = COLOR.a;
- // Source colour 混合色
- #ifdef DEBUG
- vec4 source_colour = texture(BlendTexture, UV);
- vec3 Cs = source_colour.rgb;
- float As = source_colour.a;
- #else
- vec4 source_colour = modulate_color;
- vec3 Cs = source_colour.rgb;
- float As = Ab > 0.0? source_colour.a: 0.0;
- #endif
- // Result colour
- float Ar = unionAlpha(Ab, As);
- vec3 Cr = (1.0 - As / Ar) * Cb + As / Ar * ((1.0 - Ab) * Cs + Ab * blendFunctions(Cb, Cs, blend_mode));
- // 混合原始颜色和调制后的颜色
- if (tolerance_factor >= 1.0)
- COLOR = vec4(Cr, Ar);
- else
- {
- // 计算颜色差异
- float dis = colorCompare(Cb, basic_color.rgb);
- if (dis < tolerance_factor)
- COLOR = vec4(Cr, Ar);
- }
- }
- }
|