ee413c1e4de95cf780bb4656f15180353e30f14b
[blender.git] / source / blender / gpu / shaders / gpu_shader_material.glsl
1
2 float exp_blender(float f)
3 {
4         return pow(2.71828182846, f);
5 }
6
7 float compatible_pow(float x, float y)
8 {
9         if(y == 0.0) /* x^0 -> 1, including 0^0 */
10                 return 1.0;
11
12         /* glsl pow doesn't accept negative x */
13         if(x < 0.0) {
14                 if(mod(-y, 2.0) == 0.0)
15                         return pow(-x, y);
16                 else
17                         return -pow(-x, y);
18         }
19         else if(x == 0.0)
20                 return 0.0;
21
22         return pow(x, y);
23 }
24
25 void rgb_to_hsv(vec4 rgb, out vec4 outcol)
26 {
27         float cmax, cmin, h, s, v, cdelta;
28         vec3 c;
29
30         cmax = max(rgb[0], max(rgb[1], rgb[2]));
31         cmin = min(rgb[0], min(rgb[1], rgb[2]));
32         cdelta = cmax-cmin;
33
34         v = cmax;
35         if (cmax!=0.0)
36                 s = cdelta/cmax;
37         else {
38                 s = 0.0;
39                 h = 0.0;
40         }
41
42         if (s == 0.0) {
43                 h = 0.0;
44         }
45         else {
46                 c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta;
47
48                 if (rgb.x==cmax) h = c[2] - c[1];
49                 else if (rgb.y==cmax) h = 2.0 + c[0] -  c[2];
50                 else h = 4.0 + c[1] - c[0];
51
52                 h /= 6.0;
53
54                 if (h<0.0)
55                         h += 1.0;
56         }
57
58         outcol = vec4(h, s, v, rgb.w);
59 }
60
61 void hsv_to_rgb(vec4 hsv, out vec4 outcol)
62 {
63         float i, f, p, q, t, h, s, v;
64         vec3 rgb;
65
66         h = hsv[0];
67         s = hsv[1];
68         v = hsv[2];
69
70         if(s==0.0) {
71                 rgb = vec3(v, v, v);
72         }
73         else {
74                 if(h==1.0)
75                         h = 0.0;
76                 
77                 h *= 6.0;
78                 i = floor(h);
79                 f = h - i;
80                 rgb = vec3(f, f, f);
81                 p = v*(1.0-s);
82                 q = v*(1.0-(s*f));
83                 t = v*(1.0-(s*(1.0-f)));
84                 
85                 if (i == 0.0) rgb = vec3(v, t, p);
86                 else if (i == 1.0) rgb = vec3(q, v, p);
87                 else if (i == 2.0) rgb = vec3(p, v, t);
88                 else if (i == 3.0) rgb = vec3(p, q, v);
89                 else if (i == 4.0) rgb = vec3(t, p, v);
90                 else rgb = vec3(v, p, q);
91         }
92
93         outcol = vec4(rgb, hsv.w);
94 }
95
96 float srgb_to_linearrgb(float c)
97 {
98         if(c < 0.04045)
99                 return (c < 0.0) ? 0.0: c * (1.0 / 12.92);
100         else
101                 return pow((c + 0.055)*(1.0/1.055), 2.4);
102 }
103
104 float linearrgb_to_srgb(float c)
105 {
106         if(c < 0.0031308)
107                 return (c < 0.0) ? 0.0: c * 12.92;
108         else
109                 return 1.055 * pow(c, 1.0/2.4) - 0.055;
110 }
111
112 void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
113 {
114         col_to.r = srgb_to_linearrgb(col_from.r);
115         col_to.g = srgb_to_linearrgb(col_from.g);
116         col_to.b = srgb_to_linearrgb(col_from.b);
117         col_to.a = col_from.a;
118 }
119
120 void linearrgb_to_srgb(vec4 col_from, out vec4 col_to)
121 {
122         col_to.r = linearrgb_to_srgb(col_from.r);
123         col_to.g = linearrgb_to_srgb(col_from.g);
124         col_to.b = linearrgb_to_srgb(col_from.b);
125         col_to.a = col_from.a;
126 }
127
128 #define M_PI 3.14159265358979323846
129 #define M_1_PI 0.31830988618379069
130
131 /*********** SHADER NODES ***************/
132
133 void vcol_attribute(vec4 attvcol, out vec4 vcol)
134 {
135         vcol = vec4(attvcol.x/255.0, attvcol.y/255.0, attvcol.z/255.0, 1.0);
136 }
137
138 void uv_attribute(vec2 attuv, out vec3 uv)
139 {
140         uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0);
141 }
142
143 void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
144 {
145         local = co;
146         view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(local): vec3(0.0, 0.0, -1.0);
147         global = (viewinvmat*vec4(local, 1.0)).xyz;
148         orco = attorco;
149         uv_attribute(attuv, uv);
150         normal = -normalize(nor);       /* blender render normal is negated */
151         vcol_attribute(attvcol, vcol);
152         vcol_alpha = attvcol.a;
153         frontback = (gl_FrontFacing)? 1.0: 0.0;
154 }
155
156 void particle_info(vec4 sprops, vec3 loc, vec3 vel, vec3 avel, out float index, out float age, out float life_time, out vec3 location, out float size, out vec3 velocity, out vec3 angular_velocity)
157 {
158     index = sprops.x;
159     age = sprops.y;
160     life_time = sprops.z;
161     size = sprops.w;
162
163     location = loc;
164     velocity = vel;
165     angular_velocity = avel;
166 }
167
168 void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
169 {
170         outvec = (mat * vec4(vec, 1.0)).xyz;
171         if(domin == 1.0)
172                 outvec = max(outvec, minvec);
173         if(domax == 1.0)
174                 outvec = min(outvec, maxvec);
175 }
176
177 void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
178 {
179         outdepth = abs(co.z);
180         outdist = length(co);
181         outview = normalize(co);
182 }
183
184 void lamp(vec4 col, float energy, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac)
185 {
186         outcol = col * energy;
187         outlv = lv;
188         outdist = dist;
189         outshadow = vec4(shadow, 1.0);
190         outvisifac = visifac;
191 }
192
193 void math_add(float val1, float val2, out float outval)
194 {
195         outval = val1 + val2;
196 }
197
198 void math_subtract(float val1, float val2, out float outval)
199 {
200         outval = val1 - val2;
201 }
202
203 void math_multiply(float val1, float val2, out float outval)
204 {
205         outval = val1 * val2;
206 }
207
208 void math_divide(float val1, float val2, out float outval)
209 {
210         if (val2 == 0.0)
211                 outval = 0.0;
212         else
213                 outval = val1 / val2;
214 }
215
216 void math_sine(float val, out float outval)
217 {
218         outval = sin(val);
219 }
220
221 void math_cosine(float val, out float outval)
222 {
223         outval = cos(val);
224 }
225
226 void math_tangent(float val, out float outval)
227 {
228         outval = tan(val);
229 }
230
231 void math_asin(float val, out float outval)
232 {
233         if (val <= 1.0 && val >= -1.0)
234                 outval = asin(val);
235         else
236                 outval = 0.0;
237 }
238
239 void math_acos(float val, out float outval)
240 {
241         if (val <= 1.0 && val >= -1.0)
242                 outval = acos(val);
243         else
244                 outval = 0.0;
245 }
246
247 void math_atan(float val, out float outval)
248 {
249         outval = atan(val);
250 }
251
252 void math_pow(float val1, float val2, out float outval)
253 {
254         if (val1 >= 0.0) {
255                 outval = compatible_pow(val1, val2);
256         }
257         else {
258                 float val2_mod_1 = mod(abs(val2), 1.0);
259
260                 if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001)
261                         outval = compatible_pow(val1, floor(val2 + 0.5));
262                 else
263                         outval = 0.0;
264         }
265 }
266
267 void math_log(float val1, float val2, out float outval)
268 {
269         if(val1 > 0.0  && val2 > 0.0)
270                 outval= log2(val1) / log2(val2);
271         else
272                 outval= 0.0;
273 }
274
275 void math_max(float val1, float val2, out float outval)
276 {
277         outval = max(val1, val2);
278 }
279
280 void math_min(float val1, float val2, out float outval)
281 {
282         outval = min(val1, val2);
283 }
284
285 void math_round(float val, out float outval)
286 {
287         outval= floor(val + 0.5);
288 }
289
290 void math_less_than(float val1, float val2, out float outval)
291 {
292         if(val1 < val2)
293                 outval = 1.0;
294         else
295                 outval = 0.0;
296 }
297
298 void math_greater_than(float val1, float val2, out float outval)
299 {
300         if(val1 > val2)
301                 outval = 1.0;
302         else
303                 outval = 0.0;
304 }
305
306 void math_modulo(float val1, float val2, out float outval)
307 {
308         if (val2 == 0.0)
309                 outval = 0.0;
310         else
311                 outval = mod(val1, val2);
312
313         /* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
314          * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
315         outval = (val1 > 0.0) ? outval : -outval;
316 }
317
318 void math_abs(float val1, out float outval)
319 {
320     outval = abs(val1);
321 }
322
323 void squeeze(float val, float width, float center, out float outval)
324 {
325         outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width)));
326 }
327
328 void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
329 {
330         outvec = v1 + v2;
331         outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
332 }
333
334 void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
335 {
336         outvec = v1 - v2;
337         outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
338 }
339
340 void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
341 {
342         outvec = v1 + v2;
343         outval = length(outvec);
344         outvec = normalize(outvec);
345 }
346
347 void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
348 {
349         outvec = vec3(0, 0, 0);
350         outval = dot(v1, v2);
351 }
352
353 void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
354 {
355         outvec = cross(v1, v2);
356         outval = length(outvec);
357         outvec /= outval;
358 }
359
360 void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
361 {
362         outval = length(v);
363         outvec = normalize(v);
364 }
365
366 void vec_math_negate(vec3 v, out vec3 outv)
367 {
368         outv = -v;
369 }
370
371 void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
372 {
373         outnor = nor;
374         outdot = -dot(dir, nor);
375 }
376
377 void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
378 {
379         outnor = normalize(nor);
380         outdot = dot(normalize(dir), nor);
381 }
382
383 void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
384 {
385         outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
386         outvec.y = texture2D(curvemap, vec2((vec.y + 1.0)*0.5, 0.0)).y;
387         outvec.z = texture2D(curvemap, vec2((vec.z + 1.0)*0.5, 0.0)).z;
388
389         if (fac != 1.0)
390                 outvec = (outvec*fac) + (vec*(1.0-fac));
391
392 }
393
394 void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
395 {
396         outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
397         outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
398         outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
399
400         if (fac != 1.0)
401                 outcol = (outcol*fac) + (col*(1.0-fac));
402
403         outcol.a = col.a;
404 }
405
406 void set_value(float val, out float outval)
407 {
408         outval = val;
409 }
410
411 void set_rgb(vec3 col, out vec3 outcol)
412 {
413         outcol = col;
414 }
415
416 void set_rgba(vec4 col, out vec4 outcol)
417 {
418         outcol = col;
419 }
420
421 void set_value_zero(out float outval)
422 {
423         outval = 0.0;
424 }
425
426 void set_value_one(out float outval)
427 {
428         outval = 1.0;
429 }
430
431 void set_rgb_zero(out vec3 outval)
432 {
433         outval = vec3(0.0);
434 }
435
436 void set_rgb_one(out vec3 outval)
437 {
438         outval = vec3(1.0);
439 }
440
441 void set_rgba_zero(out vec4 outval)
442 {
443         outval = vec4(0.0);
444 }
445
446 void set_rgba_one(out vec4 outval)
447 {
448         outval = vec4(1.0);
449 }
450
451 void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol)
452 {
453         float a = 1.0 + contrast;
454         float b = brightness - contrast*0.5;
455
456         outcol.r = max(a*col.r + b, 0.0);
457         outcol.g = max(a*col.g + b, 0.0);
458         outcol.b = max(a*col.b + b, 0.0);
459         outcol.a = col.a;
460 }
461
462 void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol)
463 {
464         fac = clamp(fac, 0.0, 1.0);
465         outcol = mix(col1, col2, fac);
466         outcol.a = col1.a;
467 }
468
469 void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol)
470 {
471         fac = clamp(fac, 0.0, 1.0);
472         outcol = mix(col1, col1 + col2, fac);
473         outcol.a = col1.a;
474 }
475
476 void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol)
477 {
478         fac = clamp(fac, 0.0, 1.0);
479         outcol = mix(col1, col1 * col2, fac);
480         outcol.a = col1.a;
481 }
482
483 void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol)
484 {
485         fac = clamp(fac, 0.0, 1.0);
486         float facm = 1.0 - fac;
487
488         outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1);
489         outcol.a = col1.a;
490 }
491
492 void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol)
493 {
494         fac = clamp(fac, 0.0, 1.0);
495         float facm = 1.0 - fac;
496
497         outcol = col1;
498
499         if(outcol.r < 0.5)
500                 outcol.r *= facm + 2.0*fac*col2.r;
501         else
502                 outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r);
503
504         if(outcol.g < 0.5)
505                 outcol.g *= facm + 2.0*fac*col2.g;
506         else
507                 outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g);
508
509         if(outcol.b < 0.5)
510                 outcol.b *= facm + 2.0*fac*col2.b;
511         else
512                 outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b);
513 }
514
515 void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol)
516 {
517         fac = clamp(fac, 0.0, 1.0);
518         outcol = mix(col1, col1 - col2, fac);
519         outcol.a = col1.a;
520 }
521
522 void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol)
523 {
524         fac = clamp(fac, 0.0, 1.0);
525         float facm = 1.0 - fac;
526
527         outcol = col1;
528
529         if(col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r;
530         if(col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g;
531         if(col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b;
532 }
533
534 void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
535 {
536         fac = clamp(fac, 0.0, 1.0);
537         outcol = mix(col1, abs(col1 - col2), fac);
538         outcol.a = col1.a;
539 }
540
541 void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
542 {
543         fac = clamp(fac, 0.0, 1.0);
544         outcol.rgb = min(col1.rgb, col2.rgb*fac);
545         outcol.a = col1.a;
546 }
547
548 void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
549 {
550         fac = clamp(fac, 0.0, 1.0);
551         outcol.rgb = max(col1.rgb, col2.rgb*fac);
552         outcol.a = col1.a;
553 }
554
555 void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol)
556 {
557         fac = clamp(fac, 0.0, 1.0);
558         outcol = col1;
559
560         if(outcol.r != 0.0) {
561                 float tmp = 1.0 - fac*col2.r;
562                 if(tmp <= 0.0)
563                         outcol.r = 1.0;
564                 else if((tmp = outcol.r/tmp) > 1.0)
565                         outcol.r = 1.0;
566                 else
567                         outcol.r = tmp;
568         }
569         if(outcol.g != 0.0) {
570                 float tmp = 1.0 - fac*col2.g;
571                 if(tmp <= 0.0)
572                         outcol.g = 1.0;
573                 else if((tmp = outcol.g/tmp) > 1.0)
574                         outcol.g = 1.0;
575                 else
576                         outcol.g = tmp;
577         }
578         if(outcol.b != 0.0) {
579                 float tmp = 1.0 - fac*col2.b;
580                 if(tmp <= 0.0)
581                         outcol.b = 1.0;
582                 else if((tmp = outcol.b/tmp) > 1.0)
583                         outcol.b = 1.0;
584                 else
585                         outcol.b = tmp;
586         }
587 }
588
589 void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol)
590 {
591         fac = clamp(fac, 0.0, 1.0);
592         float tmp, facm = 1.0 - fac;
593
594         outcol = col1;
595
596         tmp = facm + fac*col2.r;
597         if(tmp <= 0.0)
598                 outcol.r = 0.0;
599         else if((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0)
600                 outcol.r = 0.0;
601         else if(tmp > 1.0)
602                 outcol.r = 1.0;
603         else
604                 outcol.r = tmp;
605
606         tmp = facm + fac*col2.g;
607         if(tmp <= 0.0)
608                 outcol.g = 0.0;
609         else if((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0)
610                 outcol.g = 0.0;
611         else if(tmp > 1.0)
612                 outcol.g = 1.0;
613         else
614                 outcol.g = tmp;
615
616         tmp = facm + fac*col2.b;
617         if(tmp <= 0.0)
618                 outcol.b = 0.0;
619         else if((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0)
620                 outcol.b = 0.0;
621         else if(tmp > 1.0)
622                 outcol.b = 1.0;
623         else
624                 outcol.b = tmp;
625 }
626
627 void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol)
628 {
629         fac = clamp(fac, 0.0, 1.0);
630         float facm = 1.0 - fac;
631
632         outcol = col1;
633
634         vec4 hsv, hsv2, tmp;
635         rgb_to_hsv(col2, hsv2);
636
637         if(hsv2.y != 0.0) {
638                 rgb_to_hsv(outcol, hsv);
639                 hsv.x = hsv2.x;
640                 hsv_to_rgb(hsv, tmp); 
641
642                 outcol = mix(outcol, tmp, fac);
643                 outcol.a = col1.a;
644         }
645 }
646
647 void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol)
648 {
649         fac = clamp(fac, 0.0, 1.0);
650         float facm = 1.0 - fac;
651
652         outcol = col1;
653
654         vec4 hsv, hsv2;
655         rgb_to_hsv(outcol, hsv);
656
657         if(hsv.y != 0.0) {
658                 rgb_to_hsv(col2, hsv2);
659
660                 hsv.y = facm*hsv.y + fac*hsv2.y;
661                 hsv_to_rgb(hsv, outcol);
662         }
663 }
664
665 void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol)
666 {
667         fac = clamp(fac, 0.0, 1.0);
668         float facm = 1.0 - fac;
669
670         vec4 hsv, hsv2;
671         rgb_to_hsv(col1, hsv);
672         rgb_to_hsv(col2, hsv2);
673
674         hsv.z = facm*hsv.z + fac*hsv2.z;
675         hsv_to_rgb(hsv, outcol);
676 }
677
678 void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol)
679 {
680         fac = clamp(fac, 0.0, 1.0);
681         float facm = 1.0 - fac;
682
683         outcol = col1;
684
685         vec4 hsv, hsv2, tmp;
686         rgb_to_hsv(col2, hsv2);
687
688         if(hsv2.y != 0.0) {
689                 rgb_to_hsv(outcol, hsv);
690                 hsv.x = hsv2.x;
691                 hsv.y = hsv2.y;
692                 hsv_to_rgb(hsv, tmp); 
693
694                 outcol = mix(outcol, tmp, fac);
695                 outcol.a = col1.a;
696         }
697 }
698
699 void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol)
700 {
701         fac = clamp(fac, 0.0, 1.0);
702         float facm = 1.0 - fac;
703
704         vec4 one= vec4(1.0);
705         vec4 scr= one - (one - col2)*(one - col1);
706         outcol = facm*col1 + fac*((one - col1)*col2*col1 + col1*scr);
707 }
708
709 void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
710 {
711         fac = clamp(fac, 0.0, 1.0);
712
713         outcol = col1 + fac*(2.0*(col2 - vec4(0.5)));
714 }
715
716 void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
717 {
718         outcol = texture2D(colormap, vec2(fac, 0.0));
719         outalpha = outcol.a;
720 }
721
722 void rgbtobw(vec4 color, out float outval)  
723 {
724         outval = color.r*0.35 + color.g*0.45 + color.b*0.2; /* keep these factors in sync with texture.h:RGBTOBW */
725 }
726
727 void invert(float fac, vec4 col, out vec4 outcol)
728 {
729         outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac);
730         outcol.w = col.w;
731 }
732
733 void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
734 {
735         out_vec = clamp(vec, min, max);
736 }
737
738 void clamp_val(float value, float min, float max, out float out_value)
739 {
740         out_value = clamp(value, min, max);
741 }
742
743 void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
744 {
745         vec4 hsv;
746
747         rgb_to_hsv(col, hsv);
748
749         hsv[0] += (hue - 0.5);
750         if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
751         hsv[1] *= sat;
752         if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
753         hsv[2] *= value;
754         if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
755
756         hsv_to_rgb(hsv, outcol);
757
758         outcol = mix(col, outcol, fac);
759 }
760
761 void separate_rgb(vec4 col, out float r, out float g, out float b)
762 {
763         r = col.r;
764         g = col.g;
765         b = col.b;
766 }
767
768 void combine_rgb(float r, float g, float b, out vec4 col)
769 {
770         col = vec4(r, g, b, 1.0);
771 }
772
773 void separate_xyz(vec3 vec, out float x, out float y, out float z)
774 {
775         x = vec.r;
776         y = vec.g;
777         z = vec.b;
778 }
779
780 void combine_xyz(float x, float y, float z, out vec3 vec)
781 {
782         vec = vec3(x, y, z);
783 }
784
785 void separate_hsv(vec4 col, out float h, out float s, out float v)
786 {
787         vec4 hsv;
788
789         rgb_to_hsv(col, hsv);
790         h = hsv[0];
791         s = hsv[1];
792         v = hsv[2];
793 }
794
795 void combine_hsv(float h, float s, float v, out vec4 col)
796 {
797         hsv_to_rgb(vec4(h, s, v, 1.0), col);
798 }
799
800 void output_node(vec4 rgb, float alpha, out vec4 outrgb)
801 {
802         outrgb = vec4(rgb.rgb, alpha);
803 }
804
805 /*********** TEXTURES ***************/
806
807 void texture_flip_blend(vec3 vec, out vec3 outvec)
808 {
809         outvec = vec.yxz;
810 }
811
812 void texture_blend_lin(vec3 vec, out float outval)
813 {
814         outval = (1.0+vec.x)/2.0;
815 }
816
817 void texture_blend_quad(vec3 vec, out float outval)
818 {
819         outval = max((1.0+vec.x)/2.0, 0.0);
820         outval *= outval;
821 }
822
823 void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal)
824 {
825         float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0;
826         float wi = 0.5 + 0.5*sin(a);
827
828         value = wi;
829         color = vec4(wi, wi, wi, 1.0);
830         normal = vec3(0.0, 0.0, 0.0);
831 }
832
833 void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
834 {
835         color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5);
836         value = color.a;
837
838         normal.x = 2.0*(color.r - 0.5);
839         normal.y = 2.0*(0.5 - color.g);
840         normal.z = 2.0*(color.b - 0.5);
841 }
842
843 /************* MTEX *****************/
844
845 void texco_orco(vec3 attorco, out vec3 orco)
846 {
847         orco = attorco;
848 }
849
850 void texco_uv(vec2 attuv, out vec3 uv)
851 {
852         /* disabled for now, works together with leaving out mtex_2d_mapping
853            uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */
854         uv = vec3(attuv, 0.0);
855 }
856
857 void texco_norm(vec3 normal, out vec3 outnormal)
858 {
859         /* corresponds to shi->orn, which is negated so cancels
860            out blender normal negation */
861         outnormal = normalize(normal);
862 }
863
864 void texco_tangent(vec4 tangent, out vec3 outtangent)
865 {
866         outtangent = normalize(tangent.xyz);
867 }
868
869 void texco_global(mat4 viewinvmat, vec3 co, out vec3 global)
870 {
871         global = (viewinvmat*vec4(co, 1.0)).xyz;
872 }
873
874 void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object)
875 {
876         object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz;
877 }
878
879 void texco_refl(vec3 vn, vec3 view, out vec3 ref)
880 {
881         ref = view - 2.0*dot(vn, view)*vn;
882 }
883
884 void shade_norm(vec3 normal, out vec3 outnormal)
885 {
886         /* blender render normal is negated */
887         outnormal = -normalize(normal);
888 }
889
890 void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
891 {
892         float facm;
893
894         fact *= facg;
895         facm = 1.0-fact;
896
897         incol = fact*texcol + facm*outcol;
898 }
899
900 void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
901 {
902         float facm;
903
904         fact *= facg;
905         facm = 1.0-fact;
906
907         incol = (facm + fact*texcol)*outcol;
908 }
909
910 void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
911 {
912         float facm;
913
914         fact *= facg;
915         facm = 1.0-fact;
916
917         incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol);
918 }
919
920 void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
921 {
922         float facm;
923
924         fact *= facg;
925         facm = 1.0-fact;
926
927         if(outcol.r < 0.5)
928                 incol.r = outcol.r*(facm + 2.0*fact*texcol.r);
929         else
930                 incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r);
931
932         if(outcol.g < 0.5)
933                 incol.g = outcol.g*(facm + 2.0*fact*texcol.g);
934         else
935                 incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g);
936
937         if(outcol.b < 0.5)
938                 incol.b = outcol.b*(facm + 2.0*fact*texcol.b);
939         else
940                 incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b);
941 }
942
943 void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
944 {
945         incol = -fact*facg*texcol + outcol;
946 }
947
948 void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
949 {
950         incol = fact*facg*texcol + outcol;
951 }
952
953 void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
954 {
955         float facm;
956
957         fact *= facg;
958         facm = 1.0-fact;
959
960         if(texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r;
961         if(texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g;
962         if(texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b;
963 }
964
965 void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
966 {
967         float facm;
968
969         fact *= facg;
970         facm = 1.0-fact;
971
972         incol = facm*outcol + fact*abs(texcol - outcol);
973 }
974
975 void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
976 {
977         float facm, col;
978
979         fact *= facg;
980         facm = 1.0-fact;
981
982         incol.r = min(outcol.r, texcol.r) * fact + outcol.r * facm;
983         incol.g = min(outcol.g, texcol.g) * fact + outcol.g * facm;
984         incol.b = min(outcol.b, texcol.b) * fact + outcol.b * facm;
985 }
986
987 void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
988 {
989         float facm, col;
990
991         fact *= facg;
992
993         col = fact*texcol.r;
994         if(col > outcol.r) incol.r = col; else incol.r = outcol.r;
995         col = fact*texcol.g;
996         if(col > outcol.g) incol.g = col; else incol.g = outcol.g;
997         col = fact*texcol.b;
998         if(col > outcol.b) incol.b = col; else incol.b = outcol.b;
999 }
1000
1001 void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1002 {
1003         vec4 col;
1004
1005         mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
1006         incol.rgb = col.rgb;
1007 }
1008
1009 void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1010 {
1011         vec4 col;
1012
1013         mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
1014         incol.rgb = col.rgb;
1015 }
1016
1017 void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1018 {
1019         vec4 col;
1020
1021         mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
1022         incol.rgb = col.rgb;
1023 }
1024
1025 void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1026 {
1027         vec4 col;
1028
1029         mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
1030         incol.rgb = col.rgb;
1031 }
1032
1033 void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1034 {
1035         float facm;
1036
1037         fact *= facg;
1038         facm = 1.0-fact;
1039
1040         vec3 one = vec3(1.0);
1041         vec3 scr = one - (one - texcol)*(one - outcol);
1042         incol = facm*outcol + fact*((one - texcol)*outcol*texcol + outcol*scr);
1043 }
1044
1045 void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
1046 {
1047         fact *= facg;
1048
1049         if(texcol.r > 0.5)
1050                 incol.r = outcol.r + fact*(2.0*(texcol.r - 0.5));
1051         else
1052                 incol.r = outcol.r + fact*(2.0*(texcol.r) - 1.0);
1053
1054         if(texcol.g > 0.5)
1055                 incol.g = outcol.g + fact*(2.0*(texcol.g - 0.5));
1056         else
1057                 incol.g = outcol.g + fact*(2.0*(texcol.g) - 1.0);
1058
1059         if(texcol.b > 0.5)
1060                 incol.b = outcol.b + fact*(2.0*(texcol.b - 0.5));
1061         else
1062                 incol.b = outcol.b + fact*(2.0*(texcol.b) - 1.0);
1063 }
1064
1065 void mtex_value_vars(inout float fact, float facg, out float facm)
1066 {
1067         fact *= abs(facg);
1068         facm = 1.0-fact;
1069
1070         if(facg < 0.0) {
1071                 float tmp = fact;
1072                 fact = facm;
1073                 facm = tmp;
1074         }
1075 }
1076
1077 void mtex_value_blend(float outcol, float texcol, float fact, float facg, out float incol)
1078 {
1079         float facm;
1080         mtex_value_vars(fact, facg, facm);
1081
1082         incol = fact*texcol + facm*outcol;
1083 }
1084
1085 void mtex_value_mul(float outcol, float texcol, float fact, float facg, out float incol)
1086 {
1087         float facm;
1088         mtex_value_vars(fact, facg, facm);
1089
1090         facm = 1.0 - facg;
1091         incol = (facm + fact*texcol)*outcol;
1092 }
1093
1094 void mtex_value_screen(float outcol, float texcol, float fact, float facg, out float incol)
1095 {
1096         float facm;
1097         mtex_value_vars(fact, facg, facm);
1098
1099         facm = 1.0 - facg;
1100         incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol);
1101 }
1102
1103 void mtex_value_sub(float outcol, float texcol, float fact, float facg, out float incol)
1104 {
1105         float facm;
1106         mtex_value_vars(fact, facg, facm);
1107
1108         fact = -fact;
1109         incol = fact*texcol + outcol;
1110 }
1111
1112 void mtex_value_add(float outcol, float texcol, float fact, float facg, out float incol)
1113 {
1114         float facm;
1115         mtex_value_vars(fact, facg, facm);
1116
1117         fact = fact;
1118         incol = fact*texcol + outcol;
1119 }
1120
1121 void mtex_value_div(float outcol, float texcol, float fact, float facg, out float incol)
1122 {
1123         float facm;
1124         mtex_value_vars(fact, facg, facm);
1125
1126         if(texcol != 0.0)
1127                 incol = facm*outcol + fact*outcol/texcol;
1128         else
1129                 incol = 0.0;
1130 }
1131
1132 void mtex_value_diff(float outcol, float texcol, float fact, float facg, out float incol)
1133 {
1134         float facm;
1135         mtex_value_vars(fact, facg, facm);
1136
1137         incol = facm*outcol + fact*abs(texcol - outcol);
1138 }
1139
1140 void mtex_value_dark(float outcol, float texcol, float fact, float facg, out float incol)
1141 {
1142         float facm;
1143         mtex_value_vars(fact, facg, facm);
1144
1145         incol = facm*outcol + fact*min(outcol, texcol);
1146 }
1147
1148 void mtex_value_light(float outcol, float texcol, float fact, float facg, out float incol)
1149 {
1150         float facm;
1151         mtex_value_vars(fact, facg, facm);
1152
1153         float col = fact*texcol;
1154         if(col > outcol) incol = col; else incol = outcol;
1155 }
1156
1157 void mtex_value_clamp_positive(float fac, out float outfac)
1158 {
1159         outfac = max(fac, 0.0);
1160 }
1161
1162 void mtex_value_clamp(float fac, out float outfac)
1163 {
1164         outfac = clamp(fac, 0.0, 1.0);
1165 }
1166
1167 void mtex_har_divide(float har, out float outhar)
1168 {
1169         outhar = har/128.0;
1170 }
1171
1172 void mtex_har_multiply_clamp(float har, out float outhar)
1173 {
1174         har *= 128.0;
1175
1176         if(har < 1.0) outhar = 1.0;
1177         else if(har > 511.0) outhar = 511.0;
1178         else outhar = har;
1179 }
1180
1181 void mtex_alpha_from_col(vec4 col, out float alpha)
1182 {
1183         alpha = col.a;
1184 }
1185
1186 void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol)
1187 {
1188         outcol = vec4(col.rgb, alpha);
1189 }
1190
1191 void mtex_rgbtoint(vec4 rgb, out float intensity)
1192 {
1193         intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb);
1194 }
1195
1196 void mtex_value_invert(float invalue, out float outvalue)
1197 {
1198         outvalue = 1.0 - invalue;
1199 }
1200
1201 void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb)
1202 {
1203         outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a);
1204 }
1205
1206 void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity)
1207 {
1208         float fact = intensity;
1209         outintensity = intensity*stencil;
1210         outstencil = stencil*fact;
1211 }
1212
1213 void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb)
1214 {
1215         float fact = rgb.a;
1216         outrgb = vec4(rgb.rgb, rgb.a*stencil);
1217         outstencil = stencil*fact;
1218 }
1219
1220 void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
1221 {
1222         outtexco = texco + ofs;
1223 }
1224
1225 void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
1226 {
1227         outtexco = size*texco;
1228 }
1229
1230 void mtex_2d_mapping(vec3 vec, out vec3 outvec)
1231 {
1232         outvec = vec3(vec.xy*0.5 + vec2(0.5), vec.z);
1233 }
1234
1235 vec3 mtex_2d_mapping(vec3 vec)
1236 {
1237         return vec3(vec.xy*0.5 + vec2(0.5), vec.z);
1238 }
1239
1240 void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color)
1241 {
1242         color = texture2D(ima, texco.xy);
1243         value = 1.0;
1244 }
1245
1246 void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal)
1247 {
1248         // The invert of the red channel is to make
1249         // the normal map compliant with the outside world.
1250         // It needs to be done because in Blender
1251         // the normal used points inward.
1252         // Should this ever change this negate must be removed.
1253         vec4 color = texture2D(ima, texco.xy);
1254         normal = 2.0*(vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5));
1255 }
1256
1257 void mtex_bump_normals_init( vec3 vN, out vec3 vNorg, out vec3 vNacc, out float fPrevMagnitude )
1258 {
1259         vNorg = vN;
1260         vNacc = vN;
1261         fPrevMagnitude = 1.0;
1262 }
1263
1264 /** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */
1265 mat3 to_mat3(mat4 m4)
1266 {
1267         mat3 m3;
1268         m3[0] = m4[0].xyz;
1269         m3[1] = m4[1].xyz;
1270         m3[2] = m4[2].xyz;
1271         return m3;
1272 }
1273
1274 void mtex_bump_init_objspace( vec3 surf_pos, vec3 surf_norm,
1275                                                           mat4 mView, mat4 mViewInv, mat4 mObj, mat4 mObjInv, 
1276                                                           float fPrevMagnitude_in, vec3 vNacc_in,
1277                                                           out float fPrevMagnitude_out, out vec3 vNacc_out, 
1278                                                           out vec3 vR1, out vec3 vR2, out float fDet ) 
1279 {
1280         mat3 obj2view = to_mat3(gl_ModelViewMatrix);
1281         mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
1282         
1283         vec3 vSigmaS = view2obj * dFdx( surf_pos );
1284         vec3 vSigmaT = view2obj * dFdy( surf_pos );
1285         vec3 vN = normalize( surf_norm * obj2view );
1286
1287         vR1 = cross( vSigmaT, vN );
1288         vR2 = cross( vN, vSigmaS ) ;
1289         fDet = dot ( vSigmaS, vR1 );
1290         
1291         /* pretransform vNacc (in mtex_bump_apply) using the inverse transposed */
1292         vR1 = vR1 * view2obj;
1293         vR2 = vR2 * view2obj;
1294         vN = vN * view2obj;
1295         
1296         float fMagnitude = abs(fDet) * length(vN);
1297         vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
1298         fPrevMagnitude_out = fMagnitude;
1299 }
1300
1301 void mtex_bump_init_texturespace( vec3 surf_pos, vec3 surf_norm, 
1302                                                                   float fPrevMagnitude_in, vec3 vNacc_in,
1303                                                                   out float fPrevMagnitude_out, out vec3 vNacc_out, 
1304                                                                   out vec3 vR1, out vec3 vR2, out float fDet ) 
1305 {
1306         vec3 vSigmaS = dFdx( surf_pos );
1307         vec3 vSigmaT = dFdy( surf_pos );
1308         vec3 vN = surf_norm; /* normalized interpolated vertex normal */
1309         
1310         vR1 = normalize( cross( vSigmaT, vN ) );
1311         vR2 = normalize( cross( vN, vSigmaS ) );
1312         fDet = sign( dot(vSigmaS, vR1) );
1313         
1314         float fMagnitude = abs(fDet);
1315         vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
1316         fPrevMagnitude_out = fMagnitude;
1317 }
1318
1319 void mtex_bump_init_viewspace( vec3 surf_pos, vec3 surf_norm, 
1320                                                            float fPrevMagnitude_in, vec3 vNacc_in,
1321                                                            out float fPrevMagnitude_out, out vec3 vNacc_out, 
1322                                                            out vec3 vR1, out vec3 vR2, out float fDet ) 
1323 {
1324         vec3 vSigmaS = dFdx( surf_pos );
1325         vec3 vSigmaT = dFdy( surf_pos );
1326         vec3 vN = surf_norm; /* normalized interpolated vertex normal */
1327         
1328         vR1 = cross( vSigmaT, vN );
1329         vR2 = cross( vN, vSigmaS ) ;
1330         fDet = dot ( vSigmaS, vR1 );
1331         
1332         float fMagnitude = abs(fDet);
1333         vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
1334         fPrevMagnitude_out = fMagnitude;
1335 }
1336
1337 void mtex_bump_tap3( vec3 texco, sampler2D ima, float hScale, 
1338                      out float dBs, out float dBt )
1339 {
1340         vec2 STll = texco.xy;
1341         vec2 STlr = texco.xy + dFdx(texco.xy) ;
1342         vec2 STul = texco.xy + dFdy(texco.xy) ;
1343         
1344         float Hll,Hlr,Hul;
1345         rgbtobw( texture2D(ima, STll), Hll );
1346         rgbtobw( texture2D(ima, STlr), Hlr );
1347         rgbtobw( texture2D(ima, STul), Hul );
1348         
1349         dBs = hScale * (Hlr - Hll);
1350         dBt = hScale * (Hul - Hll);
1351 }
1352
1353 #ifdef BUMP_BICUBIC
1354
1355 void mtex_bump_bicubic( vec3 texco, sampler2D ima, float hScale, 
1356                      out float dBs, out float dBt ) 
1357 {
1358         float Hl;
1359         float Hr;
1360         float Hd;
1361         float Hu;
1362         
1363         vec2 TexDx = dFdx(texco.xy);
1364         vec2 TexDy = dFdy(texco.xy);
1365  
1366         vec2 STl = texco.xy - 0.5 * TexDx ;
1367         vec2 STr = texco.xy + 0.5 * TexDx ;
1368         vec2 STd = texco.xy - 0.5 * TexDy ;
1369         vec2 STu = texco.xy + 0.5 * TexDy ;
1370         
1371         rgbtobw(texture2D(ima, STl), Hl);
1372         rgbtobw(texture2D(ima, STr), Hr);
1373         rgbtobw(texture2D(ima, STd), Hd);
1374         rgbtobw(texture2D(ima, STu), Hu);
1375         
1376         vec2 dHdxy = vec2(Hr - Hl, Hu - Hd);
1377         float fBlend = clamp(1.0-textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
1378         if(fBlend!=0.0)
1379         {
1380                 // the derivative of the bicubic sampling of level 0
1381                 ivec2 vDim;
1382                 vDim = textureSize(ima, 0);
1383
1384                 // taking the fract part of the texture coordinate is a hardcoded wrap mode.
1385                 // this is acceptable as textures use wrap mode exclusively in 3D view elsewhere in blender. 
1386                 // this is done so that we can still get a valid texel with uvs outside the 0,1 range
1387                 // by texelFetch below, as coordinates are clamped when using this function.
1388                 vec2 fTexLoc = vDim*fract(texco.xy) - vec2(0.5, 0.5);
1389                 ivec2 iTexLoc = ivec2(floor(fTexLoc));
1390                 vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0);            // sat just to be pedantic
1391
1392 /*******************************************************************************************
1393  * This block will replace the one below when one channel textures are properly supported. *
1394  *******************************************************************************************
1395                 vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim );
1396                 vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim );
1397                 vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim );
1398                 vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim );
1399
1400                 mat4 H = mat4(vSamplesUL.w, vSamplesUL.x, vSamplesLL.w, vSamplesLL.x,
1401                                         vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y,
1402                                         vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x,
1403                                         vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y);
1404 */      
1405                 ivec2 iTexLocMod = iTexLoc + ivec2(-1, -1);
1406
1407                 mat4 H;
1408                 
1409                 for(int i = 0; i < 4; i++) {
1410                         for(int j = 0; j < 4; j++) {
1411                                 ivec2 iTexTmp = iTexLocMod + ivec2(i,j);
1412                                 
1413                                 // wrap texture coordinates manually for texelFetch to work on uvs oitside the 0,1 range.
1414                                 // this is guaranteed to work since we take the fractional part of the uv above.
1415                                 iTexTmp.x = (iTexTmp.x < 0)? iTexTmp.x + vDim.x : ((iTexTmp.x >= vDim.x)? iTexTmp.x - vDim.x : iTexTmp.x);
1416                                 iTexTmp.y = (iTexTmp.y < 0)? iTexTmp.y + vDim.y : ((iTexTmp.y >= vDim.y)? iTexTmp.y - vDim.y : iTexTmp.y);
1417
1418                                 rgbtobw(texelFetch(ima, iTexTmp, 0), H[i][j]);
1419                         }
1420                 }
1421                 
1422                 float x = t.x, y = t.y;
1423                 float x2 = x * x, x3 = x2 * x, y2 = y * y, y3 = y2 * y;
1424
1425                 vec4 X = vec4(-0.5*(x3+x)+x2,           1.5*x3-2.5*x2+1,        -1.5*x3+2*x2+0.5*x,             0.5*(x3-x2));
1426                 vec4 Y = vec4(-0.5*(y3+y)+y2,           1.5*y3-2.5*y2+1,        -1.5*y3+2*y2+0.5*y,             0.5*(y3-y2));
1427                 vec4 dX = vec4(-1.5*x2+2*x-0.5,         4.5*x2-5*x,                     -4.5*x2+4*x+0.5,                1.5*x2-x);
1428                 vec4 dY = vec4(-1.5*y2+2*y-0.5,         4.5*y2-5*y,                     -4.5*y2+4*y+0.5,                1.5*y2-y);
1429         
1430                 // complete derivative in normalized coordinates (mul by vDim)
1431                 vec2 dHdST = vDim * vec2(dot(Y, H * dX), dot(dY, H * X));
1432
1433                 // transform derivative to screen-space
1434                 vec2 dHdxy_bicubic = vec2( dHdST.x * TexDx.x + dHdST.y * TexDx.y,
1435                                                                    dHdST.x * TexDy.x + dHdST.y * TexDy.y );
1436
1437                 // blend between the two
1438                 dHdxy = dHdxy*(1-fBlend) + dHdxy_bicubic*fBlend;
1439         }
1440
1441         dBs = hScale * dHdxy.x;
1442         dBt = hScale * dHdxy.y;
1443 }
1444
1445 #endif
1446
1447 void mtex_bump_tap5( vec3 texco, sampler2D ima, float hScale, 
1448                      out float dBs, out float dBt ) 
1449 {
1450         vec2 TexDx = dFdx(texco.xy);
1451         vec2 TexDy = dFdy(texco.xy);
1452
1453         vec2 STc = texco.xy;
1454         vec2 STl = texco.xy - 0.5 * TexDx ;
1455         vec2 STr = texco.xy + 0.5 * TexDx ;
1456         vec2 STd = texco.xy - 0.5 * TexDy ;
1457         vec2 STu = texco.xy + 0.5 * TexDy ;
1458         
1459         float Hc,Hl,Hr,Hd,Hu;
1460         rgbtobw( texture2D(ima, STc), Hc );
1461         rgbtobw( texture2D(ima, STl), Hl );
1462         rgbtobw( texture2D(ima, STr), Hr );
1463         rgbtobw( texture2D(ima, STd), Hd );
1464         rgbtobw( texture2D(ima, STu), Hu );
1465         
1466         dBs = hScale * (Hr - Hl);
1467         dBt = hScale * (Hu - Hd);
1468 }
1469
1470 void mtex_bump_deriv( vec3 texco, sampler2D ima, float ima_x, float ima_y, float hScale, 
1471                      out float dBs, out float dBt ) 
1472 {
1473         float s = 1.0;          // negate this if flipped texture coordinate
1474         vec2 TexDx = dFdx(texco.xy);
1475         vec2 TexDy = dFdy(texco.xy);
1476         
1477         // this variant using a derivative map is described here
1478         // http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
1479         vec2 dim = vec2(ima_x, ima_y);
1480         vec2 dBduv = hScale*dim*(2.0*texture2D(ima, texco.xy).xy-1.0);
1481         
1482         dBs = dBduv.x*TexDx.x + s*dBduv.y*TexDx.y;
1483         dBt = dBduv.x*TexDy.x + s*dBduv.y*TexDy.y;
1484 }
1485
1486 void mtex_bump_apply( float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2, vec3 vNacc_in,
1487                                           out vec3 vNacc_out, out vec3 perturbed_norm ) 
1488 {
1489         vec3 vSurfGrad = sign(fDet) * ( dBs * vR1 + dBt * vR2 );
1490         
1491         vNacc_out = vNacc_in - vSurfGrad;
1492         perturbed_norm = normalize( vNacc_out );
1493 }
1494
1495 void mtex_bump_apply_texspace( float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2,
1496                                sampler2D ima, vec3 texco, float ima_x, float ima_y, vec3 vNacc_in,
1497                                                            out vec3 vNacc_out, out vec3 perturbed_norm ) 
1498 {
1499         vec2 TexDx = dFdx(texco.xy);
1500         vec2 TexDy = dFdy(texco.xy);
1501
1502         vec3 vSurfGrad = sign(fDet) * ( 
1503                     dBs / length( vec2(ima_x*TexDx.x, ima_y*TexDx.y) ) * vR1 + 
1504                     dBt / length( vec2(ima_x*TexDy.x, ima_y*TexDy.y) ) * vR2 );
1505                                 
1506         vNacc_out = vNacc_in - vSurfGrad;
1507         perturbed_norm = normalize( vNacc_out );
1508 }
1509
1510 void mtex_negate_texnormal(vec3 normal, out vec3 outnormal)
1511 {
1512         outnormal = vec3(-normal.x, -normal.y, normal.z);
1513 }
1514
1515 void mtex_nspace_tangent(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
1516 {
1517         vec3 B = tangent.w * cross(normal, tangent.xyz);
1518
1519         outnormal = texnormal.x*tangent.xyz + texnormal.y*B + texnormal.z*normal;
1520         outnormal = normalize(outnormal);
1521 }
1522
1523 void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
1524 {
1525         outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz);
1526 }
1527
1528 void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
1529 {
1530         outnormal = normalize(gl_NormalMatrix * texnormal);
1531 }
1532
1533 void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
1534 {
1535         outnormal = (1.0 - norfac)*normal + norfac*newnormal;
1536         outnormal = normalize(outnormal);
1537 }
1538
1539 /******* MATERIAL *********/
1540
1541 void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac)
1542 {
1543         lv = lampvec;
1544         dist = 1.0;
1545         visifac = 1.0;
1546 }
1547
1548 void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac)
1549 {
1550         lv = co - lampco;
1551         dist = length(lv);
1552         lv = normalize(lv);
1553         visifac = 1.0;
1554 }
1555
1556 void lamp_falloff_invlinear(float lampdist, float dist, out float visifac)
1557 {
1558         visifac = lampdist/(lampdist + dist);
1559 }
1560
1561 void lamp_falloff_invsquare(float lampdist, float dist, out float visifac)
1562 {
1563         visifac = lampdist/(lampdist + dist*dist);
1564 }
1565
1566 void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac)
1567 {
1568         float lampdistkw = lampdist*lampdist;
1569
1570         visifac = lampdist/(lampdist + ld1*dist);
1571         visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
1572 }
1573
1574 void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
1575 {
1576         visifac = texture2D(curvemap, vec2(dist/lampdist, 0.0)).x;
1577 }
1578
1579 void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
1580 {
1581         float t= lampdist - dist;
1582
1583         outvisifac= visifac*max(t, 0.0)/lampdist;
1584 }
1585
1586 void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr)
1587 {
1588         if(dot(lv, lampvec) > 0.0) {
1589                 vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
1590                 float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z));
1591
1592                 inpr = 1.0/sqrt(1.0 + x*x);
1593         }
1594         else
1595                 inpr = 0.0;
1596 }
1597
1598 void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr)
1599 {
1600         inpr = dot(lv, lampvec);
1601 }
1602
1603 void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)
1604 {
1605         float t = spotsi;
1606
1607         if(inpr <= t) {
1608                 outvisifac = 0.0;
1609         }
1610         else {
1611                 t = inpr - t;
1612
1613                 /* soft area */
1614                 if(spotbl != 0.0)
1615                         inpr *= smoothstep(0.0, 1.0, t/spotbl);
1616
1617                 outvisifac = visifac*inpr;
1618         }
1619 }
1620
1621 void lamp_visibility_clamp(float visifac, out float outvisifac)
1622 {
1623         outvisifac = (visifac < 0.001)? 0.0: visifac;
1624 }
1625
1626 void shade_view(vec3 co, out vec3 view)
1627 {
1628         /* handle perspective/orthographic */
1629         view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0);
1630 }
1631
1632 void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
1633 {
1634         vec3 c = cross(lv, tang);
1635         vec3 vnor = cross(c, tang);
1636
1637         vn = -normalize(vnor);
1638 }
1639
1640 void shade_inp(vec3 vn, vec3 lv, out float inp)
1641 {
1642         inp = dot(vn, lv);
1643 }
1644
1645 void shade_is_no_diffuse(out float is)
1646 {
1647         is = 0.0;
1648 }
1649
1650 void shade_is_hemi(float inp, out float is)
1651 {
1652         is = 0.5*inp + 0.5;
1653 }
1654
1655 float area_lamp_energy(mat4 area, vec3 co, vec3 vn)
1656 {
1657         vec3 vec[4], c[4];
1658         float rad[4], fac;
1659         
1660         vec[0] = normalize(co - area[0].xyz);
1661         vec[1] = normalize(co - area[1].xyz);
1662         vec[2] = normalize(co - area[2].xyz);
1663         vec[3] = normalize(co - area[3].xyz);
1664
1665         c[0] = normalize(cross(vec[0], vec[1]));
1666         c[1] = normalize(cross(vec[1], vec[2]));
1667         c[2] = normalize(cross(vec[2], vec[3]));
1668         c[3] = normalize(cross(vec[3], vec[0]));
1669
1670         rad[0] = acos(dot(vec[0], vec[1]));
1671         rad[1] = acos(dot(vec[1], vec[2]));
1672         rad[2] = acos(dot(vec[2], vec[3]));
1673         rad[3] = acos(dot(vec[3], vec[0]));
1674
1675         fac=  rad[0]*dot(vn, c[0]);
1676         fac+= rad[1]*dot(vn, c[1]);
1677         fac+= rad[2]*dot(vn, c[2]);
1678         fac+= rad[3]*dot(vn, c[3]);
1679
1680         return max(fac, 0.0);
1681 }
1682
1683 void shade_inp_area(vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, out float inp)
1684 {
1685         vec3 co = position;
1686         vec3 vec = co - lampco;
1687
1688         if(dot(vec, lampvec) < 0.0) {
1689                 inp = 0.0;
1690         }
1691         else {
1692                 float intens = area_lamp_energy(area, co, vn);
1693
1694                 inp = pow(intens*areasize, k);
1695         }
1696 }
1697
1698 void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is)
1699 {
1700         vec3 h = normalize(v + l);
1701         float nh = max(dot(n, h), 0.0);
1702         float nv = max(dot(n, v), 0.0);
1703         float realnl = dot(n, l);
1704
1705         if(realnl < 0.0) {
1706                 is = 0.0;
1707         }
1708         else if(nl < 0.0) {
1709                 is = 0.0;
1710         }
1711         else {
1712                 float vh = max(dot(v, h), 0.0);
1713                 float Lit_A = acos(realnl);
1714                 float View_A = acos(nv);
1715
1716                 vec3 Lit_B = normalize(l - realnl*n);
1717                 vec3 View_B = normalize(v - nv*n);
1718
1719                 float t = max(dot(Lit_B, View_B), 0.0);
1720
1721                 float a, b;
1722
1723                 if(Lit_A > View_A) {
1724                         a = Lit_A;
1725                         b = View_A;
1726                 }
1727                 else {
1728                         a = View_A;
1729                         b = Lit_A;
1730                 }
1731
1732                 float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33)));
1733                 float B = 0.45*((rough*rough)/((rough*rough) + 0.09));
1734
1735                 b *= 0.95;
1736                 is = nl*(A + (B * t * sin(a) * tan(b)));
1737         }
1738 }
1739
1740 void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is)
1741 {
1742         float rslt = dot(n, l);
1743         float ang = acos(rslt);
1744
1745         if(ang < size) is = 1.0;
1746         else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0;
1747         else is = 1.0 - ((ang - size)/tsmooth);
1748 }
1749
1750 void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is)
1751 {
1752         if(nl <= 0.0) {
1753                 is = 0.0;
1754         }
1755         else {
1756                 float nv = max(dot(n, v), 0.0);
1757
1758                 if(darkness <= 1.0)
1759                         is = nl*pow(max(nv*nl, 0.1), darkness - 1.0);
1760                 else
1761                         is = nl*pow(1.0001 - nv, darkness - 1.0);
1762         }
1763 }
1764
1765 float fresnel_fac(vec3 view, vec3 vn, float grad, float fac)
1766 {
1767         float t1, t2;
1768         float ffac;
1769
1770         if(fac==0.0) {
1771                 ffac = 1.0;
1772         }
1773         else {
1774                 t1= dot(view, vn);
1775                 if(t1>0.0)  t2= 1.0+t1;
1776                 else t2= 1.0-t1;
1777
1778                 t2= grad + (1.0-grad)*pow(t2, fac);
1779
1780                 if(t2<0.0) ffac = 0.0;
1781                 else if(t2>1.0) ffac = 1.0;
1782                 else ffac = t2;
1783         }
1784
1785         return ffac;
1786 }
1787
1788 void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is)
1789 {
1790         is = fresnel_fac(lv, vn, fac_i, fac);
1791 }
1792
1793 void shade_cubic(float is, out float outis)
1794 {
1795         if(is>0.0 && is<1.0)
1796                 outis= smoothstep(0.0, 1.0, is);
1797         else
1798                 outis= is;
1799 }
1800
1801 void shade_visifac(float i, float visifac, float refl, out float outi)
1802 {
1803         /*if(i > 0.0)*/
1804                 outi = max(i*visifac*refl, 0.0);
1805         /*else
1806                 outi = i;*/
1807 }
1808
1809 void shade_tangent_v_spec(vec3 tang, out vec3 vn)
1810 {
1811         vn = tang;
1812 }
1813
1814 void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol)
1815 {
1816         if(i > 0.0)
1817                 outcol = i*lampcol*col;
1818         else
1819                 outcol = vec3(0.0, 0.0, 0.0);
1820 }
1821
1822 void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t)
1823 {
1824         lv += view;
1825         lv = normalize(lv);
1826
1827         t = dot(vn, lv);
1828         t = 0.5*t + 0.5;
1829
1830         t = visifac*spec*pow(t, hard);
1831 }
1832
1833 void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
1834 {
1835         vec3 h = normalize(l + v);
1836         float rslt = max(dot(h, n), 0.0);
1837
1838         specfac = pow(rslt, hard);
1839 }
1840
1841 void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
1842 {
1843         vec3 h = normalize(v + l);
1844         float nh = dot(n, h);
1845
1846         if(nh < 0.0) {
1847                 specfac = 0.0;
1848         }
1849         else {
1850                 float nv = max(dot(n, v), 0.0);
1851                 float i = pow(nh, hard);
1852
1853                 i = i/(0.1+nv);
1854                 specfac = i;
1855         }
1856 }
1857
1858 void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac)
1859 {
1860         if(refrac < 1.0) {
1861                 specfac = 0.0;
1862         }
1863         else if(spec_power == 0.0) {
1864                 specfac = 0.0;
1865         }
1866         else {
1867                 if(spec_power<100.0)
1868                         spec_power= sqrt(1.0/spec_power);
1869                 else
1870                         spec_power= 10.0/spec_power;
1871
1872                 vec3 h = normalize(v + l);
1873                 float nh = dot(n, h);
1874                 if(nh < 0.0) {
1875                         specfac = 0.0;
1876                 }
1877                 else {
1878                         float nv = max(dot(n, v), 0.01);
1879                         float nl = dot(n, l);
1880                         if(nl <= 0.01) {
1881                                 specfac = 0.0;
1882                         }
1883                         else {
1884                                 float vh = max(dot(v, h), 0.01);
1885
1886                                 float a = 1.0;
1887                                 float b = (2.0*nh*nv)/vh;
1888                                 float c = (2.0*nh*nl)/vh;
1889
1890                                 float g = 0.0;
1891
1892                                 if(a < b && a < c) g = a;
1893                                 else if(b < a && b < c) g = b;
1894                                 else if(c < a && c < b) g = c;
1895
1896                                 float p = sqrt(((refrac * refrac)+(vh*vh)-1.0));
1897                                 float f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1.0+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0))));
1898                                 float ang = acos(nh);
1899
1900                                 specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0);
1901                         }
1902                 }
1903         }
1904 }
1905
1906 void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac)
1907 {
1908         vec3 h = normalize(l + v);
1909         float nh = max(dot(n, h), 0.001);
1910         float nv = max(dot(n, v), 0.001);
1911         float nl = max(dot(n, l), 0.001);
1912         float angle = tan(acos(nh));
1913         float alpha = max(rms, 0.001);
1914
1915         specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
1916 }
1917
1918 void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac)
1919 {
1920         vec3 h = normalize(l + v);
1921         float rslt = dot(h, n);
1922         float ang = acos(rslt);
1923
1924         if(ang < size) rslt = 1.0;
1925         else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0;
1926         else rslt = 1.0 - ((ang - size)/tsmooth);
1927
1928         specfac = rslt;
1929 }
1930
1931 void shade_spec_area_inp(float specfac, float inp, out float outspecfac)
1932 {
1933         outspecfac = specfac*inp;
1934 }
1935
1936 void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t)
1937 {
1938         t = shadfac*spec*visifac*specfac;
1939 }
1940
1941 void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
1942 {
1943         outcol = t*lampcol*speccol;
1944 }
1945
1946 void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha)
1947 {
1948         if (spectra > 0.0) {
1949                 float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0);
1950                 outalpha = (1.0 - t) * alpha + t;
1951         }
1952         else {
1953                 outalpha = alpha;
1954         }
1955 }
1956
1957 void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
1958 {
1959         outcol = col1 + col2;
1960 }
1961
1962 void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
1963 {
1964         outcol = col + col1*col2;
1965 }
1966
1967 void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol)
1968 {
1969         outcol = col1 + max(col2, vec4(0.0, 0.0, 0.0, 0.0));
1970 }
1971
1972 void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
1973 {
1974         outcol = col + max(col1*col2, vec4(0.0, 0.0, 0.0, 0.0));
1975 }
1976
1977 void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol)
1978 {
1979         outcol = col + f*col1;
1980 }
1981
1982 void shade_mul(vec4 col1, vec4 col2, out vec4 outcol)
1983 {
1984         outcol = col1*col2;
1985 }
1986
1987 void shade_mul_value(float fac, vec4 col, out vec4 outcol)
1988 {
1989         outcol = col*fac;
1990 }
1991
1992 void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol)
1993 {
1994         outcol = col*fac;
1995 }
1996
1997 void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
1998 {
1999         outcol = vec4(col.rgb*obcol.rgb, col.a);
2000 }
2001
2002 void ramp_rgbtobw(vec3 color, out float outval)
2003 {
2004         outval = color.r*0.3 + color.g*0.58 + color.b*0.12;
2005 }
2006
2007 void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb)
2008 {
2009         outshadrgb = i*energy*(1.0 - shadfac)*(vec3(1.0)-shadcol);
2010 }
2011
2012 void shade_only_shadow_diffuse(vec3 shadrgb, vec3 rgb, vec4 diff, out vec4 outdiff)
2013 {
2014         outdiff = diff - vec4(rgb*shadrgb, 0.0);
2015 }
2016
2017 void shade_only_shadow_specular(vec3 shadrgb, vec3 specrgb, vec4 spec, out vec4 outspec)
2018 {
2019         outspec = spec - vec4(specrgb*shadrgb, 0.0);
2020 }
2021
2022 void shade_clamp_positive(vec4 col, out vec4 outcol)
2023 {
2024         outcol = max(col, vec4(0.0));
2025 }
2026
2027 void test_shadowbuf(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, out float result)
2028 {
2029         if(inp <= 0.0) {
2030                 result = 0.0;
2031         }
2032         else {
2033                 vec4 co = shadowpersmat*vec4(rco, 1.0);
2034
2035                 //float bias = (1.5 - inp*inp)*shadowbias;
2036                 co.z -= shadowbias*co.w;
2037                 
2038                 if (co.w > 0.0 && co.x > 0.0 && co.x/co.w < 1.0 && co.y > 0.0 && co.y/co.w < 1.0)
2039                         result = shadow2DProj(shadowmap, co).x;
2040                 else
2041                         result = 1.0;
2042         }
2043 }
2044
2045 void test_shadowbuf_vsm(vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float shadowbias, float bleedbias, float inp, out float result)
2046 {
2047         if(inp <= 0.0) {
2048                 result = 0.0;
2049         }
2050         else {
2051                 vec4 co = shadowpersmat*vec4(rco, 1.0);
2052                 if (co.w > 0.0 && co.x > 0.0 && co.x/co.w < 1.0 && co.y > 0.0 && co.y/co.w < 1.0) {
2053                         vec2 moments = texture2DProj(shadowmap, co).rg;
2054                         float dist = co.z/co.w;
2055                         float p = 0.0;
2056                         
2057                         if(dist <= moments.x)
2058                                 p = 1.0;
2059
2060                         float variance = moments.y - (moments.x*moments.x);
2061                         variance = max(variance, shadowbias/10.0);
2062
2063                         float d = moments.x - dist;
2064                         float p_max = variance / (variance + d*d);
2065
2066                         // Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1]
2067                         p_max = clamp((p_max-bleedbias)/(1.0-bleedbias), 0.0, 1.0);
2068
2069                         result = max(p, p_max);
2070                 }
2071                 else {
2072                         result = 1.0;
2073                 }
2074         }
2075 }
2076
2077 void shadows_only(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, vec3 shadowcolor, float inp, out vec3 result)
2078 {
2079         result = vec3(1.0);
2080
2081         if(inp > 0.0) {
2082                 float shadfac;
2083
2084                 test_shadowbuf(rco, shadowmap, shadowpersmat, shadowbias, inp, shadfac);
2085                 result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
2086         }
2087 }
2088
2089 void shadows_only_vsm(vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float shadowbias, float bleedbias, vec3 shadowcolor, float inp, out vec3 result)
2090 {
2091         result = vec3(1.0);
2092
2093         if(inp > 0.0) {
2094                 float shadfac;
2095
2096                 test_shadowbuf_vsm(rco, shadowmap, shadowpersmat, shadowbias, bleedbias, inp, shadfac);
2097                 result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
2098         }
2099 }
2100
2101 void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec4 result)
2102 {
2103
2104         vec4 co = shadowpersmat*vec4(rco, 1.0);
2105
2106         result = texture2DProj(cookie, co);
2107 }
2108
2109 void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol)
2110 {
2111         outcol = linfac*(1.0 - exp(col*logfac));
2112 }
2113
2114 void shade_mist_factor(vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, out float outfac)
2115 {
2116         if(enable == 1.0) {
2117                 float fac, zcor;
2118
2119                 zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
2120                 
2121                 fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
2122                 if(misttype == 0.0) fac *= fac;
2123                 else if(misttype == 1.0);
2124                 else fac = sqrt(fac);
2125
2126                 outfac = 1.0 - (1.0 - fac) * (1.0 - misi);
2127         }
2128         else {
2129                 outfac = 0.0;
2130         }
2131 }
2132
2133 void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol)
2134 {
2135         float fac = clamp(col.a, 0.0, 1.0);
2136         outcol = vec4(mix(hor, col.rgb, fac), col.a);
2137 }
2138
2139 void shade_alpha_opaque(vec4 col, out vec4 outcol)
2140 {
2141         outcol = vec4(col.rgb, 1.0);
2142 }
2143
2144 void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
2145 {
2146         outcol = vec4(col.rgb, col.a*obcol.a);
2147 }
2148
2149 /*********** NEW SHADER UTILITIES **************/
2150
2151 float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
2152 {
2153         /* compute fresnel reflectance without explicitly computing
2154          * the refracted direction */
2155         float c = abs(dot(Incoming, Normal));
2156         float g = eta * eta - 1.0 + c * c;
2157         float result;
2158
2159         if(g > 0.0) {
2160                 g = sqrt(g);
2161                 float A =(g - c)/(g + c);
2162                 float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
2163                 result = 0.5 * A * A *(1.0 + B * B);
2164         }
2165         else {
2166                 result = 1.0;  /* TIR (no refracted component) */
2167         }
2168
2169         return result;
2170 }
2171
2172 float hypot(float x, float y)
2173 {
2174         return sqrt(x*x + y*y);
2175 }
2176
2177 /*********** NEW SHADER NODES ***************/
2178
2179 #define NUM_LIGHTS 3
2180
2181 /* bsdfs */
2182
2183 void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
2184 {
2185         /* ambient light */
2186         vec3 L = vec3(0.2);
2187
2188         /* directional lights */
2189         for(int i = 0; i < NUM_LIGHTS; i++) {
2190                 vec3 light_position = gl_LightSource[i].position.xyz;
2191                 vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
2192
2193                 float bsdf = max(dot(N, light_position), 0.0);
2194                 L += light_diffuse*bsdf;
2195         }
2196
2197         result = vec4(L*color.rgb, 1.0);
2198 }
2199
2200 void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
2201 {
2202         /* ambient light */
2203         vec3 L = vec3(0.2);
2204
2205         /* directional lights */
2206         for(int i = 0; i < NUM_LIGHTS; i++) {
2207                 vec3 light_position = gl_LightSource[i].position.xyz;
2208                 vec3 H = gl_LightSource[i].halfVector.xyz;
2209                 vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
2210                 vec3 light_specular = gl_LightSource[i].specular.rgb;
2211
2212                 /* we mix in some diffuse so low roughness still shows up */
2213                 float bsdf = 0.5*pow(max(dot(N, H), 0.0), 1.0/roughness);
2214                 bsdf += 0.5*max(dot(N, light_position), 0.0);
2215                 L += light_specular*bsdf;
2216         }
2217
2218         result = vec4(L*color.rgb, 1.0);
2219 }
2220
2221 void node_bsdf_anisotropic(vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, out vec4 result)
2222 {
2223         node_bsdf_diffuse(color, 0.0, N, result);
2224 }
2225
2226 void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
2227 {
2228         node_bsdf_diffuse(color, 0.0, N, result);
2229 }
2230
2231 void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result)
2232 {
2233         node_bsdf_diffuse(color, 0.0, N, result);
2234 }
2235
2236 void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
2237 {
2238         node_bsdf_diffuse(color, 0.0, N, result);
2239 }
2240
2241 void node_bsdf_transparent(vec4 color, out vec4 result)
2242 {
2243         /* this isn't right */
2244         result.r = color.r;
2245         result.g = color.g;
2246         result.b = color.b;
2247         result.a = 0.0;
2248 }
2249
2250 void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
2251 {
2252         node_bsdf_diffuse(color, 0.0, N, result);
2253 }
2254
2255 void node_subsurface_scattering(vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, out vec4 result)
2256 {
2257         node_bsdf_diffuse(color, 0.0, N, result);
2258 }
2259
2260 void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, out vec4 result)
2261 {
2262         result = color;
2263 }
2264
2265 /* emission */
2266
2267 void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
2268 {
2269         result = color*strength;
2270 }
2271
2272 /* background */
2273
2274 void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
2275 {
2276         vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
2277         vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
2278
2279         vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
2280         worldvec = (gl_ModelViewMatrixInverse * co).xyz;
2281 }
2282
2283 void node_background(vec4 color, float strength, vec3 N, out vec4 result)
2284 {
2285         result = color*strength;
2286 }
2287
2288 /* closures */
2289
2290 void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
2291 {
2292         shader = mix(shader1, shader2, fac);
2293 }
2294
2295 void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
2296 {
2297         shader = shader1 + shader2;
2298 }
2299
2300 /* fresnel */
2301
2302 void node_fresnel(float ior, vec3 N, vec3 I, out float result)
2303 {
2304         /* handle perspective/orthographic */
2305         vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
2306
2307         float eta = max(ior, 0.00001);
2308         result = fresnel_dielectric(I_view, N, (gl_FrontFacing)? eta: 1.0/eta);
2309 }
2310
2311 /* layer_weight */
2312
2313 void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing)
2314 {
2315         /* fresnel */
2316         float eta = max(1.0 - blend, 0.00001);
2317         vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
2318
2319         fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing)? 1.0/eta : eta );
2320
2321         /* facing */
2322         facing = abs(dot(I_view, N));
2323         if(blend != 0.5) {
2324                 blend = clamp(blend, 0.0, 0.99999);
2325                 blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend);
2326                 facing = pow(facing, blend);
2327         }
2328         facing = 1.0 - facing;
2329 }
2330
2331 /* gamma */
2332
2333 void node_gamma(vec4 col, float gamma, out vec4 outcol)
2334 {
2335         outcol = col;
2336
2337         if(col.r > 0.0)
2338                 outcol.r = compatible_pow(col.r, gamma);
2339         if(col.g > 0.0)
2340                 outcol.g = compatible_pow(col.g, gamma);
2341         if(col.b > 0.0)
2342                 outcol.b = compatible_pow(col.b, gamma);
2343 }
2344
2345 /* geometry */
2346
2347 void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float outf)
2348 {
2349         outcol = vec4(attr_uv, 1.0);
2350         outvec = attr_uv;
2351         outf = (attr_uv.x + attr_uv.y + attr_uv.z)/3.0;
2352 }
2353
2354 void node_uvmap(vec3 attr_uv, out vec3 outvec)
2355 {
2356         outvec = attr_uv;
2357 }
2358
2359 void node_geometry(vec3 I, vec3 N, mat4 toworld,
2360         out vec3 position, out vec3 normal, out vec3 tangent,
2361         out vec3 true_normal, out vec3 incoming, out vec3 parametric,
2362         out float backfacing, out float pointiness)
2363 {
2364         position = (toworld*vec4(I, 1.0)).xyz;
2365         normal = (toworld*vec4(N, 0.0)).xyz;
2366         tangent = vec3(0.0);
2367         true_normal = normal;
2368
2369         /* handle perspective/orthographic */
2370         vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
2371         incoming = -(toworld*vec4(I_view, 0.0)).xyz;
2372
2373         parametric = vec3(0.0);
2374         backfacing = (gl_FrontFacing)? 0.0: 1.0;
2375         pointiness = 0.0;
2376 }
2377
2378 void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
2379         vec3 attr_orco, vec3 attr_uv,
2380         out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
2381         out vec3 camera, out vec3 window, out vec3 reflection)
2382 {
2383         generated = attr_orco * 0.5 + vec3(0.5);
2384         normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
2385         uv = attr_uv;
2386         object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
2387         camera = vec3(I.xy, -I.z);
2388         vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
2389         window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
2390
2391         vec3 shade_I;
2392         shade_view(I, shade_I);
2393         vec3 view_reflection = reflect(shade_I, normalize(N));
2394         reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
2395 }
2396
2397 void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
2398         vec3 attr_orco, vec3 attr_uv,
2399         out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
2400         out vec3 camera, out vec3 window, out vec3 reflection)
2401 {
2402         vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
2403         vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
2404
2405         vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
2406
2407         co = normalize(co);
2408         vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
2409
2410         generated = coords;
2411         normal = -coords;
2412         uv = vec3(attr_uv.xy, 0.0);
2413         object = coords;
2414
2415         camera = vec3(co.xy, -co.z);
2416         window = (gl_ProjectionMatrix[3][3] == 0.0) ? 
2417                       vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : 
2418                       vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
2419
2420         reflection = -coords;
2421 }
2422
2423 /* textures */
2424
2425 void node_tex_gradient(vec3 co, out vec4 color, out float fac)
2426 {
2427         color = vec4(1.0);
2428         fac = 1.0;
2429 }
2430
2431 void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac)
2432 {
2433         color = vec4(1.0);
2434         fac = 1.0;
2435 }
2436
2437 void node_tex_brick(vec3 co, vec4 color1, vec4 color2, vec4 mortar, float scale, float mortar_size, float bias, float brick_width, float row_height, out vec4 color, out float fac)
2438 {
2439         color = vec4(1.0);
2440         fac = 1.0;
2441 }
2442
2443 void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
2444 {
2445         color = vec4(1.0);
2446         fac = 1.0;
2447 }
2448
2449 void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
2450 {
2451         vec3 nco = normalize(co);
2452         float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5;
2453         float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5;
2454
2455         color = texture2D(ima, vec2(u, v));
2456 }
2457
2458 void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
2459 {
2460         vec3 nco = normalize(co);
2461
2462         nco.y -= 1.0;
2463
2464         float div = 2.0*sqrt(max(-0.5*nco.y, 0.0));
2465         if(div > 0.0)
2466                 nco /= div;
2467
2468         float u = 0.5*(nco.x + 1.0);
2469         float v = 0.5*(nco.z + 1.0);
2470
2471         color = texture2D(ima, vec2(u, v));
2472 }
2473
2474 void node_tex_environment_empty(vec3 co, out vec4 color)
2475 {
2476         color = vec4(1.0, 0.0, 1.0, 1.0);
2477 }
2478
2479 void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
2480 {
2481         color = texture2D(ima, co.xy);
2482         alpha = color.a;
2483 }
2484
2485 void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
2486 {
2487         color = vec4(0.0);
2488         alpha = 0.0;
2489 }
2490
2491 void node_tex_magic(vec3 p, float scale, float distortion, out vec4 color, out float fac)
2492 {
2493         color = vec4(1.0);
2494         fac = 1.0;
2495 }
2496
2497 void node_tex_musgrave(vec3 co, float scale, float detail, float dimension, float lacunarity, float offset, float gain, out vec4 color, out float fac)
2498 {
2499         color = vec4(1.0);
2500         fac = 1.0;
2501 }
2502
2503 void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
2504 {
2505         color = vec4(1.0);
2506         fac = 1.0;
2507 }
2508
2509 void node_tex_sky(vec3 co, out vec4 color)
2510 {
2511         color = vec4(1.0);
2512 }
2513
2514 void node_tex_voronoi(vec3 co, float scale, out vec4 color, out float fac)
2515 {
2516         color = vec4(1.0);
2517         fac = 1.0;
2518 }
2519
2520 void node_tex_wave(vec3 co, float scale, float distortion, float detail, float detail_scale, out vec4 color, out float fac)
2521 {
2522         color = vec4(1.0);
2523         fac = 1.0;
2524 }
2525
2526 /* light path */
2527
2528 void node_light_path(
2529         out float is_camera_ray,
2530         out float is_shadow_ray,
2531         out float is_diffuse_ray,
2532         out float is_glossy_ray,
2533         out float is_singular_ray,
2534         out float is_reflection_ray,
2535         out float is_transmission_ray,
2536         out float ray_length,
2537         out float ray_depth,
2538         out float transparent_depth)
2539 {
2540         is_camera_ray = 1.0;
2541         is_shadow_ray = 0.0;
2542         is_diffuse_ray = 0.0;
2543         is_glossy_ray = 0.0;
2544         is_singular_ray = 0.0;
2545         is_reflection_ray = 0.0;
2546         is_transmission_ray = 0.0;
2547         ray_length = 1.0;
2548         ray_depth = 1.0;
2549         transparent_depth = 1.0;
2550 }
2551
2552 void node_light_falloff(float strength, float tsmooth, out float quadratic, out float linear, out float constant)
2553 {
2554         quadratic = strength;
2555         linear = strength;
2556         constant = strength;
2557 }
2558
2559 void node_object_info(out vec3 location, out float object_index, out float material_index, out float random)
2560 {
2561         location = vec3(0.0);
2562         object_index = 0.0;
2563         material_index = 0.0;
2564         random = 0.0;
2565 }
2566
2567 void node_normal_map(float strength, vec4 color, vec3 N, out vec3 result)
2568 {
2569         result = N;
2570 }
2571
2572 void node_bump(float strength, float dist, float height, vec3 N, out vec3 result)
2573 {
2574         result = N;
2575 }
2576
2577 /* output */
2578
2579 void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)
2580 {
2581         result = surface;
2582 }
2583
2584 void node_output_world(vec4 surface, vec4 volume, out vec4 result)
2585 {
2586         result = surface;
2587 }
2588
2589 /* ********************** matcap style render ******************** */
2590
2591 void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
2592 {
2593         vec3 normal;
2594         vec2 tex;
2595         
2596         /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors 
2597          * between shader stages and we want the full range of the normal */
2598         normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
2599         if (normal.z < 0.0) {
2600                 normal.z = 0.0;
2601         }
2602         normal = normalize(normal);
2603
2604         tex.x = 0.5 + 0.49 * normal.x;
2605         tex.y = 0.5 + 0.49 * normal.y;
2606         result = texture2D(ima, tex) * mask;
2607 }