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