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