1// VERTEX_SHADER:
2// blend.glsl
3
4void main() {
5  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
6
7  vUv = vec2(aUv.x, aUv.y);
8}
9
10// FRAGMENT_SHADER:
11// blend.glsl
12
13uniform int u_mode;
14uniform sampler2D u_source2;
15
16float
17combine (float source, float backdrop)
18{
19  return source + backdrop * (1.0 - source);
20}
21
22vec4
23composite (vec4 Cs, vec4 Cb, vec3 B)
24{
25  float ao = Cs.a + Cb.a * (1.0 - Cs.a);
26  vec3 Co = (Cs.a*(1.0 - Cb.a)*Cs.rgb + Cs.a*Cb.a*B + (1.0 - Cs.a)*Cb.a*Cb.rgb) / ao;
27  return vec4(Co, ao);
28}
29
30vec4
31normal (vec4 Cs, vec4 Cb)
32{
33  return composite (Cs, Cb, Cs.rgb);
34}
35
36vec4
37multiply (vec4 Cs, vec4 Cb)
38{
39  return composite (Cs, Cb, Cs.rgb * Cb.rgb);
40}
41
42vec4
43difference (vec4 Cs, vec4 Cb)
44{
45  return composite (Cs, Cb, abs(Cs.rgb - Cb.rgb));
46}
47
48vec4
49screen (vec4 Cs, vec4 Cb)
50{
51  return composite (Cs, Cb, Cs.rgb + Cb.rgb - Cs.rgb * Cb.rgb);
52}
53
54float
55hard_light (float source, float backdrop)
56{
57  if (source <= 0.5)
58    return 2.0 * backdrop * source;
59  else
60    return 2.0 * (backdrop + source - backdrop * source) - 1.0;
61}
62
63vec4
64hard_light (vec4 Cs, vec4 Cb)
65{
66  vec3 B = vec3 (hard_light (Cs.r, Cb.r),
67                 hard_light (Cs.g, Cb.g),
68                 hard_light (Cs.b, Cb.b));
69  return composite (Cs, Cb, B);
70}
71
72float
73soft_light (float source, float backdrop)
74{
75  float db;
76
77  if (backdrop <= 0.25)
78    db = ((16.0 * backdrop - 12.0) * backdrop + 4.0) * backdrop;
79  else
80    db = sqrt (backdrop);
81
82  if (source <= 0.5)
83    return backdrop - (1.0 - 2.0 * source) * backdrop * (1.0 - backdrop);
84  else
85    return backdrop + (2.0 * source - 1.0) * (db - backdrop);
86}
87
88vec4
89soft_light (vec4 Cs, vec4 Cb)
90{
91  vec3 B = vec3 (soft_light (Cs.r, Cb.r),
92                 soft_light (Cs.g, Cb.g),
93                 soft_light (Cs.b, Cb.b));
94  return composite (Cs, Cb, B);
95}
96
97vec4
98overlay (vec4 Cs, vec4 Cb)
99{
100  vec3 B = vec3 (hard_light (Cb.r, Cs.r),
101                 hard_light (Cb.g, Cs.g),
102                 hard_light (Cb.b, Cs.b));
103  return composite (Cs, Cb, B);
104}
105
106vec4
107darken (vec4 Cs, vec4 Cb)
108{
109  vec3 B = min (Cs.rgb, Cb.rgb);
110  return composite (Cs, Cb, B);
111}
112
113vec4
114lighten (vec4 Cs, vec4 Cb)
115{
116  vec3 B = max (Cs.rgb, Cb.rgb);
117  return composite (Cs, Cb, B);
118}
119
120float
121color_dodge (float source, float backdrop)
122{
123  return (source == 1.0) ? source : min (backdrop / (1.0 - source), 1.0);
124}
125
126vec4
127color_dodge (vec4 Cs, vec4 Cb)
128{
129  vec3 B = vec3 (color_dodge (Cs.r, Cb.r),
130                 color_dodge (Cs.g, Cb.g),
131                 color_dodge (Cs.b, Cb.b));
132  return composite (Cs, Cb, B);
133}
134
135
136float
137color_burn (float source, float backdrop)
138{
139  return (source == 0.0) ? source : max ((1.0 - ((1.0 - backdrop) / source)), 0.0);
140}
141
142vec4
143color_burn (vec4 Cs, vec4 Cb)
144{
145  vec3 B = vec3 (color_burn (Cs.r, Cb.r),
146                 color_burn (Cs.g, Cb.g),
147                 color_burn (Cs.b, Cb.b));
148  return composite (Cs, Cb, B);
149}
150
151vec4
152exclusion (vec4 Cs, vec4 Cb)
153{
154  vec3 B = Cb.rgb + Cs.rgb - 2.0 * Cb.rgb * Cs.rgb;
155  return composite (Cs, Cb, B);
156}
157
158float
159lum (vec3 c)
160{
161  return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
162}
163
164vec3
165clip_color (vec3 c)
166{
167  float l = lum (c);
168  float n = min (c.r, min (c.g, c.b));
169  float x = max (c.r, max (c.g, c.b));
170  if (n < 0.0) c = l + (((c - l) * l) / (l - n));
171  if (x > 1.0) c = l + (((c - l) * (1.0 - l)) / (x - l));
172  return c;
173}
174
175vec3
176set_lum (vec3 c, float l)
177{
178  float d = l - lum (c);
179  return clip_color (vec3 (c.r + d, c.g + d, c.b + d));
180}
181
182float
183sat (vec3 c)
184{
185  return max (c.r, max (c.g, c.b)) - min (c.r, min (c.g, c.b));
186}
187
188vec3
189set_sat (vec3 c, float s)
190{
191  float cmin = min (c.r, min (c.g, c.b));
192  float cmax = max (c.r, max (c.g, c.b));
193  vec3 res;
194
195  if (cmax == cmin)
196    res = vec3 (0, 0, 0);
197  else
198    {
199      if (c.r == cmax)
200        {
201          if (c.g == cmin)
202            {
203              res.b = ((c.b - cmin) * s) / (cmax - cmin);
204              res.g = 0.0;
205            }
206          else
207            {
208              res.g = ((c.g - cmin) * s) / (cmax - cmin);
209              res.b = 0.0;
210            }
211          res.r = s;
212        }
213      else if (c.g == cmax)
214        {
215          if (c.r == cmin)
216            {
217              res.b = ((c.b - cmin) * s) / (cmax - cmin);
218              res.r = 0.0;
219            }
220          else
221            {
222              res.r = ((c.r - cmin) * s) / (cmax - cmin);
223              res.b = 0.0;
224            }
225          res.g = s;
226        }
227      else
228        {
229          if (c.r == cmin)
230            {
231              res.g = ((c.g - cmin) * s) / (cmax - cmin);
232              res.r = 0.0;
233            }
234          else
235            {
236              res.r = ((c.r - cmin) * s) / (cmax - cmin);
237              res.g = 0.0;
238            }
239          res.b = s;
240        }
241    }
242  return res;
243}
244
245vec4
246color (vec4 Cs, vec4 Cb)
247{
248  vec3 B = set_lum (Cs.rgb, lum (Cb.rgb));
249  return composite (Cs, Cb, B);
250}
251
252vec4
253hue (vec4 Cs, vec4 Cb)
254{
255  vec3 B = set_lum (set_sat (Cs.rgb, sat (Cb.rgb)), lum (Cb.rgb));
256  return composite (Cs, Cb, B);
257}
258
259vec4
260saturation (vec4 Cs, vec4 Cb)
261{
262  vec3 B = set_lum (set_sat (Cb.rgb, sat (Cs.rgb)), lum (Cb.rgb));
263  return composite (Cs, Cb, B);
264}
265
266vec4
267luminosity (vec4 Cs, vec4 Cb)
268{
269  vec3 B = set_lum (Cb.rgb, lum (Cs.rgb));
270  return composite (Cs, Cb, B);
271}
272
273void main() {
274  vec4 bottom_color = GskTexture(u_source, vUv);
275  vec4 top_color = GskTexture(u_source2, vUv);
276
277  vec4 result;
278  if (u_mode == 0)
279    result = normal(top_color, bottom_color);
280  else if (u_mode == 1)
281    result = multiply(top_color, bottom_color);
282  else if (u_mode == 2)
283    result = screen(top_color, bottom_color);
284  else if (u_mode == 3)
285    result = overlay(top_color, bottom_color);
286  else if (u_mode == 4)
287    result = darken(top_color, bottom_color);
288  else if (u_mode == 5)
289    result = lighten(top_color, bottom_color);
290  else if (u_mode == 6)
291    result = color_dodge(top_color, bottom_color);
292  else if (u_mode == 7)
293    result = color_burn(top_color, bottom_color);
294  else if (u_mode == 8)
295    result = hard_light(top_color, bottom_color);
296  else if (u_mode == 9)
297    result = soft_light(top_color, bottom_color);
298  else if (u_mode == 10)
299    result = difference(top_color, bottom_color);
300  else if (u_mode == 11)
301    result = exclusion(top_color, bottom_color);
302  else if (u_mode == 12)
303    result = color(top_color, bottom_color);
304  else if (u_mode == 13)
305    result = hue(top_color, bottom_color);
306  else if (u_mode == 14)
307    result = saturation(top_color, bottom_color);
308  else if (u_mode == 15)
309    result = luminosity(top_color, bottom_color);
310  else
311    discard;
312
313  gskSetScaledOutputColor(result, u_alpha);
314}
315