Committing Konrads GLSL preview of bumpmapping, now we no longer have the bizarre...
[blender-staging.git] / source / blender / gpu / intern / gpu_shader_material.glsl
1
2 float exp_blender(float f)
3 {
4         return pow(2.71828182846, f);
5 }
6
7 void rgb_to_hsv(vec4 rgb, out vec4 outcol)
8 {
9         float cmax, cmin, h, s, v, cdelta;
10         vec3 c;
11
12         cmax = max(rgb[0], max(rgb[1], rgb[2]));
13         cmin = min(rgb[0], min(rgb[1], rgb[2]));
14         cdelta = cmax-cmin;
15
16         v = cmax;
17         if (cmax!=0.0)
18                 s = cdelta/cmax;
19         else {
20                 s = 0.0;
21                 h = 0.0;
22         }
23
24         if (s == 0.0) {
25                 h = 0.0;
26         }
27         else {
28                 c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta;
29
30                 if (rgb.x==cmax) h = c[2] - c[1];
31                 else if (rgb.y==cmax) h = 2.0 + c[0] -  c[2];
32                 else h = 4.0 + c[1] - c[0];
33
34                 h /= 6.0;
35
36                 if (h<0.0)
37                         h += 1.0;
38         }
39
40         outcol = vec4(h, s, v, rgb.w);
41 }
42
43 void hsv_to_rgb(vec4 hsv, out vec4 outcol)
44 {
45         float i, f, p, q, t, h, s, v;
46         vec3 rgb;
47
48         h = hsv[0];
49         s = hsv[1];
50         v = hsv[2];
51
52         if(s==0.0) {
53                 rgb = vec3(v, v, v);
54         }
55         else {
56                 if(h==1.0)
57                         h = 0.0;
58                 
59                 h *= 6.0;
60                 i = floor(h);
61                 f = h - i;
62                 rgb = vec3(f, f, f);
63                 p = v*(1.0-s);
64                 q = v*(1.0-(s*f));
65                 t = v*(1.0-(s*(1.0-f)));
66                 
67                 if (i == 0.0) rgb = vec3(v, t, p);
68                 else if (i == 1.0) rgb = vec3(q, v, p);
69                 else if (i == 2.0) rgb = vec3(p, v, t);
70                 else if (i == 3.0) rgb = vec3(p, q, v);
71                 else if (i == 4.0) rgb = vec3(t, p, v);
72                 else rgb = vec3(v, p, q);
73         }
74
75         outcol = vec4(rgb, hsv.w);
76 }
77
78 float srgb_to_linearrgb(float c)
79 {
80         if(c < 0.04045)
81                 return (c < 0.0)? 0.0: c * (1.0/12.92);
82         else
83                 return pow((c + 0.055)*(1.0/1.055), 2.4);
84 }
85
86 float linearrgb_to_srgb(float c)
87 {
88         if(c < 0.0031308)
89                 return (c < 0.0)? 0.0: c * 12.92;
90         else
91                 return 1.055 * pow(c, 1.0/2.4) - 0.055;
92 }
93
94 void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
95 {
96         col_to.r = srgb_to_linearrgb(col_from.r);
97         col_to.g = srgb_to_linearrgb(col_from.g);
98         col_to.b = srgb_to_linearrgb(col_from.b);
99         col_to.a = col_from.a;
100 }
101
102 void linearrgb_to_srgb(vec4 col_from, out vec4 col_to)
103 {
104         col_to.r = linearrgb_to_srgb(col_from.r);
105         col_to.g = linearrgb_to_srgb(col_from.g);
106         col_to.b = linearrgb_to_srgb(col_from.b);
107         col_to.a = col_from.a;
108 }
109
110 #define M_PI 3.14159265358979323846
111
112 /*********** SHADER NODES ***************/
113
114 void vcol_attribute(vec4 attvcol, out vec4 vcol)
115 {
116         vcol = vec4(attvcol.x/255.0, attvcol.y/255.0, attvcol.z/255.0, 1.0);
117 }
118
119 void uv_attribute(vec2 attuv, out vec3 uv)
120 {
121         uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0);
122 }
123
124 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 frontback)
125 {
126         local = co;
127         view = normalize(local);
128         global = (viewinvmat*vec4(local, 1.0)).xyz;
129         orco = attorco;
130         uv_attribute(attuv, uv);
131         normal = -normalize(nor);       /* blender render normal is negated */
132         vcol_attribute(attvcol, vcol);
133         frontback = 1.0;
134 }
135
136 void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
137 {
138         outvec = (mat * vec4(vec, 1.0)).xyz;
139         if(domin == 1.0)
140                 outvec = max(outvec, minvec);
141         if(domax == 1.0)
142                 outvec = min(outvec, maxvec);
143 }
144
145 void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
146 {
147         outdepth = abs(co.z);
148         outdist = length(co);
149         outview = normalize(co);
150 }
151
152 void math_add(float val1, float val2, out float outval)
153 {
154         outval = val1 + val2;
155 }
156
157 void math_subtract(float val1, float val2, out float outval)
158 {
159         outval = val1 - val2;
160 }
161
162 void math_multiply(float val1, float val2, out float outval)
163 {
164         outval = val1 * val2;
165 }
166
167 void math_divide(float val1, float val2, out float outval)
168 {
169         if (val2 == 0.0)
170                 outval = 0.0;
171         else
172                 outval = val1 / val2;
173 }
174
175 void math_sine(float val, out float outval)
176 {
177         outval = sin(val);
178 }
179
180 void math_cosine(float val, out float outval)
181 {
182         outval = cos(val);
183 }
184
185 void math_tangent(float val, out float outval)
186 {
187         outval = tan(val);
188 }
189
190 void math_asin(float val, out float outval)
191 {
192         if (val <= 1.0 && val >= -1.0)
193                 outval = asin(val);
194         else
195                 outval = 0.0;
196 }
197
198 void math_acos(float val, out float outval)
199 {
200         if (val <= 1.0 && val >= -1.0)
201                 outval = acos(val);
202         else
203                 outval = 0.0;
204 }
205
206 void math_atan(float val, out float outval)
207 {
208         outval = atan(val);
209 }
210
211 void math_pow(float val1, float val2, out float outval)
212 {
213         if (val1 >= 0.0)
214                 outval = pow(val1, val2);
215         else
216                 outval = 0.0;
217 }
218
219 void math_log(float val1, float val2, out float outval)
220 {
221         if(val1 > 0.0  && val2 > 0.0)
222                 outval= log2(val1) / log2(val2);
223         else
224                 outval= 0.0;
225 }
226
227 void math_max(float val1, float val2, out float outval)
228 {
229         outval = max(val1, val2);
230 }
231
232 void math_min(float val1, float val2, out float outval)
233 {
234         outval = min(val1, val2);
235 }
236
237 void math_round(float val, out float outval)
238 {
239         outval= floor(val + 0.5);
240 }
241
242 void math_less_than(float val1, float val2, out float outval)
243 {
244         if(val1 < val2)
245                 outval = 1.0;
246         else
247                 outval = 0.0;
248 }
249
250 void math_greater_than(float val1, float val2, out float outval)
251 {
252         if(val1 > val2)
253                 outval = 1.0;
254         else
255                 outval = 0.0;
256 }
257
258 void squeeze(float val, float width, float center, out float outval)
259 {
260         outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width)));
261 }
262
263 void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
264 {
265         outvec = v1 + v2;
266         outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
267 }
268
269 void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
270 {
271         outvec = v1 - v2;
272         outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
273 }
274
275 void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
276 {
277         outvec = v1 + v2;
278         outval = length(outvec);
279         outvec = normalize(outvec);
280 }
281
282 void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
283 {
284         outvec = vec3(0, 0, 0);
285         outval = dot(v1, v2);
286 }
287
288 void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
289 {
290         outvec = cross(v1, v2);
291         outval = length(outvec);
292 }
293
294 void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
295 {
296         outval = length(v);
297         outvec = normalize(v);
298 }
299
300 void vec_math_negate(vec3 v, out vec3 outv)
301 {
302         outv = -v;
303 }
304
305 void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
306 {
307         outnor = dir;
308         outdot = -dot(dir, nor);
309 }
310
311 void curves_vec(float fac, vec3 vec, sampler1D curvemap, out vec3 outvec)
312 {
313         outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x;
314         outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y;
315         outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z;
316
317         if (fac != 1.0)
318                 outvec = (outvec*fac) + (vec*(1.0-fac));
319
320 }
321
322 void curves_rgb(float fac, vec4 col, sampler1D curvemap, out vec4 outcol)
323 {
324         outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r;
325         outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g;
326         outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b;
327
328         if (fac != 1.0)
329                 outcol = (outcol*fac) + (col*(1.0-fac));
330
331         outcol.a = col.a;
332 }
333
334 void set_value(float val, out float outval)
335 {
336         outval = val;
337 }
338
339 void set_rgb(vec3 col, out vec3 outcol)
340 {
341         outcol = col;
342 }
343
344 void set_rgba(vec4 col, out vec4 outcol)
345 {
346         outcol = col;
347 }
348
349 void set_value_zero(out float outval)
350 {
351         outval = 0.0;
352 }
353
354 void set_value_one(out float outval)
355 {
356         outval = 1.0;
357 }
358
359 void set_rgb_zero(out vec3 outval)
360 {
361         outval = vec3(0.0);
362 }
363
364 void set_rgba_zero(out vec4 outval)
365 {
366         outval = vec4(0.0);
367 }
368
369 void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol)
370 {
371         fac = clamp(fac, 0.0, 1.0);
372         outcol = mix(col1, col2, fac);
373         outcol.a = col1.a;
374 }
375
376 void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol)
377 {
378         fac = clamp(fac, 0.0, 1.0);
379         outcol = mix(col1, col1 + col2, fac);
380         outcol.a = col1.a;
381 }
382
383 void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol)
384 {
385         fac = clamp(fac, 0.0, 1.0);
386         outcol = mix(col1, col1 * col2, fac);
387         outcol.a = col1.a;
388 }
389
390 void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol)
391 {
392         fac = clamp(fac, 0.0, 1.0);
393         float facm = 1.0 - fac;
394
395         outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1);
396         outcol.a = col1.a;
397 }
398
399 void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol)
400 {
401         fac = clamp(fac, 0.0, 1.0);
402         float facm = 1.0 - fac;
403
404         outcol = col1;
405
406         if(outcol.r < 0.5)
407                 outcol.r *= facm + 2.0*fac*col2.r;
408         else
409                 outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r);
410
411         if(outcol.g < 0.5)
412                 outcol.g *= facm + 2.0*fac*col2.g;
413         else
414                 outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g);
415
416         if(outcol.b < 0.5)
417                 outcol.b *= facm + 2.0*fac*col2.b;
418         else
419                 outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b);
420 }
421
422 void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol)
423 {
424         fac = clamp(fac, 0.0, 1.0);
425         outcol = mix(col1, col1 - col2, fac);
426         outcol.a = col1.a;
427 }
428
429 void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol)
430 {
431         fac = clamp(fac, 0.0, 1.0);
432         float facm = 1.0 - fac;
433
434         outcol = col1;
435
436         if(col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r;
437         if(col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g;
438         if(col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b;
439 }
440
441 void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
442 {
443         fac = clamp(fac, 0.0, 1.0);
444         outcol = mix(col1, abs(col1 - col2), fac);
445         outcol.a = col1.a;
446 }
447
448 void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
449 {
450         fac = clamp(fac, 0.0, 1.0);
451         outcol.rgb = min(col1.rgb, col2.rgb*fac);
452         outcol.a = col1.a;
453 }
454
455 void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
456 {
457         fac = clamp(fac, 0.0, 1.0);
458         outcol.rgb = max(col1.rgb, col2.rgb*fac);
459         outcol.a = col1.a;
460 }
461
462 void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol)
463 {
464         fac = clamp(fac, 0.0, 1.0);
465         outcol = col1;
466
467         if(outcol.r != 0.0) {
468                 float tmp = 1.0 - fac*col2.r;
469                 if(tmp <= 0.0)
470                         outcol.r = 1.0;
471                 else if((tmp = outcol.r/tmp) > 1.0)
472                         outcol.r = 1.0;
473                 else
474                         outcol.r = tmp;
475         }
476         if(outcol.g != 0.0) {
477                 float tmp = 1.0 - fac*col2.g;
478                 if(tmp <= 0.0)
479                         outcol.g = 1.0;
480                 else if((tmp = outcol.g/tmp) > 1.0)
481                         outcol.g = 1.0;
482                 else
483                         outcol.g = tmp;
484         }
485         if(outcol.b != 0.0) {
486                 float tmp = 1.0 - fac*col2.b;
487                 if(tmp <= 0.0)
488                         outcol.b = 1.0;
489                 else if((tmp = outcol.b/tmp) > 1.0)
490                         outcol.b = 1.0;
491                 else
492                         outcol.b = tmp;
493         }
494 }
495
496 void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol)
497 {
498         fac = clamp(fac, 0.0, 1.0);
499         float tmp, facm = 1.0 - fac;
500
501         outcol = col1;
502
503         tmp = facm + fac*col2.r;
504         if(tmp <= 0.0)
505                 outcol.r = 0.0;
506         else if((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0)
507                 outcol.r = 0.0;
508         else if(tmp > 1.0)
509                 outcol.r = 1.0;
510         else
511                 outcol.r = tmp;
512
513         tmp = facm + fac*col2.g;
514         if(tmp <= 0.0)
515                 outcol.g = 0.0;
516         else if((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0)
517                 outcol.g = 0.0;
518         else if(tmp > 1.0)
519                 outcol.g = 1.0;
520         else
521                 outcol.g = tmp;
522
523         tmp = facm + fac*col2.b;
524         if(tmp <= 0.0)
525                 outcol.b = 0.0;
526         else if((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0)
527                 outcol.b = 0.0;
528         else if(tmp > 1.0)
529                 outcol.b = 1.0;
530         else
531                 outcol.b = tmp;
532 }
533
534 void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol)
535 {
536         fac = clamp(fac, 0.0, 1.0);
537         float facm = 1.0 - fac;
538
539         outcol = col1;
540
541         vec4 hsv, hsv2, tmp;
542         rgb_to_hsv(col2, hsv2);
543
544         if(hsv2.y != 0.0) {
545                 rgb_to_hsv(outcol, hsv);
546                 hsv.x = hsv2.x;
547                 hsv_to_rgb(hsv, tmp); 
548
549                 outcol = mix(outcol, tmp, fac);
550                 outcol.a = col1.a;
551         }
552 }
553
554 void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol)
555 {
556         fac = clamp(fac, 0.0, 1.0);
557         float facm = 1.0 - fac;
558
559         outcol = col1;
560
561         vec4 hsv, hsv2;
562         rgb_to_hsv(outcol, hsv);
563
564         if(hsv.y != 0.0) {
565                 rgb_to_hsv(col2, hsv2);
566
567                 hsv.y = facm*hsv.y + fac*hsv2.y;
568                 hsv_to_rgb(hsv, outcol);
569         }
570 }
571
572 void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol)
573 {
574         fac = clamp(fac, 0.0, 1.0);
575         float facm = 1.0 - fac;
576
577         vec4 hsv, hsv2;
578         rgb_to_hsv(col1, hsv);
579         rgb_to_hsv(col2, hsv2);
580
581         hsv.z = facm*hsv.z + fac*hsv2.z;
582         hsv_to_rgb(hsv, outcol);
583 }
584
585 void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol)
586 {
587         fac = clamp(fac, 0.0, 1.0);
588         float facm = 1.0 - fac;
589
590         outcol = col1;
591
592         vec4 hsv, hsv2, tmp;
593         rgb_to_hsv(col2, hsv2);
594
595         if(hsv2.y != 0.0) {
596                 rgb_to_hsv(outcol, hsv);
597                 hsv.x = hsv2.x;
598                 hsv.y = hsv2.y;
599                 hsv_to_rgb(hsv, tmp); 
600
601                 outcol = mix(outcol, tmp, fac);
602                 outcol.a = col1.a;
603         }
604 }
605
606 void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol)
607 {
608         fac = clamp(fac, 0.0, 1.0);
609         float facm = 1.0 - fac;
610
611         vec4 one= vec4(1.0);
612         vec4 scr= one - (one - col2)*(one - col1);
613         outcol = facm*col1 + fac*((one - col1)*col2*col1 + col1*scr);
614 }
615
616 void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
617 {
618         fac = clamp(fac, 0.0, 1.0);
619
620         outcol = col1;
621
622         if(col2.r > 0.5)
623                 outcol.r= col1.r + fac*(2.0*(col2.r - 0.5));
624         else
625                 outcol.r= col1.r + fac*(2.0*(col2.r) - 1.0);
626
627         if(col2.g > 0.5)
628                 outcol.g= col1.g + fac*(2.0*(col2.g - 0.5));
629         else
630                 outcol.g= col1.g + fac*(2.0*(col2.g) - 1.0);
631
632         if(col2.b > 0.5)
633                 outcol.b= col1.b + fac*(2.0*(col2.b - 0.5));
634         else
635                 outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
636 }
637
638 void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha)
639 {
640         outcol = texture1D(colormap, fac);
641         outalpha = outcol.a;
642 }
643
644 void rgbtobw(vec4 color, out float outval)
645 {
646         outval = color.r*0.35 + color.g*0.45 + color.b*0.2;
647 }
648
649 void invert(float fac, vec4 col, out vec4 outcol)
650 {
651         outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac);
652         outcol.w = col.w;
653 }
654
655 void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
656 {
657         vec4 hsv;
658
659         rgb_to_hsv(col, hsv);
660
661         hsv[0] += (hue - 0.5);
662         if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
663         hsv[1] *= sat;
664         if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
665         hsv[2] *= value;
666         if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
667
668         hsv_to_rgb(hsv, outcol);
669
670         outcol = mix(col, outcol, fac);
671 }
672
673 void separate_rgb(vec4 col, out float r, out float g, out float b)
674 {
675         r = col.r;
676         g = col.g;
677         b = col.b;
678 }
679
680 void combine_rgb(float r, float g, float b, out vec4 col)
681 {
682         col = vec4(r, g, b, 1.0);
683 }
684
685 void output_node(vec4 rgb, float alpha, out vec4 outrgb)
686 {
687         outrgb = vec4(rgb.rgb, alpha);
688 }
689
690 /*********** TEXTURES ***************/
691
692 void texture_flip_blend(vec3 vec, out vec3 outvec)
693 {
694         outvec = vec.yxz;
695 }
696
697 void texture_blend_lin(vec3 vec, out float outval)
698 {
699         outval = (1.0+vec.x)/2.0;
700 }
701
702 void texture_blend_quad(vec3 vec, out float outval)
703 {
704         outval = max((1.0+vec.x)/2.0, 0.0);
705         outval *= outval;
706 }
707
708 void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal)
709 {
710         float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0;
711         float wi = 0.5 + 0.5*sin(a);
712
713         value = wi;
714         color = vec4(wi, wi, wi, 1.0);
715         normal = vec3(0.0, 0.0, 0.0);
716 }
717
718 void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
719 {
720         color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5);
721         value = 1.0;
722
723         normal.x = 2.0*(color.r - 0.5);
724         normal.y = 2.0*(0.5 - color.g);
725         normal.z = 2.0*(color.b - 0.5);
726 }
727
728 /************* MTEX *****************/
729
730 void texco_orco(vec3 attorco, out vec3 orco)
731 {
732         orco = attorco;
733 }
734
735 void texco_uv(vec2 attuv, out vec3 uv)
736 {
737         /* disabled for now, works together with leaving out mtex_2d_mapping
738            uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */
739         uv = vec3(attuv, 0.0);
740 }
741
742 void texco_norm(vec3 normal, out vec3 outnormal)
743 {
744         /* corresponds to shi->orn, which is negated so cancels
745            out blender normal negation */
746         outnormal = normalize(normal);
747 }
748
749 void texco_tangent(vec3 tangent, out vec3 outtangent)
750 {
751         outtangent = normalize(tangent);
752 }
753
754 void texco_global(mat4 viewinvmat, vec3 co, out vec3 global)
755 {
756         global = (viewinvmat*vec4(co, 1.0)).xyz;
757 }
758
759 void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object)
760 {
761         object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz;
762 }
763
764 void texco_refl(vec3 vn, vec3 view, out vec3 ref)
765 {
766         ref = view - 2.0*dot(vn, view)*vn;
767 }
768
769 void shade_norm(vec3 normal, out vec3 outnormal)
770 {
771         /* blender render normal is negated */
772         outnormal = -normalize(normal);
773 }
774
775 void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
776 {
777         float facm;
778
779         fact *= facg;
780         facm = 1.0-fact;
781
782         incol = fact*texcol + facm*outcol;
783 }
784
785 void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
786 {
787         float facm;
788
789         fact *= facg;
790         facm = 1.0-facg;
791
792         incol = (facm + fact*texcol)*outcol;
793 }
794
795 void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
796 {
797         float facm;
798
799         fact *= facg;
800         facm = 1.0-facg;
801
802         incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol);
803 }
804
805 void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
806 {
807         float facm;
808
809         fact *= facg;
810         facm = 1.0-facg;
811
812         if(outcol.r < 0.5)
813                 incol.r = outcol.r*(facm + 2.0*fact*texcol.r);
814         else
815                 incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r);
816
817         if(outcol.g < 0.5)
818                 incol.g = outcol.g*(facm + 2.0*fact*texcol.g);
819         else
820                 incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g);
821
822         if(outcol.b < 0.5)
823                 incol.b = outcol.b*(facm + 2.0*fact*texcol.b);
824         else
825                 incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b);
826 }
827
828 void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
829 {
830         incol = -fact*facg*texcol + outcol;
831 }
832
833 void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
834 {
835         incol = fact*facg*texcol + outcol;
836 }
837
838 void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
839 {
840         float facm;
841
842         fact *= facg;
843         facm = 1.0-fact;
844
845         if(texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r;
846         if(texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g;
847         if(texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b;
848 }
849
850 void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
851 {
852         float facm;
853
854         fact *= facg;
855         facm = 1.0-fact;
856
857         incol = facm*outcol + fact*abs(texcol - outcol);
858 }
859
860 void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
861 {
862         float facm, col;
863
864         fact *= facg;
865         facm = 1.0-fact;
866
867         col = fact*texcol.r;
868         if(col < outcol.r) incol.r = col; else incol.r = outcol.r;
869         col = fact*texcol.g;
870         if(col < outcol.g) incol.g = col; else incol.g = outcol.g;
871         col = fact*texcol.b;
872         if(col < outcol.b) incol.b = col; else incol.b = outcol.b;
873 }
874
875 void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
876 {
877         float facm, col;
878
879         fact *= facg;
880         facm = 1.0-fact;
881
882         col = fact*texcol.r;
883         if(col > outcol.r) incol.r = col; else incol.r = outcol.r;
884         col = fact*texcol.g;
885         if(col > outcol.g) incol.g = col; else incol.g = outcol.g;
886         col = fact*texcol.b;
887         if(col > outcol.b) incol.b = col; else incol.b = outcol.b;
888 }
889
890 void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
891 {
892         vec4 col;
893
894         mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
895         incol.rgb = col.rgb;
896 }
897
898 void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
899 {
900         vec4 col;
901
902         mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
903         incol.rgb = col.rgb;
904 }
905
906 void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
907 {
908         vec4 col;
909
910         mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
911         incol.rgb = col.rgb;
912 }
913
914 void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
915 {
916         vec4 col;
917
918         mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
919         incol.rgb = col.rgb;
920 }
921
922 void mtex_value_vars(inout float fact, float facg, out float facm)
923 {
924         fact *= abs(facg);
925         facm = 1.0-fact;
926
927         if(facg < 0.0) {
928                 float tmp = fact;
929                 fact = facm;
930                 facm = tmp;
931         }
932 }
933
934 void mtex_value_blend(float outcol, float texcol, float fact, float facg, out float incol)
935 {
936         float facm;
937         mtex_value_vars(fact, facg, facm);
938
939         incol = fact*texcol + facm*outcol;
940 }
941
942 void mtex_value_mul(float outcol, float texcol, float fact, float facg, out float incol)
943 {
944         float facm;
945         mtex_value_vars(fact, facg, facm);
946
947         facm = 1.0 - facg;
948         incol = (facm + fact*texcol)*outcol;
949 }
950
951 void mtex_value_screen(float outcol, float texcol, float fact, float facg, out float incol)
952 {
953         float facm;
954         mtex_value_vars(fact, facg, facm);
955
956         facm = 1.0 - facg;
957         incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol);
958 }
959
960 void mtex_value_sub(float outcol, float texcol, float fact, float facg, out float incol)
961 {
962         float facm;
963         mtex_value_vars(fact, facg, facm);
964
965         fact = -fact;
966         incol = fact*texcol + outcol;
967 }
968
969 void mtex_value_add(float outcol, float texcol, float fact, float facg, out float incol)
970 {
971         float facm;
972         mtex_value_vars(fact, facg, facm);
973
974         fact = fact;
975         incol = fact*texcol + outcol;
976 }
977
978 void mtex_value_div(float outcol, float texcol, float fact, float facg, out float incol)
979 {
980         float facm;
981         mtex_value_vars(fact, facg, facm);
982
983         if(texcol != 0.0)
984                 incol = facm*outcol + fact*outcol/texcol;
985         else
986                 incol = 0.0;
987 }
988
989 void mtex_value_diff(float outcol, float texcol, float fact, float facg, out float incol)
990 {
991         float facm;
992         mtex_value_vars(fact, facg, facm);
993
994         incol = facm*outcol + fact*abs(texcol - outcol);
995 }
996
997 void mtex_value_dark(float outcol, float texcol, float fact, float facg, out float incol)
998 {
999         float facm;
1000         mtex_value_vars(fact, facg, facm);
1001
1002         float col = fact*texcol;
1003         if(col < outcol) incol = col; else incol = outcol;
1004 }
1005
1006 void mtex_value_light(float outcol, float texcol, float fact, float facg, out float incol)
1007 {
1008         float facm;
1009         mtex_value_vars(fact, facg, facm);
1010
1011         float col = fact*texcol;
1012         if(col > outcol) incol = col; else incol = outcol;
1013 }
1014
1015 void mtex_value_clamp_positive(float fac, out float outfac)
1016 {
1017         outfac = max(fac, 0.0);
1018 }
1019
1020 void mtex_value_clamp(float fac, out float outfac)
1021 {
1022         outfac = clamp(fac, 0.0, 1.0);
1023 }
1024
1025 void mtex_har_divide(float har, out float outhar)
1026 {
1027         outhar = har/128.0;
1028 }
1029
1030 void mtex_har_multiply_clamp(float har, out float outhar)
1031 {
1032         har *= 128.0;
1033
1034         if(har < 1.0) outhar = 1.0;
1035         else if(har > 511.0) outhar = 511.0;
1036         else outhar = har;
1037 }
1038
1039 void mtex_alpha_from_col(vec4 col, out float alpha)
1040 {
1041         alpha = col.a;
1042 }
1043
1044 void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol)
1045 {
1046         outcol = vec4(col.rgb, alpha);
1047 }
1048
1049 void mtex_rgbtoint(vec4 rgb, out float intensity)
1050 {
1051         intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb);
1052 }
1053
1054 void mtex_value_invert(float invalue, out float outvalue)
1055 {
1056         outvalue = 1.0 - invalue;
1057 }
1058
1059 void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb)
1060 {
1061         outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a);
1062 }
1063
1064 void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity)
1065 {
1066         float fact = intensity;
1067         outintensity = intensity*stencil;
1068         outstencil = stencil*fact;
1069 }
1070
1071 void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb)
1072 {
1073         float fact = rgb.a;
1074         outrgb = vec4(rgb.rgb, rgb.a*stencil);
1075         outstencil = stencil*fact;
1076 }
1077
1078 void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
1079 {
1080         outtexco = texco + ofs;
1081 }
1082
1083 void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
1084 {
1085         outtexco = size*texco;
1086 }
1087
1088 void mtex_2d_mapping(vec3 vec, out vec3 outvec)
1089 {
1090         outvec = vec3(vec.xy*0.5 + vec2(0.5, 0.5), vec.z);
1091 }
1092
1093 void mtex_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
1094 {
1095         color = texture2D(ima, vec.xy);
1096         value = 1.0;
1097         
1098         normal = 2.0*(vec3(color.r, -color.g, color.b) - vec3(0.5, -0.5, 0.5));
1099 }
1100
1101 /*
1102         Helper function for on the fly normal map generation from height map.
1103 */
1104 void mtex_h2n_rgb2float(vec4 color, out float outval)
1105 {
1106         float scale = 1.0;
1107         outval = (color.r + color.g + color .b) / 3.0 * scale;
1108 }
1109
1110 /*
1111         On the fly normal map generation from bump map.
1112         
1113         This is replacement for mtex_image which generates the normal value from a height value.
1114         It is inspired by The GIMP normal map plugin. I took the explicit algorithm and
1115         streamlined it to fit implicit GPU computation.
1116 */
1117 void mtex_height_to_normal(vec3 texcoord, sampler2D image, vec2 texsize, out float value, out vec4 color, out vec3 normal)
1118 {
1119         float down, up, right, left;
1120         /*texsize.xy = textureSize2D(image, 0);*/
1121         
1122         mtex_h2n_rgb2float( texture2D(image, texcoord.st+vec2(0,1)/texsize.xy), down );
1123         mtex_h2n_rgb2float( texture2D(image, texcoord.st+vec2(0,-1)/texsize.xy), up );
1124         mtex_h2n_rgb2float( texture2D(image, texcoord.st+vec2(1,0)/texsize.xy), right );
1125         mtex_h2n_rgb2float( texture2D(image, texcoord.st+vec2(-1,0)/texsize.xy), left );
1126
1127         normal = normalize(vec3(left - right, down - up, 1.0));
1128         color = texture2D(image, texcoord.xy);
1129         value = 1.0;
1130 }
1131
1132 void mtex_negate_texnormal(vec3 normal, out vec3 outnormal)
1133 {
1134         outnormal = vec3(-normal.x, -normal.y, normal.z);
1135 }
1136
1137 void mtex_nspace_tangent(vec3 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
1138 {
1139         tangent = normalize(tangent);
1140         vec3 B = cross(normal, tangent);
1141
1142         outnormal = texnormal.x*tangent + texnormal.y*B + texnormal.z*normal;
1143         outnormal = normalize(outnormal);
1144 }
1145
1146 void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
1147 {
1148         outnormal = (1.0 - norfac)*normal + norfac*newnormal;
1149         outnormal = normalize(outnormal);
1150 }
1151
1152 /******* MATERIAL *********/
1153
1154 void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac)
1155 {
1156         lv = lampvec;
1157         dist = 1.0;
1158         visifac = 1.0;
1159 }
1160
1161 void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac)
1162 {
1163         lv = co - lampco;
1164         dist = length(lv);
1165         lv = normalize(lv);
1166         visifac = 1.0;
1167 }
1168
1169 void lamp_falloff_invlinear(float lampdist, float dist, out float visifac)
1170 {
1171         visifac = lampdist/(lampdist + dist);
1172 }
1173
1174 void lamp_falloff_invsquare(float lampdist, float dist, out float visifac)
1175 {
1176         visifac = lampdist/(lampdist + dist*dist);
1177 }
1178
1179 void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac)
1180 {
1181         float lampdistkw = lampdist*lampdist;
1182
1183         visifac = lampdist/(lampdist + ld1*dist);
1184         visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
1185 }
1186
1187 void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac)
1188 {
1189         visifac = texture1D(curvemap, dist/lampdist).x;
1190 }
1191
1192 void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
1193 {
1194         float t= lampdist - dist;
1195
1196         outvisifac= visifac*max(t, 0.0)/lampdist;
1197 }
1198
1199 void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr)
1200 {
1201         if(dot(lv, lampvec) > 0.0) {
1202                 vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
1203                 float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z));
1204
1205                 inpr = 1.0/sqrt(1.0 + x*x);
1206         }
1207         else
1208                 inpr = 0.0;
1209 }
1210
1211 void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr)
1212 {
1213         inpr = dot(lv, lampvec);
1214 }
1215
1216 void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)
1217 {
1218         float t = spotsi;
1219
1220         if(inpr <= t) {
1221                 outvisifac = 0.0;
1222         }
1223         else {
1224                 t = inpr - t;
1225
1226                 /* soft area */
1227                 if(spotbl != 0.0)
1228                         inpr *= smoothstep(0.0, 1.0, t/spotbl);
1229
1230                 outvisifac = visifac*inpr;
1231         }
1232 }
1233
1234 void lamp_visibility_clamp(float visifac, out float outvisifac)
1235 {
1236         outvisifac = (visifac < 0.001)? 0.0: visifac;
1237 }
1238
1239 void shade_view(vec3 co, out vec3 view)
1240 {
1241         /* handle perspective/orthographic */
1242         view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0);
1243 }
1244
1245 void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
1246 {
1247         vec3 c = cross(lv, tang);
1248         vec3 vnor = cross(c, tang);
1249
1250         vn = -normalize(vnor);
1251 }
1252
1253 void shade_inp(vec3 vn, vec3 lv, out float inp)
1254 {
1255         inp = dot(vn, lv);
1256 }
1257
1258 void shade_is_no_diffuse(out float is)
1259 {
1260         is = 0.0;
1261 }
1262
1263 void shade_is_hemi(float inp, out float is)
1264 {
1265         is = 0.5*inp + 0.5;
1266 }
1267
1268 float area_lamp_energy(mat4 area, vec3 co, vec3 vn)
1269 {
1270         vec3 vec[4], c[4];
1271         float rad[4], fac;
1272         
1273         vec[0] = normalize(co - area[0].xyz);
1274         vec[1] = normalize(co - area[1].xyz);
1275         vec[2] = normalize(co - area[2].xyz);
1276         vec[3] = normalize(co - area[3].xyz);
1277
1278         c[0] = normalize(cross(vec[0], vec[1]));
1279         c[1] = normalize(cross(vec[1], vec[2]));
1280         c[2] = normalize(cross(vec[2], vec[3]));
1281         c[3] = normalize(cross(vec[3], vec[0]));
1282
1283         rad[0] = acos(dot(vec[0], vec[1]));
1284         rad[1] = acos(dot(vec[1], vec[2]));
1285         rad[2] = acos(dot(vec[2], vec[3]));
1286         rad[3] = acos(dot(vec[3], vec[0]));
1287
1288         fac=  rad[0]*dot(vn, c[0]);
1289         fac+= rad[1]*dot(vn, c[1]);
1290         fac+= rad[2]*dot(vn, c[2]);
1291         fac+= rad[3]*dot(vn, c[3]);
1292
1293         return max(fac, 0.0);
1294 }
1295
1296 void shade_inp_area(vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, out float inp)
1297 {
1298         vec3 co = position;
1299         vec3 vec = co - lampco;
1300
1301         if(dot(vec, lampvec) < 0.0) {
1302                 inp = 0.0;
1303         }
1304         else {
1305                 float intens = area_lamp_energy(area, co, vn);
1306
1307                 inp = pow(intens*areasize, k);
1308         }
1309 }
1310
1311 void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is)
1312 {
1313         vec3 h = normalize(v + l);
1314         float nh = max(dot(n, h), 0.0);
1315         float nv = max(dot(n, v), 0.0);
1316         float realnl = dot(n, l);
1317
1318         if(realnl < 0.0) {
1319                 is = 0.0;
1320         }
1321         else if(nl < 0.0) {
1322                 is = 0.0;
1323         }
1324         else {
1325                 float vh = max(dot(v, h), 0.0);
1326                 float Lit_A = acos(realnl);
1327                 float View_A = acos(nv);
1328
1329                 vec3 Lit_B = normalize(l - realnl*n);
1330                 vec3 View_B = normalize(v - nv*n);
1331
1332                 float t = max(dot(Lit_B, View_B), 0.0);
1333
1334                 float a, b;
1335
1336                 if(Lit_A > View_A) {
1337                         a = Lit_A;
1338                         b = View_A;
1339                 }
1340                 else {
1341                         a = View_A;
1342                         b = Lit_A;
1343                 }
1344
1345                 float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33)));
1346                 float B = 0.45*((rough*rough)/((rough*rough) + 0.09));
1347
1348                 b *= 0.95;
1349                 is = nl*(A + (B * t * sin(a) * tan(b)));
1350         }
1351 }
1352
1353 void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is)
1354 {
1355         float rslt = dot(n, l);
1356         float ang = acos(rslt);
1357
1358         if(ang < size) is = 1.0;
1359         else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0;
1360         else is = 1.0 - ((ang - size)/tsmooth);
1361 }
1362
1363 void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is)
1364 {
1365         if(nl <= 0.0) {
1366                 is = 0.0;
1367         }
1368         else {
1369                 float nv = max(dot(n, v), 0.0);
1370
1371                 if(darkness <= 1.0)
1372                         is = nl*pow(max(nv*nl, 0.1), darkness - 1.0);
1373                 else
1374                         is = nl*pow(1.0001 - nv, darkness - 1.0);
1375         }
1376 }
1377
1378 float fresnel_fac(vec3 view, vec3 vn, float grad, float fac)
1379 {
1380         float t1, t2;
1381         float ffac;
1382
1383         if(fac==0.0) {
1384                 ffac = 1.0;
1385         }
1386         else {
1387                 t1= dot(view, vn);
1388                 if(t1>0.0)  t2= 1.0+t1;
1389                 else t2= 1.0-t1;
1390
1391                 t2= grad + (1.0-grad)*pow(t2, fac);
1392
1393                 if(t2<0.0) ffac = 0.0;
1394                 else if(t2>1.0) ffac = 1.0;
1395                 else ffac = t2;
1396         }
1397
1398         return ffac;
1399 }
1400
1401 void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is)
1402 {
1403         is = fresnel_fac(lv, vn, fac_i, fac);
1404 }
1405
1406 void shade_cubic(float is, out float outis)
1407 {
1408         if(is>0.0 && is<1.0)
1409                 outis= smoothstep(0.0, 1.0, is);
1410         else
1411                 outis= is;
1412 }
1413
1414 void shade_visifac(float i, float visifac, float refl, out float outi)
1415 {
1416         /*if(i > 0.0)*/
1417                 outi = max(i*visifac*refl, 0.0);
1418         /*else
1419                 outi = i;*/
1420 }
1421
1422 void shade_tangent_v_spec(vec3 tang, out vec3 vn)
1423 {
1424         vn = tang;
1425 }
1426
1427 void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol)
1428 {
1429         if(i > 0.0)
1430                 outcol = i*lampcol*col;
1431         else
1432                 outcol = vec3(0.0, 0.0, 0.0);
1433 }
1434
1435 void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t)
1436 {
1437         lv += view;
1438         lv = normalize(lv);
1439
1440         t = dot(vn, lv);
1441         t = 0.5*t + 0.5;
1442
1443         t = visifac*spec*pow(t, hard);
1444 }
1445
1446 void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
1447 {
1448         vec3 h = normalize(l + v);
1449         float rslt = max(dot(h, n), 0.0);
1450
1451         specfac = pow(rslt, hard);
1452 }
1453
1454 void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
1455 {
1456         vec3 h = normalize(v + l);
1457         float nh = dot(n, h);
1458
1459         if(nh < 0.0) {
1460                 specfac = 0.0;
1461         }
1462         else {
1463                 float nv = max(dot(n, v), 0.0);
1464                 float i = pow(nh, hard);
1465
1466                 i = i/(0.1+nv);
1467                 specfac = i;
1468         }
1469 }
1470
1471 void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac)
1472 {
1473         if(refrac < 1.0) {
1474                 specfac = 0.0;
1475         }
1476         else if(spec_power == 0.0) {
1477                 specfac = 0.0;
1478         }
1479         else {
1480                 if(spec_power<100.0)
1481                         spec_power= sqrt(1.0/spec_power);
1482                 else
1483                         spec_power= 10.0/spec_power;
1484
1485                 vec3 h = normalize(v + l);
1486                 float nh = dot(n, h);
1487                 if(nh < 0.0) {
1488                         specfac = 0.0;
1489                 }
1490                 else {
1491                         float nv = max(dot(n, v), 0.01);
1492                         float nl = dot(n, l);
1493                         if(nl <= 0.01) {
1494                                 specfac = 0.0;
1495                         }
1496                         else {
1497                                 float vh = max(dot(v, h), 0.01);
1498
1499                                 float a = 1.0;
1500                                 float b = (2.0*nh*nv)/vh;
1501                                 float c = (2.0*nh*nl)/vh;
1502
1503                                 float g = 0.0;
1504
1505                                 if(a < b && a < c) g = a;
1506                                 else if(b < a && b < c) g = b;
1507                                 else if(c < a && c < b) g = c;
1508
1509                                 float p = sqrt(((refrac * refrac)+(vh*vh)-1.0));
1510                                 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))));
1511                                 float ang = acos(nh);
1512
1513                                 specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0);
1514                         }
1515                 }
1516         }
1517 }
1518
1519 void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac)
1520 {
1521         vec3 h = normalize(l + v);
1522         float nh = max(dot(n, h), 0.001);
1523         float nv = max(dot(n, v), 0.001);
1524         float nl = max(dot(n, l), 0.001);
1525         float angle = tan(acos(nh));
1526         float alpha = max(rms, 0.001);
1527
1528         specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
1529 }
1530
1531 void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac)
1532 {
1533         vec3 h = normalize(l + v);
1534         float rslt = dot(h, n);
1535         float ang = acos(rslt);
1536
1537         if(ang < size) rslt = 1.0;
1538         else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0;
1539         else rslt = 1.0 - ((ang - size)/tsmooth);
1540
1541         specfac = rslt;
1542 }
1543
1544 void shade_spec_area_inp(float specfac, float inp, out float outspecfac)
1545 {
1546         outspecfac = specfac*inp;
1547 }
1548
1549 void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t)
1550 {
1551         t = shadfac*spec*visifac*specfac;
1552 }
1553
1554 void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
1555 {
1556         outcol = t*lampcol*speccol;
1557 }
1558
1559 void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
1560 {
1561         outcol = col1 + col2;
1562 }
1563
1564 void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
1565 {
1566         outcol = col + col1*col2;
1567 }
1568
1569 void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol)
1570 {
1571         outcol = col + f*col1;
1572 }
1573
1574 void shade_mul(vec4 col1, vec4 col2, out vec4 outcol)
1575 {
1576         outcol = col1*col2;
1577 }
1578
1579 void shade_mul_value(float fac, vec4 col, out vec4 outcol)
1580 {
1581         outcol = col*fac;
1582 }
1583
1584 void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
1585 {
1586         outcol = vec4(col.rgb*obcol.rgb, col.a);
1587 }
1588
1589 void ramp_rgbtobw(vec3 color, out float outval)
1590 {
1591         outval = color.r*0.3 + color.g*0.58 + color.b*0.12;
1592 }
1593
1594 void shade_only_shadow(float i, float shadfac, float energy, out float outshadfac)
1595 {
1596         outshadfac = i*energy*(1.0 - shadfac);
1597 }
1598
1599 void shade_only_shadow_diffuse(float shadfac, vec3 rgb, vec4 diff, out vec4 outdiff)
1600 {
1601         outdiff = diff - vec4(rgb*shadfac, 0.0);
1602 }
1603
1604 void shade_only_shadow_specular(float shadfac, vec3 specrgb, vec4 spec, out vec4 outspec)
1605 {
1606         outspec = spec - vec4(specrgb*shadfac, 0.0);
1607 }
1608
1609 void test_shadowbuf(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, out float result)
1610 {
1611         if(inp <= 0.0) {
1612                 result = 0.0;
1613         }
1614         else {
1615                 vec4 co = shadowpersmat*vec4(rco, 1.0);
1616
1617                 //float bias = (1.5 - inp*inp)*shadowbias;
1618                 co.z -= shadowbias*co.w;
1619
1620                 result = shadow2DProj(shadowmap, co).x;
1621         }
1622 }
1623
1624 void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol)
1625 {
1626         outcol = linfac*(1.0 - exp(col*logfac));
1627 }
1628
1629 void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac)
1630 {
1631         float fac, zcor;
1632
1633         zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
1634         
1635         fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0);
1636         if(misttype == 0.0) fac *= fac;
1637         else if(misttype == 1.0);
1638         else fac = sqrt(fac);
1639
1640         outfac = 1.0 - (1.0-fac)*(1.0-misi);
1641 }
1642
1643 void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol)
1644 {
1645         float fac = clamp(col.a, 0.0, 1.0);
1646         outcol = vec4(mix(hor, col.rgb, fac), col.a);
1647 }
1648
1649 void shade_alpha_opaque(vec4 col, out vec4 outcol)
1650 {
1651         outcol = vec4(col.rgb, 1.0);
1652 }
1653
1654 void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
1655 {
1656         outcol = vec4(col.rgb, col.a*obcol.a);
1657 }
1658