1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
uniform sampler2D tex;
uniform float red;
uniform float green;
uniform float blue;
uniform float blend;
uniform int mode;
const int NORMAL = 0;
const int MULTIPLY = 1;
const int SCREEN = 2;
const int OVERLAY = 3;
const int DARKEN = 4;
const int LIGHTEN = 5;
const int PLUS_DARKER = 6;
const int PLUS_LIGHTER = 7;
const int COLOR_DODGE = 8;
const int COLOR_BURN = 9;
const int HARD_LIGHT = 10;
const int SOFT_LIGHT = 11;
const int DIFFERENCE = 12;
const int EXCLUSION = 13;
const int HUE = 14;
const int SATURATION = 15;
const int COLOR = 16;
const int LUMINOSITY = 17;
vec3 rgb_to_hsl(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsl_to_rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
float soft_light_channel(float base, float _blend) {
if (_blend < 0.5) {
return base - (1.0 - 2.0 * _blend) * base * (1.0 - base);
} else {
float d = (base < 0.25)
? ((16.0 * base - 12.0) * base + 4.0) * base
: sqrt(base);
return base + (2.0 * _blend - 1.0) * (d - base);
}
}
vec3 get_blend(vec3 base, vec3 _blend) {
if (mode == MULTIPLY) return base * _blend;
if (mode == SCREEN) return 1 - (1 - base) * (1 - _blend);
if (mode == OVERLAY) {
vec3 result;
result.r = base.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r));
result.g = base.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g));
result.b = base.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b));
return result;
}
if (mode == DARKEN) return min(base, _blend);
if (mode == LIGHTEN) return max(base, _blend);
if (mode == PLUS_DARKER) return base + _blend - 1;
if (mode == PLUS_LIGHTER) return base + _blend;
if (mode == COLOR_DODGE) return base / (1 - _blend);
if (mode == COLOR_BURN) return 1 - (1 - base) / _blend;
if (mode == HARD_LIGHT) {
vec3 result;
result.r = _blend.r < 0.5 ? (2.0 * base.r * _blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - _blend.r));
result.g = _blend.g < 0.5 ? (2.0 * base.g * _blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - _blend.g));
result.b = _blend.b < 0.5 ? (2.0 * base.b * _blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - _blend.b));
return result;
}
if (mode == SOFT_LIGHT) {
return vec3(soft_light_channel(base.r, _blend.r), soft_light_channel(base.g, _blend.g), soft_light_channel(base.b, _blend.b));
}
if (mode == DIFFERENCE) return abs(base - _blend);
if (mode == EXCLUSION) return 0.5 - 2 * (base - 0.5) * (_blend - 0.5);
if (mode == HUE) {
vec3 base_hsl = rgb_to_hsl(base);
vec3 blend_hsl = rgb_to_hsl(_blend);
return hsl_to_rgb(vec3(blend_hsl.x, base_hsl.y, base_hsl.z));
}
if (mode == SATURATION) {
vec3 base_hsl = rgb_to_hsl(base);
vec3 blend_hsl = rgb_to_hsl(_blend);
return hsl_to_rgb(vec3(base_hsl.x, blend_hsl.y, base_hsl.z));
}
if (mode == COLOR) {
vec3 base_hsl = rgb_to_hsl(base);
vec3 blend_hsl = rgb_to_hsl(_blend);
return hsl_to_rgb(vec3(blend_hsl.x, blend_hsl.y, base_hsl.z));
}
if (mode == LUMINOSITY) {
vec3 base_hsl = rgb_to_hsl(base);
vec3 blend_hsl = rgb_to_hsl(_blend);
return hsl_to_rgb(vec3(base_hsl.x, base_hsl.y, blend_hsl.z));
}
return _blend; // For NORMAL
}
void main() {
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
vec3 pix_color = c.xyz;
vec3 color = get_blend(pix_color, vec3(red, green, blue));
cogl_color_out = vec4(mix(pix_color, color, blend), 1.);
}
|