1 /* Beta-0.4.7: MOSAIC support library for Blender to RenderMan shader integration */
2 
3 
4 //////// Global Define Constants...
5 
6 /* These generated constants are for simplifing use of the list based token parameters returned by MOSAIC.
7    They are defined here so they are globally accessible for parameter passing between shaders. */
8 
9 // Global Constants...
10 #define GLOB_TEX_CHANNELS 10
11 #define	GLOB_UF_PARALEN 2
12 
13 #define	MAT_UF_SETMODE 0
14 #define	MAT_UF_SETINDEX 1
15 
16 // MOSAICsurface Constants...
17 #define	MAT_UF_PARALEN 61
18 #define	MAT_UC_PARALEN 7
19 #define	TEX_US_PARALEN 10
20 #define	TEX_VF_PARALEN 41
21 
22 #define	MAT_UF_AMB 0
23 #define	MAT_UF_REF 1
24 #define	MAT_UF_SPEC 2
25 #define	MAT_UF_HARD 3
26 #define	MAT_UF_ALPHA 4
27 #define	MAT_UF_OBJALPHA 5
28 #define	MAT_UF_TRALU 6
29 #define	MAT_UF_EMIT 7
30 #define	MAT_UF_ROUGHNESS 8
31 #define	MAT_UF_DIFFDARK 9
32 #define	MAT_UF_DIFFSIZE 10
33 #define	MAT_UF_DIFFSMOOTH 11
34 #define	MAT_UF_IOR 12
35 #define	MAT_UF_RAYMIR 13
36 #define	MAT_UF_MIRRAYDEPTH 14
37 #define	MAT_UF_MIRFRESNEL 15
38 #define	MAT_UF_MIRFRESFAC 16
39 #define	MAT_UF_MIRSAMPLES 17
40 #define	MAT_UF_MIRGLOSS 18
41 #define	MAT_UF_TRANSPRAYDEPTH 19
42 #define	MAT_UF_TRANSPFRESNEL 20
43 #define	MAT_UF_TRANSPFRESFAC 21
44 #define	MAT_UF_TRANSPSAMPLES 22
45 #define	MAT_UF_TRANSPGLOSS 23
46 #define	MAT_UF_TRANSPFILTER 24
47 #define	MAT_UF_TRANSPSPECTRA 25
48 #define	MAT_UF_SSSUSE 26
49 #define	MAT_UF_SSSIOR 27
50 #define	MAT_UF_SSSERROR 28
51 #define	MAT_UF_SSSSCALE 29
52 #define	MAT_UF_SSSTEX 30
53 #define	MAT_UF_SSSFRONT 31
54 #define	MAT_UF_SSSBACK 32
55 #define	MAT_UF_SSSRADIUSR 33
56 #define	MAT_UF_SSSRADIUSG 34
57 #define	MAT_UF_SSSRADIUSB 35
58 #define	MAT_UF_SSSCOLBLEND 36
59 #define	MAT_UF_SPECREFRACT 37
60 #define	MAT_UF_SPECSIZE 38
61 #define	MAT_UF_SPECSMOOTH 39
62 #define	MAT_UF_SPECRMS 40
63 #define	MAT_UF_DIFFUSETYPE 41
64 #define	MAT_UF_SPECULARTYPE 42
65 #define	MAT_UF_SHADALPHA 43
66 #define	MAT_UF_ISSTRANDTAN 44
67 #define	MAT_UF_ISCUBIC 45
68 #define	MAT_UF_ISOBJCOL 46
69 #define	MAT_UF_ISRAYMIRROR 47
70 #define	MAT_UF_ISRAYTRANSP 48
71 #define	MAT_UF_ISSHADOW 49
72 #define	MAT_UF_ISONLYSHADOW 50
73 #define	MAT_UF_ISTRANSPSHADOW 51
74 #define	MAT_UF_ISENV 52
75 #define	MAT_UF_ISWIRE 53
76 #define	MAT_UF_ISTANGENT 54
77 #define	MAT_UF_ISNOMIST 55
78 #define	MAT_UF_ISVCOLLIGHT 56
79 #define	MAT_UF_ISVCOLPAINT 57
80 #define	MAT_UF_TEXFACE 58
81 #define	MAT_UF_ISTEXFACEALPHA 59
82 #define	MAT_UF_ISSHADLESS 60
83 #define	MAT_UC_DIFCOL 0
84 #define	MAT_UC_SPECCOL 1
85 #define	MAT_UC_MIRCOL 2
86 #define	MAT_UC_HORCOL 3
87 #define	MAT_UC_AMBCOL 4
88 #define	MAT_UC_OBJCOL 5
89 #define	MAT_UC_SSSCOL 6
90 #define	TEX_US_TEXSLOT1 0
91 #define	TEX_US_TEXSLOT2 1
92 #define	TEX_US_TEXSLOT3 2
93 #define	TEX_US_TEXSLOT4 3
94 #define	TEX_US_TEXSLOT5 4
95 #define	TEX_US_TEXSLOT6 5
96 #define	TEX_US_TEXSLOT7 6
97 #define	TEX_US_TEXSLOT8 7
98 #define	TEX_US_TEXSLOT9 8
99 #define	TEX_US_TEXSLOT10 9
100 #define	TEX_VF_STCOOR 0
101 #define	TEX_VF_STLAYER 1
102 #define	TEX_VF_USEALPHA 2
103 #define	TEX_VF_CALCALPHA 3
104 #define	TEX_VF_NEGALPHA 4
105 #define	TEX_VF_FILTER 5
106 #define	TEX_VF_ROT90 6
107 #define	TEX_VF_STENCIL 7
108 #define	TEX_VF_NEG 8
109 #define	TEX_VF_NORGB 9
110 #define	TEX_VF_OFSX 10
111 #define	TEX_VF_OFSY 11
112 #define	TEX_VF_OFSZ 12
113 #define	TEX_VF_SIZEX 13
114 #define	TEX_VF_SIZEY 14
115 #define	TEX_VF_SIZEZ 15
116 #define	TEX_VF_ISCOL 16
117 #define	TEX_VF_ISCSP 17
118 #define	TEX_VF_ISCMIR 18
119 #define	TEX_VF_ISREF 19
120 #define	TEX_VF_ISSPEC 20
121 #define	TEX_VF_ISAMB 21
122 #define	TEX_VF_ISHARD 22
123 #define	TEX_VF_ISRAYMIR 23
124 #define	TEX_VF_ISALPHA 24
125 #define	TEX_VF_ISEMIT 25
126 #define	TEX_VF_ISTRANSLU 26
127 #define	TEX_VF_ISWARP 27
128 #define	TEX_VF_BRIGHT 28
129 #define	TEX_VF_CONTR 29
130 #define	TEX_VF_R 30
131 #define	TEX_VF_G 31
132 #define	TEX_VF_B 32
133 #define	TEX_VF_TEXR 33
134 #define	TEX_VF_TEXG 34
135 #define	TEX_VF_TEXB 35
136 #define	TEX_VF_BLENDMODE 36
137 #define	TEX_VF_WARPFAC 37
138 #define	TEX_VF_BLENDCOL 38
139 #define	TEX_VF_BLENDVAR 39
140 #define	TEX_VF_BLENDDVAR 40
141 
142 // MOSAICdisplace constants...
143 #define	DISP_US_PARALEN 10
144 #define	DISP_VF_PARALEN 27
145 
146 #define	DISP_US_TEXSLOT1 0
147 #define	DISP_US_TEXSLOT2 1
148 #define	DISP_US_TEXSLOT3 2
149 #define	DISP_US_TEXSLOT4 3
150 #define	DISP_US_TEXSLOT5 4
151 #define	DISP_US_TEXSLOT6 5
152 #define	DISP_US_TEXSLOT7 6
153 #define	DISP_US_TEXSLOT8 7
154 #define	DISP_US_TEXSLOT9 8
155 #define	DISP_US_TEXSLOT10 9
156 #define	DISP_VF_STCOOR 0
157 #define	DISP_VF_STLAYER 1
158 #define	DISP_VF_USEALPHA 2
159 #define	DISP_VF_CALCALPHA 3
160 #define	DISP_VF_NEGALPHA 4
161 #define	DISP_VF_FILTER 5
162 #define	DISP_VF_ROT90 6
163 #define	DISP_VF_STENCIL 7
164 #define	DISP_VF_NEG 8
165 #define	DISP_VF_OFSX 9
166 #define	DISP_VF_OFSY 10
167 #define	DISP_VF_OFSZ 11
168 #define	DISP_VF_SIZEX 12
169 #define	DISP_VF_SIZEY 13
170 #define	DISP_VF_SIZEZ 14
171 #define	DISP_VF_ISNOR 15
172 #define	DISP_VF_MID 16
173 #define	DISP_VF_VERTGRP 17
174 #define	DISP_VF_ISDISP 18
175 #define	DISP_VF_BRIGHT 19
176 #define	DISP_VF_CONTR 20
177 #define	DISP_VF_TEXR 21
178 #define	DISP_VF_TEXG 22
179 #define	DISP_VF_TEXB 23
180 #define	DISP_VF_BLENDMODE 24
181 #define	DISP_VF_NORFAC 25
182 #define	DISP_VF_DISPFAC 26
183 
184 // MOSAIClight constants...
185 #define	LAMP_UF_PARALEN 21
186 #define	LAMP_UC_PARALEN 1
187 #define	LAMP_US_PARALEN 10
188 #define	LAMP_VF_PARALEN 25
189 
190 #define	LAMP_UF_NODIFFUSE 0
191 #define	LAMP_UF_NOSPECULAR 1
192 #define	LAMP_UF_ISNEGATIVE 2
193 #define	LAMP_UF_ISONLYSHAD 3
194 #define	LAMP_UF_ISSQUARE 4
195 #define	LAMP_UF_ISHALO 5
196 #define	LAMP_UF_HALOINT 6
197 #define	LAMP_UF_FALLOFFTYPE 7
198 #define	LAMP_UF_ISSPHERE 8
199 #define	LAMP_UF_QUAD1 9
200 #define	LAMP_UF_QUAD2 10
201 #define	LAMP_UF_LAMPTYPE 11
202 #define	LAMP_UF_ENERGY 12
203 #define	LAMP_UF_DIST 13
204 #define	LAMP_UF_SPOTSI 14
205 #define	LAMP_UF_SPOTBL 15
206 #define	LAMP_UF_BIAS 16
207 #define	LAMP_UF_BUFSOFT 17
208 #define	LAMP_UF_RAYSOFT 18
209 #define	LAMP_UF_BUFSAMP 19
210 #define	LAMP_UF_RAYSAMP 20
211 #define	LAMP_UC_LAMPCOL 0
212 #define	LAMP_US_TEXSLOT1 0
213 #define	LAMP_US_TEXSLOT2 1
214 #define	LAMP_US_TEXSLOT3 2
215 #define	LAMP_US_TEXSLOT4 3
216 #define	LAMP_US_TEXSLOT5 4
217 #define	LAMP_US_TEXSLOT6 5
218 #define	LAMP_US_TEXSLOT7 6
219 #define	LAMP_US_TEXSLOT8 7
220 #define	LAMP_US_TEXSLOT9 8
221 #define	LAMP_US_TEXSLOT10 9
222 #define	LAMP_VF_USEALPHA 0
223 #define	LAMP_VF_CALCALPHA 1
224 #define	LAMP_VF_NEGALPHA 2
225 #define	LAMP_VF_FILTER 3
226 #define	LAMP_VF_ROT90 4
227 #define	LAMP_VF_STENCIL 5
228 #define	LAMP_VF_NEG 6
229 #define	LAMP_VF_NORGB 7
230 #define	LAMP_VF_OFSX 8
231 #define	LAMP_VF_OFSY 9
232 #define	LAMP_VF_OFSZ 10
233 #define	LAMP_VF_SIZEX 11
234 #define	LAMP_VF_SIZEY 12
235 #define	LAMP_VF_SIZEZ 13
236 #define	LAMP_VF_ISCOL 14
237 #define	LAMP_VF_BRIGHT 15
238 #define	LAMP_VF_CONTR 16
239 #define	LAMP_VF_R 17
240 #define	LAMP_VF_G 18
241 #define	LAMP_VF_B 19
242 #define	LAMP_VF_TEXR 20
243 #define	LAMP_VF_TEXG 21
244 #define	LAMP_VF_TEXB 22
245 #define	LAMP_VF_BLENDMODE 23
246 #define	LAMP_VF_BLENDCOL 24
247 
248 // MOSAICfog constants...
249 #define	MIST_UF_PARALEN 6
250 #define	MIST_UC_PARALEN 1
251 
252 #define	MIST_UF_ISMIST 0
253 #define	MIST_UF_MISTTYPE 1
254 #define	MIST_UF_MISTINT 2
255 #define	MIST_UF_MISTSTA 3
256 #define	MIST_UF_MISTDI 4
257 #define	MIST_UF_MISTHI 5
258 #define	MIST_UC_MISTCOL 0
259 
260 // MOSAICbackground constants...
261 
262 
263 
264 
265 //////// Global Define Functions...
266 
267 #define CUBICDIFFUSE 1.4
268 #define MINFILTERWIDTH  1e-7
269 #define filterwidthf(x) (max(abs(Du(x) * (du)) + (Dv(x) * (dv)),MINFILTERWIDTH))
270 #define filterwidthp(x) (max(sqrt(area(x)), MINFILTERWIDTH))
271 
272 
273 //////// Global Utility Functions...
274 
275 //// Adjust sAdj and tAdj by xy offset and size
stAdjust(output float sAdj;output float tAdj;float offX;float offY;float scaleX;float scaleY;)276 void stAdjust(
277     output float sAdj;      // s texture coordinate to adjust
278     output float tAdj;      // t texture coordinate to adjust
279     float offX;             // +/- texture offset along s
280     float offY;             // +/- texture offset along t
281     float scaleX;           // scale factor along s
282     float scaleY;)          // scale factor along t
283 {
284     sAdj    = (sAdj*scaleX-(scaleX-1)/2)+offX;
285     tAdj    = (tAdj*scaleY-(scaleY-1)/2)-offY;
286 }
287 
288 
289 //// Blend color1 into color2 by value according to mode and return result, modes are:
290 //// 0-13 (mix,mult,add,sub,divide,darken,diff,lighten,screen,overlay,hue,saturation,value,color)
colorblend(color color1;color color2;float mode;float value;float pos_neg;)291 color colorblend(
292     color color1;           // First color to blend
293     color color2;           // Second color to blend
294     float mode;             // Blend mode see above
295     float value;            // Blend first color into second color by this factor
296     float pos_neg;)         // Positive or negative (inverted) result
297 {
298     color blendcolor    = color(1);
299     color outputcolor   = color(1);
300     if (mode == 0)          // mix
301         blendcolor      = color2;
302     else if (mode == 1)     // mult
303         blendcolor      = color1*color2;
304     else if (mode == 2)     // add
305         blendcolor      = color1+color2;
306     else if (mode == 3)     // sub
307         blendcolor      = max(color1-color2, color(0));
308     else if (mode == 4)     // divide
309         blendcolor      = max(color1/color2, color(0));
310     else if (mode == 5)     // darken
311         blendcolor      = min(color1, color2);
312     else if (mode == 6)     // diff
313         blendcolor      = max(color1, color2)-min(color1, color2);
314     else if (mode == 7)     // lighten
315         blendcolor      = max(color1, color2);
316     else if (mode == 8)     // screen
317         blendcolor      = color(1)-((color(1)-color2)*(color(1)-color1));
318     else if (mode == 9)     // overlay
319         blendcolor      = (color1*(color(1)-((color(1)-color2)*(color(1)-color1))))+((color(1)-color1)*color1*color2);
320     else                    // setup for hsv modes
321     {
322         float hue1      = comp(ctransform("hsv", color1), 0);
323         float sat1      = comp(ctransform("hsv", color1), 1);
324         float val1      = comp(ctransform("hsv", color1), 2);
325         float hue2      = comp(ctransform("hsv", color2), 0);
326         float sat2      = comp(ctransform("hsv", color2), 1);
327         float val2      = comp(ctransform("hsv", color2), 2);
328         float lit1      = comp(ctransform("hsl", color1), 2);
329         blendcolor      = ctransform("rgb", "hsv", blendcolor);
330         if (mode == 10)     // hue
331         {
332             setcomp(blendcolor, 0, hue2);
333             setcomp(blendcolor, 1, sat1);
334             setcomp(blendcolor, 2, val1);
335         }
336         else if (mode == 11)// saturation
337         {
338             setcomp(blendcolor, 0, hue1);
339             setcomp(blendcolor, 1, sat2);
340             setcomp(blendcolor, 2, val1);
341         }
342         else if (mode == 12)// value
343         {
344             setcomp(blendcolor, 0, hue1);
345             setcomp(blendcolor, 1, sat1);
346             setcomp(blendcolor, 2, val2);
347         }
348         else if (mode == 13)// color
349         {
350             setcomp(blendcolor, 0, hue2);
351             setcomp(blendcolor, 1, sat2);
352             setcomp(blendcolor, 2, lit1);
353         }
354         blendcolor      = ctransform("hsv", "rgb", blendcolor);
355     }
356     outputcolor         = mix(color1, blendcolor, value);
357     if (pos_neg < 0)
358         outputcolor     = max(color(0), 1-outputcolor);
359     return outputcolor;
360 }
361 
362 
363 //// Returns attenuation factor for Length based on Type and controlled using Linear and Quad
Attenuate(float Type;float Length;float Distance;float Linear;float Quad;float Sphere;)364 float Attenuate(
365     float Type;             // Specifies attenuation type (0 = constant, 1 = inverse linear, 2 = inverse square, 3 = Lin/Quad weighted)
366     float Length;           // Length to attenuate
367     float Distance;         // Distance to attenuate by
368     float Linear;           // Linear factor for Lin/Quad type
369     float Quad;             // Quadratic factor for Lin/Quad type
370     float Sphere;)          // Use Distance as absolute term for all attenuation types (0 || 1)
371 {
372     float                   q1, q2, q3, a1 = 1, a2 = 1, a3 = 1, Atten = 1;
373     if (Type > 0)           // Are we attenuating at all?
374     {
375         if (Type == 1)      // inverse linear setup
376         {
377             q1          = 1;
378             q2          = 0;
379             q3          = 0;
380         }
381         else if (Type == 2) // inverse square setup
382         {
383             q1          = 0;
384             q2          = 0;
385             q3          = 1;
386         }
387         else                // Linear/Quadratic weighted
388         {
389             q1          = Linear;
390             q2          = Quad;
391             q3          = 0;
392         }
393         if (q1 > 0)         // Linear equation
394             a1          = Distance/(Distance+q1*Length);
395         if (q2 > 0)         // Quadratic equation
396             a2          = pow(Distance, 2)/(pow(Distance, 2)+q2*pow(Length, 2));
397         if (q3 > 0)         // Inverse Square Equation
398             a3          = Distance/(Distance+q3*pow(Length, 2));
399         Atten           = a1*a2*a3;
400     }
401     if (Sphere > 0)         // Are we using sphere attenuation?
402         Atten           *= (Distance-Length)/Distance;
403     return max(0, Atten);
404 }
405 
406 
407 //////// Surface Shader Utility Functions...
408 
409 #ifdef SURFACE_UTILITIES
410 
411 //// Returns Oren-Nayer diffusion model modified from Larry Gritz's source
orennayardiff(normal Nf;vector In;vector Eye;float sigma;float isCubic;float translu;output color _shadow;output color _caustic;)412 color orennayardiff(
413     normal Nf;              // Normalized faceforward surface normal
414     vector In;              // Normalized camera vector
415     vector Eye;             // Eye vector
416     float sigma;            // Roughness
417     float isCubic;          // Use cubic terminator blend
418     float translu;          // Translucent diffuse factor
419     output color _shadow;   // Shadow layer for composite
420     output color _caustic;) // Caustic layer for composite
421 {
422     extern point        P;
423     extern vector       L;
424     vector              Ln;
425     float               Fd;
426     float               C1, C2, C3, L1, L2;
427     float               theta_r, theta_i, cos_theta_i;
428     float               alpha, beta, sigma2, cos_phi_diff;
429     float nondiff       = 0;
430     float lighttype     = 0;
431     color diffuse       = color(0);
432     color lightcolor    = color(1);
433     color shadowcolor   = color(1);
434     color causticcolor  = color(0);
435     theta_r             = acos(abs(Eye.Nf));
436     sigma2              = sigma*sigma;
437     illuminance(P)
438     {
439         lightsource("__nondiffuse", nondiff);
440         if (nondiff == 0)
441         {
442             lightsource("__lighttype", lighttype);
443             lightsource("__lightcolor", lightcolor);
444             lightsource("__shadowcolor", shadowcolor);
445             lightsource("__causticcolor", causticcolor);
446             Ln          = normalize(L);
447             if (lighttype == 3)
448             {
449                 Fd      = min((Nf.Ln+1)/2, 1);
450             }
451             else
452             {
453                 cos_theta_i = max(0, Ln.Nf);
454                 cos_phi_diff= normalize(Eye-Nf*(Eye.Nf)).normalize(Ln-Nf*(max(0, Ln.Nf)));
455                 theta_i = acos(cos_theta_i);
456                 alpha   = max(theta_i, theta_r);
457                 beta    = min(theta_i, theta_r);
458                 C1      = 1-0.5*sigma2/(sigma2+0.33);
459                 C2      = 0.45*sigma2/(sigma2 + 0.09);
460                 if (cos_phi_diff >= 0)  C2 *= sin(alpha);
461                 else                    C2 *= (sin(alpha)-pow(2*beta/PI,3));
462                 C3      = 0.125*sigma2/(sigma2+0.09)*pow((4*alpha*beta)/(PI*PI),2);
463                 L1      = cos_theta_i*(C1+cos_phi_diff*C2*tan(beta)+(1-abs(cos_phi_diff))*C3*tan((alpha+beta)/2));
464                 L2      = 0.17*cos_theta_i*sigma2/(sigma2+0.13)*(1-cos_phi_diff*(4*beta*beta)/(PI*PI));
465                 Fd      = L1+L2;
466             }
467             if (translu > 0)
468                 Fd      += max(0, -Nf.Ln)*translu;
469             if (isCubic)
470                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
471             diffuse     += lightcolor*Fd;
472             if (Fd > 0)
473             {
474                 _shadow     += lightcolor*shadowcolor*Fd;
475                 _caustic    += causticcolor*Fd;
476             }
477         }
478     }
479     return diffuse;
480 }
481 
482 
483 //// Returns simple toon cell shading for diffusion
toondiff(normal Nf;float diffSize;float diffSmooth;float isCubic;float translu;output color _shadow;output color _caustic;)484 color toondiff(
485     normal Nf;              // Normalized faceforward surface normal
486     float diffSize;         // Size of solid diffusion color
487     float diffSmooth;       // Edge smoothing of solid color
488     float isCubic;          // Use cubic terminator blend
489     float translu;          // Translucent diffuse factor
490     output color _shadow;   // Shadow layer for composite
491     output color _caustic;) // Caustic layer for composite
492 {
493     extern point        P;
494     vector              Ln;
495     float               Fd;
496     float nondiff       = 0;
497     float lighttype     = 0;
498     color diffuse       = color(0);
499     color lightcolor    = color(1);
500     color shadowcolor   = color(1);
501     color causticcolor  = color(0);
502     illuminance(P)
503     {
504         lightsource("__nondiffuse", nondiff);
505         if (nondiff == 0)
506         {
507             lightsource("__lighttype", lighttype);
508             lightsource("__lightcolor", lightcolor);
509             lightsource("__shadowcolor", shadowcolor);
510             lightsource("__causticcolor", causticcolor);
511             Ln          = normalize(L);
512             if (lighttype == 3)
513                 Fd      = min((Nf.Ln+1)/2, 1);
514             else
515                 Fd      = max(0, smoothstep(cos(diffSize)-sin(diffSmooth)/1.3, cos(diffSize), comp(color(Ln.Nf), 0)));
516             if (translu > 0)
517                 Fd      += max(0, -Nf.Ln)*translu;
518             if (isCubic)
519                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
520             diffuse     += lightcolor*Fd;
521             if (Fd > 0)
522             {
523                 _shadow     += lightcolor*shadowcolor*Fd;
524                 _caustic    += causticcolor*Fd;
525             }
526         }
527     }
528     return diffuse;
529 }
530 
531 
532 //// Returns Minnaert diffusion model
minnaertdiff(normal Nf;vector In;float dark;float isCubic;float translu;output color _shadow;output color _caustic;)533 color minnaertdiff(
534     normal Nf;              // Normalized faceforward surface normal
535     vector In;              // Normalized camera vector
536     float dark;             // Minnaert darkness setting
537     float isCubic;          // Use cubic terminator blend
538     float translu;          // Translucent diffuse factor
539     output color _shadow;   // Shadow layer for composite
540     output color _caustic;) // Caustic layer for composite
541 {
542     extern point        P;
543     vector              Ln;
544     float               Fd;
545     float nondiff       = 0;
546     float lighttype     = 0;
547     float Dd            = 0;
548     color diffuse       = color(0);
549     if (dark > 0)   Dd  = 1;
550     color lightcolor    = color(1);
551     color shadowcolor   = color(1);
552     color causticcolor  = color(0);
553     illuminance(P)
554     {
555         lightsource("__nondiffuse", nondiff);
556         if (nondiff == 0)
557         {
558             lightsource("__lighttype", lighttype);
559             lightsource("__lightcolor", lightcolor);
560             lightsource("__shadowcolor", shadowcolor);
561             lightsource("__causticcolor", causticcolor);
562             Ln          = normalize(L);
563             if (lighttype == 3)
564                 Fd      = min((Nf.Ln+1)/2, 1);
565             else
566                 Fd      = max(0, (Nf.Ln)*pow(max(0, (Nf.Ln)*abs(In.Nf+Dd)), dark));
567             if (translu > 0)
568                 Fd      += max(0, -Nf.Ln)*translu;
569             if (isCubic)
570                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
571             diffuse     += lightcolor*Fd;
572             if (Fd > 0)
573             {
574                 _shadow     += lightcolor*shadowcolor*Fd;
575                 _caustic    += causticcolor*Fd;
576             }
577         }
578     }
579     return diffuse;
580 }
581 
582 
583 //// Returns Lambert diffusion model
lambertdiff(normal Nf;float isCubic;float translu;output color _shadow;output color _caustic;)584 color lambertdiff(
585     normal Nf;              // Normalized faceforward surface normal
586     float isCubic;          // Use cubic terminator blend
587     float translu;          // Translucent diffuse factor
588     output color _shadow;   // Shadow layer for composite
589     output color _caustic;) // Caustic layer for composite
590 {
591     extern point        P;
592     vector              Ln;
593     float               Fd;
594     float nondiff       = 0;
595     float lighttype     = 0;
596     color diffuse       = color(0);
597     color lightcolor    = color(1);
598     color shadowcolor   = color(1);
599     color causticcolor  = color(0);
600     illuminance(P)
601     {
602         lightsource("__nondiffuse", nondiff);
603         if (nondiff == 0)
604         {
605             lightsource("__lighttype", lighttype);
606             lightsource("__lightcolor", lightcolor);
607             lightsource("__shadowcolor", shadowcolor);
608             lightsource("__causticcolor", causticcolor);
609             Ln          = normalize(L);
610             if (lighttype == 3)
611                 Fd      = min((Nf.Ln+1)/2, 1);
612             else
613                 Fd      = max(0, Nf.Ln);
614             if (translu > 0)
615                 Fd      += max(0, -Nf.Ln)*translu;
616             if (isCubic)
617                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
618             diffuse     += lightcolor*Fd;
619             if (Fd > 0)
620             {
621                 _shadow     += lightcolor*shadowcolor*Fd;
622                 _caustic    += causticcolor*Fd;
623             }
624         }
625     }
626     return diffuse;
627 }
628 
629 
630 //// Returns fresnel diffusion model
fresneldiff(normal Nf;float power;float factor;float isCubic;float translu;output color _shadow;output color _caustic;)631 color fresneldiff(
632     normal Nf;              // Normalized faceforward surface normal
633     float power;            // Fresnel power
634     float factor;           // Fresnel factor
635     float isCubic;          // Use cubic terminator blend
636     float translu;          // Translucent diffuse factor
637     output color _shadow;   // Shadow layer for composite
638     output color _caustic;) // Caustic layer for composite
639 {
640     extern point        P;
641     vector              Ln;
642     float               Fd;
643     float nondiff       = 0;
644     float lighttype     = 0;
645     color diffuse       = color(0);
646     color lightcolor    = color(1);
647     color shadowcolor   = color(1);
648     color causticcolor  = color(0);
649     illuminance(P)
650     {
651         lightsource("__nondiffuse", nondiff);
652         if (nondiff == 0)
653         {
654             lightsource("__lighttype", lighttype);
655             lightsource("__lightcolor", lightcolor);
656             lightsource("__shadowcolor", shadowcolor);
657             lightsource("__causticcolor", causticcolor);
658             Ln          = normalize(L);
659             if (lighttype == 3)
660                 Fd      = min((Nf.Ln+1)/2, 1);
661             else
662                 Fd      = pow(clamp(Ln.reflect(Ln, normalize(Nf)), 0, 1), pow(power, factor));
663             if (translu > 0)
664                 Fd      += max(0, -Nf.Ln)*translu;
665             if (isCubic)
666                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
667             diffuse     += lightcolor*Fd;
668             if (Fd > 0)
669             {
670                 _shadow     += lightcolor*shadowcolor*Fd;
671                 _caustic    += causticcolor*Fd;
672             }
673         }
674     }
675     return diffuse;
676 }
677 
678 
679 //// Returns anisotropic diffusion model
anisodiff(normal Nf;float isCubic;float translu;output color _shadow;output color _caustic;)680 color anisodiff(
681     normal Nf;              // Normalized faceforward surface normal
682     float isCubic;          // Use cubic terminator blend
683     float translu;          // Translucent diffuse factor
684     output color _shadow;   // Shadow layer for composite
685     output color _caustic;) // Caustic layer for composite
686 {
687     extern point        P;
688     extern float        t;
689     vector              Ln;
690     float               Fd;
691     float nondiff       = 0;
692     float lighttype     = 0;
693     vector tangent      = normalize(Deriv(P, t));
694     color diffuse       = color(0);
695     color lightcolor    = color(1);
696     color shadowcolor   = color(1);
697     color causticcolor  = color(0);
698     illuminance(P)
699     {
700         lightsource("__nondiffuse", nondiff);
701         if (nondiff == 0)
702         {
703             lightsource("__lighttype", lighttype);
704             lightsource("__lightcolor", lightcolor);
705             lightsource("__shadowcolor", shadowcolor);
706             lightsource("__causticcolor", causticcolor);
707             Ln          = normalize(L);
708             if (lighttype == 3)
709                 Fd      = min((Nf.Ln+1)/2, 1);
710             else
711                 Fd      = sqrt(1-pow(Ln.tangent, 2));
712             if (translu > 0)
713                 Fd      += max(0, -Nf.Ln)*translu;
714             if (isCubic)
715                 Fd      = pow(max(Fd, 0), CUBICDIFFUSE);
716             diffuse     += lightcolor*Fd;
717             if (Fd > 0)
718             {
719                 _shadow     += lightcolor*shadowcolor*Fd;
720                 _caustic    += causticcolor*Fd;
721             }
722         }
723     }
724     return diffuse;
725 }
726 
727 
728 //// Returns only shadow data from lights for shadow mattes
onlyshadow(normal Nf;)729 color onlyshadow(
730     normal Nf;)             // Normalized surface normal
731 {
732     extern point        P;
733     float samples       = 0;
734     float Fd            = 0;
735     vector Ln           = 0;
736     color matte         = color(0);
737     color lightcolor    = color(1);
738     color shadowcolor   = color(1);
739     illuminance(P)
740     {
741         lightsource("__lightcolor", lightcolor);
742         lightsource("__shadowcolor", shadowcolor);
743         Ln              = normalize(L);
744         Fd              = Nf.Ln;
745         if (Fd > 0)
746             matte       += comp(ctransform("hsv", min(lightcolor*shadowcolor, color(1))), 2);
747         else
748             matte       += color(1);
749         samples         += 1;
750     }
751     return min(matte/(samples == 0 ? 1 : samples), color(1));
752 }
753 
754 
755 
756 //Simulate SSS using blurred shadows or diffuse brickmap, returns number of lights used for SSS or 1 for brickmap use
sssdiff(string BrickMap;float Diffuse;float FrFact;float BkFact;float SSSBias;float Samples;float Scale;color SSSCol;color SSSRad;output color _diffuse;output color _shadow;output color _caustic;)757 float sssdiff(
758     string BrickMap;        // Name of brickmap containing diffusion to use for SSS (instead of using light depth maps)
759     float Diffuse;          // Colorless diffusion with shadows to blend on top of SSS at low obsorbtion
760     float FrFact;           // Front factor of SSS light obsorbtion
761     float BkFact;           // Back factor of SSS light obsorbtion
762     float SSSBias;          // Bias to use for SSS depth maps
763     float Samples;          // Number of samples used for shadow lookup
764     float Scale;            // Obsorbtion scale (technically a blurring scale)
765     color SSSCol;           // Surface color off SSS (this color used on front and inverse used on back)
766     color SSSRad;           // SSS Radius simulating scattering path of light for each color channel
767     output color _diffuse;  // Diffuse layer for composite
768     output color _shadow;   // Shadow layer for composite
769     output color _caustic;) // Caustic layer for composite
770 {
771     extern point        P;
772     extern vector       I;
773     string              shadowname = "", depthname = "", depthmap = "";
774     float               LgBlur, frdiff, indiff, nondiff = 0, shadowblur = 0, lightCount = 0;
775     color               InDepth, FrDepth, BkDepth, SSS = color(0), lightcolor = color(1);
776     color InCol         = (1.004-SSSCol)*SSSRad;
777     float DiffBlend     = 0.65; // Factor of diffuse blending at low SSS scales
778     if (comp(ctransform("hsv", SSSRad), 2) > 1)
779         InCol           = color(normalize(vector(InCol)));
780     color FrCol         = color(1)-InCol;
781     float InBlur        = clamp(comp(ctransform("hsv", InCol), 2)*0.3*Scale, 0.001, 1);
782     float FrBlur        = clamp((1-comp(ctransform("hsv", FrCol), 2))*0.2*Scale, 0.001, 1);
783     float InDiff        = InBlur*DiffBlend*20;
784     float FrDiff        = FrBlur*DiffBlend*20;
785 
786     if (BrickMap != "")     // If brickmap is specified use it for SSS calculations...
787     {
788         point pP        = P;
789         // If not global brick map then transform to object space
790         if (match("GLOBAL", BrickMap) != 1.0)
791             pP          = transform("object", pP);
792         BkDepth         = color(0);
793         #ifndef AQSIS
794         #ifdef AIR
795             texture3d(BrickMap, pP, normal(0), "blur", InBlur, "_diffusion", InDepth);
796             texture3d(BrickMap, pP, normal(0), "blur", FrBlur, "_diffusion", FrDepth);
797         #endif
798         #ifdef PIXIE
799             texture3d(BrickMap, pP, normal(0), "radius", InBlur, "_diffusion", InDepth);
800             texture3d(BrickMap, pP, normal(0), "radius", FrBlur, "_diffusion", FrDepth);
801         #endif
802         #ifndef AIR
803         #ifndef PIXIE
804             texture3d(BrickMap, pP, normal(0), "filterradius", InBlur, "_diffusion", InDepth);
805             texture3d(BrickMap, pP, normal(0), "filterradius", FrBlur, "_diffusion", FrDepth);
806         #endif
807         #endif
808         #endif
809         if (BkFact != 1) illuminance(P) {BkDepth += max(pow(normalize(I).normalize(L), 16)*InDepth, color(0))*(BkFact-1);}
810         SSS             = min(color(1), (InCol*InDepth + FrCol*FrDepth)*FrFact+BkDepth);
811         lightCount      = 1;
812     }
813     else                    // Otherwise use light depth maps for calculations...
814     {
815         illuminance(P)
816         {
817             lightsource("__nondiffuse", nondiff);
818             if (nondiff == 0)
819             {
820                 lightsource("__shadowname", shadowname);
821                 lightsource("__depthname", depthname);
822                 if (depthname != "")
823                     depthmap    = depthname;
824                 else
825                     depthmap    = shadowname;
826                 if (depthmap != "" && depthmap != "raytrace")
827                 {
828                     lightCount  += 1;
829                     lightsource("__lightcolor", lightcolor);
830                     lightsource("__shadowblur", shadowblur);
831                     indiff      = clamp((clamp(Diffuse, 0, 1)*(1-InDiff))+InDiff, 0, 1);
832                     frdiff      = clamp((clamp(Diffuse, 0, 1)*(1-FrDiff))+FrDiff, 0, 1);
833                     LgBlur      = InBlur*comp(ctransform("hsv", lightcolor), 2)+shadowblur;
834                     FrBlur      += shadowblur;
835                     InDepth     = comp(ctransform("hsv", 1-shadow(depthmap, P, "samples", Samples, "bias", SSSBias, "blur", LgBlur)), 2);
836                     FrDepth     = comp(ctransform("hsv", 1-shadow(depthmap, P, "samples", Samples, "bias", SSSBias, "blur", FrBlur)), 2);
837                     BkDepth     = InDepth*max(normalize(I).normalize(L)*0.2, 0)*(BkFact-1);
838                     SSS         += min(color(1), lightcolor*(InCol*InDepth*indiff + FrCol*FrDepth*frdiff)*FrFact+BkDepth + _caustic);
839                 }
840             }
841         }
842         if (lightCount > 0)
843         {
844             _caustic    = color(0);
845             _shadow     = SSS;
846         }
847     }
848     if (lightCount > 0)
849         _diffuse        = SSS;
850     return lightCount;
851 }
852 
853 
854 //// Returns Cooktorr specular model
cooktorrspec(normal Nf;vector In;float hard;)855 color cooktorrspec(
856     normal Nf;              // Normalized faceforward surface normal
857     vector In;              // Normalized camera vector
858     float hard;)            // Specular hard factor
859 {
860     extern point        P;
861     vector              Ln;
862     color               Fs;
863     float nonspec       = 0;
864     color spec          = color(0);
865     color lightcolor    = color(1);
866     color shadowcolor   = color(1);
867     illuminance(P, Nf, PI/2)
868     {
869         lightsource("__nonspecular", nonspec);
870         if (nonspec == 0)
871         {
872             lightsource("__lightcolor", lightcolor);
873             lightsource("__shadowcolor", shadowcolor);
874             Ln          = normalize(L);
875             Fs          = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
876             if (Fs != color(0))
877                 spec    += lightcolor*shadowcolor*Fs;
878         }
879     }
880     return spec;
881 }
882 
883 
884 //// Returns Phong specular model
phongspec(normal Nf;vector In;float size;float hard;)885 color phongspec(
886     normal Nf;              // Normalized faceforward surface normal
887     vector In;              // Normalized camera vector
888     float size;             // Specular size
889     float hard;)            // Specular hard factor
890 {
891     extern point        P;
892     vector              Ln;
893     color               Fs;
894     float nonspec       = 0;
895     float lighttype     = 0;
896     vector R            = reflect(-In, Nf);
897     color spec          = color(0);
898     color lightcolor    = color(1);
899     color shadowcolor   = color(1);
900     illuminance(P, Nf, PI/2)
901     {
902         lightsource("__nonspecular", nonspec);
903         if (nonspec == 0)
904         {
905             lightsource("__lighttype", lighttype);
906             lightsource("__lightcolor", lightcolor);
907             lightsource("__shadowcolor", shadowcolor);
908             Ln          = normalize(L);
909             if (lighttype == 3)
910                 Fs      = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
911             else
912                 Fs      = pow(max(0.0, R.Ln), size);
913             if (Fs != color(0))
914                 spec    += lightcolor*shadowcolor*Fs;
915         }
916     }
917     return spec;
918 }
919 
920 
921 //// Returns Blinn specular model
blinnspec(normal Nf;vector In;float hard;float refr;)922 color blinnspec(
923     normal Nf;              // Normalized faceforward surface normal
924     vector In;              // Normalized camera vector
925     float hard;             // Specular hard factor
926     float refr;)            // Index of refraction
927 {
928     extern point        P;
929     vector              Ln, R, T;
930     color               Fs;
931     float               Kr, Kt;
932     float nonspec       = 0;
933     float lighttype     = 0;
934     float ior           = (refr-1)/9;
935     color spec          = color(0);
936     color lightcolor    = color(1);
937     color shadowcolor   = color(1);
938     fresnel(-In, Nf, 0.1, Kr, Kt, R, T);
939     illuminance(P, Nf, PI/2)
940     {
941         lightsource("__nonspecular", nonspec);
942         if (nonspec == 0)
943         {
944             lightsource("__lighttype", lighttype);
945             lightsource("__lightcolor", lightcolor);
946             lightsource("__shadowcolor", shadowcolor);
947             Ln          = normalize(L);
948             if (lighttype == 3)
949                 Fs      = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
950             else
951                 Fs      = max((specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard)-Kt)*2, color(0))*ior;
952             if (Fs != color(0))
953                 spec    += lightcolor*shadowcolor*Fs;
954         }
955     }
956     return spec;
957 }
958 
959 
960 //// Returns simple toon cell shading for specularity
toonspec(normal Nf;vector In;float specSize;float specSmooth;float hard;)961 color toonspec(
962     normal Nf;              // Normalized faceforward surface normal
963     vector In;              // Normalized camera vector
964     float specSize;         // Size of specular solid color
965     float specSmooth;       // Smoothing or solid color's edges
966     float hard;)            // Specular hard factor
967 {
968     extern point        P;
969     vector              Ln;
970     color               brdf;
971     color               Fs;
972     float nonspec       = 0;
973     float lighttype     = 0;
974     color spec          = color(0);
975     color lightcolor    = color(1);
976     color shadowcolor   = color(1);
977     illuminance(P, Nf, PI/2)
978     {
979         lightsource("__nonspecular", nonspec);
980         if (nonspec == 0)
981         {
982             lightsource("__lighttype", lighttype);
983             lightsource("__lightcolor", lightcolor);
984             lightsource("__shadowcolor", shadowcolor);
985             Ln          = normalize(L);
986             if (lighttype == 3)
987             {
988                 Fs      = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
989             }
990             else
991             {
992                 brdf    = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), 20);
993                 Fs      = smoothstep(cos(specSize)-sin(specSmooth)/1.3, cos(specSize), comp(brdf, 0));
994             }
995             if (Fs != color(0))
996                 spec    += lightcolor*shadowcolor*Fs;
997         }
998     }
999     return spec;
1000 }
1001 
1002 
1003 //// Returns Wardlso specular model (poorly hacked variant from Cook model)
wardspec(normal Nf;vector In;float rms;float hard;)1004 color wardspec(
1005     normal Nf;              // Normalized faceforward surface normal
1006     vector In;              // Normalized camera vector
1007     float rms;              // Simulation or Wardlso deviation of surface slope
1008     float hard;)            // Specular hard factor
1009 {
1010     extern point        P;
1011     vector              Ln;
1012     color               Fs;
1013     float nonspec       = 0;
1014     float lighttype     = 0;
1015     color spec          = color(0);
1016     color lightcolor    = color(1);
1017     color shadowcolor   = color(1);
1018     illuminance(P, Nf, PI/2)
1019     {
1020         lightsource("__nonspecular", nonspec);
1021         if (nonspec == 0)
1022         {
1023             lightsource("__lighttype", lighttype);
1024             lightsource("__lightcolor", lightcolor);
1025             lightsource("__shadowcolor", shadowcolor);
1026             Ln          = normalize(L);
1027             if (lighttype == 3)
1028                 Fs      = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
1029             else
1030                 Fs      = min(comp(specularbrdf(normalize(Ln), normalize(Nf), normalize(In), rms)*(0.8-rms), 0)*(9-(20*rms)), 1);
1031             if (Fs != color(0))
1032                 spec    += lightcolor*shadowcolor*Fs;
1033         }
1034     }
1035     return spec;
1036 }
1037 
1038 
1039 //// Returns anisotropic specular model
anisospec(normal Nf;vector In;float hard;)1040 color anisospec(
1041     normal Nf;              // Normalized faceforward surface normal
1042     vector In;              // Normalized camera vector
1043     float hard;)            // Specular hard factor
1044 {
1045     extern point        P;
1046     extern float        t;
1047     vector              Ln;
1048     color               Fs;
1049     float nonspec       = 0;
1050     float lighttype     = 0;
1051     vector tangent      = normalize(Deriv(P, t));
1052     color spec          = color(0);
1053     color lightcolor    = color(1);
1054     color shadowcolor   = color(1);
1055     illuminance(P, Nf, PI/2)
1056     {
1057         lightsource("__nonspecular", nonspec);
1058         if (nonspec == 0)
1059         {
1060             lightsource("__lighttype", lighttype);
1061             lightsource("__lightcolor", lightcolor);
1062             lightsource("__shadowcolor", shadowcolor);
1063             Ln          = normalize(L);
1064             if (lighttype == 3)
1065                 Fs      = specularbrdf(normalize(Ln), normalize(Nf), normalize(In), hard);
1066             else
1067                 Fs      = pow(max(0, sqrt(1-pow(Ln.tangent, 2))*sqrt(1-pow(In.tangent, 2))-(Ln.tangent)*(In.tangent)), 1/hard);
1068             if (Fs != color(0))
1069                 spec    += lightcolor*shadowcolor*Fs;
1070         }
1071     }
1072     return spec;
1073 }
1074 
1075 
1076 //// Returns reflection and refraction model for both environment maps or raytracing if "raytrace" is used for map name
mirrortransp(string Environment;vector In;vector Nf;uniform float dirMode;uniform float Samples;uniform float maxDist;uniform float Gloss;float IOR;float maxDepth;float dispFactor;float fadeMode;color mirCol;color fogCol;)1077 color mirrortransp(
1078     string Environment;
1079     vector In;              // Normalized camera vector
1080     vector Nf;              // Normalized faceforward surface normal
1081     uniform float dirMode;  // Direction mode: 0 == reflect, 1 == refract
1082     uniform float Samples;  // Number of samples for environment lookup
1083     uniform float maxDist;  // Maximum distance for ray visibility, also serves as env map lookup correction radius
1084     uniform float Gloss;    // Level of environment blur
1085     float IOR;              // Index of refraction
1086     float maxDepth;         // Maximum number of ray bounces
1087     float dispFactor;       // Factor displacement effect env map lookups
1088     float fadeMode;         // Non ray hit or env map alpha color mode: 0 = black, 1 = horizon color, 2 = diffuse color
1089     color mirCol;           // Color modulated on reflection
1090     color fogCol;)          // Color for sky (non ray hit) used for fadeMode 1
1091 {
1092     extern point        P;
1093     extern normal       N;
1094     vector              R;
1095     color Col           = mirCol;
1096     color fadeCol       = fogCol*mirCol;
1097     string mapName      = Environment;
1098     if (dirMode == 0)
1099         R               = reflect(In, Nf);
1100     else
1101         R               = refract(In, Nf, (In.Nf < 0 ? 1/IOR : IOR));
1102     if (Environment != "raytrace")
1103     {
1104         if (match("planar", mapName))
1105         {
1106             //Transform N to same space as reflection map (shader->camera->-object) to correct for displacements, then transform to NDC for texture lookup
1107             point Pndc  = transform("NDC", P+vtransform("object", vtransform("camera", vector(Nf)))*dispFactor);
1108             float tx    = xcomp(Pndc);
1109             float ty    = ycomp(Pndc);
1110             Col         *= texture(mapName, tx, ty, "samples", Samples, "blur", Gloss);
1111             if (fadeMode != 1)
1112             {
1113                 float alpha = texture(mapName[3], tx, ty, "samples", Samples, "blur", Gloss);
1114                 Col         = Col*alpha + fadeCol*(1-alpha);
1115             }
1116         }
1117         else
1118         {
1119             //Adjust N to compensate for point position P during map lookup by mapRadius for more accurate reflection and refraction mapping
1120             R           = (vtransform("world", R*dispFactor)+(transform("world", P)-transform("object", "world", (0, 0, 0)))/maxDist)*vector(1, 1, -1);
1121             Col         *= environment(mapName, R, "samples", Samples, "blur", Gloss);
1122             if (fadeMode != 1)
1123             {
1124                 float alpha = environment(mapName[3], R, "samples", Samples, "blur", Gloss);
1125                 Col         = Col*alpha + fadeCol*(1-alpha);
1126             }
1127         }
1128     }
1129     else
1130     {
1131         float rayLen    = 0;
1132         float rayDepth  = 0;
1133         float avgLen    = 0;
1134         color rayCol    = color(0);
1135         color avgCol    = color(0);
1136         #ifdef AIR
1137             string catagory = "environment";
1138         #else
1139             string catagory = "illuminance";
1140         #endif
1141         gather(catagory, P, R, PI*0.5*Gloss, Samples, "maxdist", maxDist, "surface:Ci", rayCol, "ray:length", rayLen)
1142         {
1143             rayinfo("depth", rayDepth);
1144             if (rayDepth >= maxDepth)
1145             {
1146                 avgLen  += maxDist;
1147                 avgCol  += fadeCol;
1148             }
1149             else
1150             {
1151                 avgLen  += rayLen;
1152                 avgCol  += rayCol;
1153             }
1154         }
1155         else
1156         {
1157             avgLen      += maxDist;
1158             avgCol      += fadeCol;
1159         }
1160         avgLen          = min(avgLen/Samples/maxDist, 1);
1161         Col             *= (avgCol/Samples)*(1-avgLen)+fadeCol*avgLen;
1162     }
1163 
1164     return Col;
1165 }
1166 
1167 
1168 //// Returns occlusion model for both occlusion maps or raytracing if "raytrace" is used for map name
hdrocclusion(string occMap;string occPoint;string hdrMap;vector Nf;vector bendN;uniform float occSamples;uniform float maxDist;uniform float maxSolidAngle;float mapBlur;float mapBias;float occFalloff;float hdrBlur;float hdrSamples;float hdrFactor;color occCol;)1169 color hdrocclusion(
1170     string occMap;              // Occlusion depth map or set as "raytrace"
1171     string occPoint;            // Occlusion point cloud
1172     string hdrMap;              // HDR map to use for non ray hit color lookup
1173     vector Nf;                  // Normalized faceforward surface normal
1174     vector bendN;               // Bend surface normals in this direction
1175     uniform float occSamples;   // Number of samples to use for occlusion
1176     uniform float maxDist;      // Maximum distance for occlusion
1177     uniform float maxSolidAngle;// Quality versus speed for point data
1178     float mapBlur;              // Blur for occlusion map lookup
1179     float mapBias;              // Occlusion map bias
1180     float occFalloff;           // Falloff factor
1181     float hdrBlur;              // Blur for HDR map lookup
1182     float hdrSamples;           // Samples for HDR map lookup
1183     float hdrFactor;            // Factor of HDR color blended into occlusion
1184     color occCol;)              // Color modulated into occlusion
1185 {
1186     extern point        P;
1187     float Hits          = 0;
1188     normal Nocc         = 0;
1189     color Occ           = color(1);;
1190     if (occMap != "raytrace")
1191     {
1192         if (occPoint != "")
1193         {
1194             #ifndef AIR
1195             #ifndef AQSIS
1196                 Hits    = comp(ctransform("hsv", color(1)-occlusion(P, Nf+bendN, 0, "pointbased", 1, "filename", occPoint, "maxdist", maxDist, "maxsolidangle", maxSolidAngle)), 2);
1197             #endif
1198             #endif
1199         }
1200         else
1201         {
1202             #ifdef AIR
1203                 Hits    = comp(ctransform("hsv", color(1)-occlusion(occMap, P, Nf+bendN, PI/2, Nocc, "samples", occSamples, "bias", mapBias, "blur", mapBlur)), 2);
1204             #endif
1205             #ifdef AQSIS
1206                 Hits    = comp(ctransform("hsv", color(1)-occlusion(occMap, P, Nf+bendN, PI/2, "samples", occSamples, "bias", mapBias, "blur", mapBlur)), 2);
1207             #endif
1208         }
1209     }
1210     else
1211     {
1212         #ifdef AIR
1213             Hits        = comp(ctransform("hsv", color(1)-occlusion(P, Nf+bendN, PI/2, Nocc, "samples", occSamples, "maxdist", maxDist)), 2);
1214         #else
1215         #ifndef AQSIS
1216             Hits        = comp(ctransform("hsv", color(1)-occlusion(P, Nf+bendN, occSamples, "maxdist", maxDist)), 2);
1217         #endif
1218         #endif
1219     }
1220     if (occFalloff > 0)
1221         Hits            = min(Hits*(occFalloff+1), 1);
1222     if (hdrMap != "")
1223     {
1224         color hdr       = environment(hdrMap, vtransform("world", Nf)*vector(1,1,-1), "samples", hdrSamples, "blur", hdrBlur);
1225         Occ             = occCol*mix(color(1), hdr, hdrFactor)*Hits;
1226     }
1227     else
1228     {
1229         Occ             = occCol*Hits;
1230     }
1231     return Occ;
1232 }
1233 
1234 
1235 //// Returns indirect diffusion model for both env maps or raytracing if "raytrace" is used for map name
hdrindirectdiff(string diffMap;string diffPoint;string hdrMap;vector Nf;uniform float diffSamples;uniform float maxDist;uniform float maxSolidAngle;float mapBlur;float dispFactor;float objScale;float hdrBlur;float hdrSamples;float hdrFactor;color diffCol;)1236 color hdrindirectdiff(
1237     string diffMap;             // Diffusion env map or "raytrace"
1238     string diffPoint;           // Indirect diffusion point cloud
1239     string hdrMap;              // HDR map to use for non ray hit color lookup
1240     vector Nf;                  // Normalized faceforward surface normal
1241     uniform float diffSamples;  // Number of samples to use for indirect diffusion
1242     uniform float maxDist;      // Maximum distance for indirect diffusion
1243     uniform float maxSolidAngle;// Quality versus speed for point data
1244     float mapBlur;              // Blur for occlusion map lookup
1245     float dispFactor;           // Factor displacement effect env map lookups
1246     float  objScale;            // Scale of object to map planar diffusion map to
1247     float  hdrBlur;             // Blur for HDR map lookup
1248     float  hdrSamples;          // Samples for HDR map lookup
1249     float  hdrFactor;           // Factor of HDR color blended into indirect diffusion
1250     color diffCol;)             // Color modulated into indirect diffusion
1251 {
1252     extern point            P;
1253     color Hits              = 0;
1254     color Diff              = color(0);
1255     string mapName          = diffMap;
1256     if (diffMap != "raytrace")
1257     {
1258         if (diffPoint != "")
1259         {
1260             #ifndef AIR
1261             #ifndef AQSIS
1262                 Hits        = indirectdiffuse(P, Nf, 0, "pointbased", 1, "filename", diffPoint, "maxdist", maxDist, "maxsolidangle", maxSolidAngle);
1263             #endif
1264             #endif
1265         }
1266         else
1267         {
1268             if (match("planar", mapName))
1269             {
1270                 //Transform P plus displacements to object space and adjust coordinates to texture ortho scale to map planar map directly to surface
1271                 point Pobj  = transform("object", P+Nf*dispFactor);
1272                 float       tx = 0.5-xcomp(-Pobj)/objScale;
1273                 float       ty = 0.5-ycomp(Pobj)/objScale;
1274                 Hits        = texture(mapName, tx, ty, "samples", diffSamples, "blur", mapBlur);
1275             }
1276             else
1277             {
1278                 float envBlur   = mapBlur/4;
1279                 //Adjust N to componsate for point position P during map lookup to directly map env to surface
1280                 vector D    = (vtransform("world", Nf*dispFactor)+(transform("world", P)-transform("object", "world", (0, 0, 0))))*vector(1, 1, -1);
1281                 Hits        = environment(mapName, D, "samples", diffSamples, "blur", envBlur);
1282             }
1283         }
1284     }
1285     #ifndef AQSIS
1286         else
1287         {
1288             Hits            = indirectdiffuse(P, Nf, diffSamples, "maxdist", maxDist);
1289         }
1290     #endif
1291 
1292     if (hdrMap != "")
1293     {
1294         color hdr           = environment(hdrMap, vtransform("world", Nf)*vector(1,1,-1), "samples", hdrSamples, "blur", hdrBlur);
1295         Diff                = diffCol*mix(color(1), hdr, hdrFactor)*Hits;
1296     }
1297     else
1298     {
1299         Diff                = diffCol*Hits;
1300     }
1301     return Diff;
1302 }
1303 
1304 #endif
1305 
1306 
1307 //////// Displacement Shader Utility Functions...
1308 
1309 #ifdef DISPLACE_UTILITIES
1310     // None
1311 #endif
1312 
1313 
1314 //////// Light Shader Utility Functions...
1315 
1316 #ifdef LIGHT_UTILITIES
1317 
1318 //// Returns avarage distance from specified point to nearest light blocker referenced in depth map
blockerdepth(string depthmap;uniform float Samples;uniform float Radius;uniform float Power;uniform float MinAvg;uniform float MaxAvg;)1319 float blockerdepth(
1320     string depthmap;        // Depth map to check blocker depth from
1321     uniform float Samples;  // Number of samples to average depth by
1322     uniform float Radius;   // Sample radius to average depth by
1323     uniform float Power;    // Power final depth value
1324     uniform float MinAvg;   // Minimum average depth returned
1325     uniform float MaxAvg;)  // Maximum average depth returned
1326 {
1327     extern point            Ps;
1328     float depth             = 0;
1329     if (depthmap != "" && depthmap != "raytrace")
1330     {
1331         uniform matrix      shadProjSpace;
1332         uniform matrix      shadCamSpace;
1333         textureinfo(depthmap, "projectionmatrix", shadProjSpace);
1334         textureinfo(depthmap, "viewingmatrix", shadCamSpace);
1335         point shadProjP     = transform(shadProjSpace, Ps);
1336         point shadCamP      = transform(shadCamSpace, Ps);
1337         float PsDepth       = zcomp(shadCamP);
1338         float sloc          = (1+xcomp(shadProjP))*0.5;
1339         float tloc          = (1-ycomp(shadProjP))*0.5;
1340         float weight        = 0;
1341         float step          = 0;
1342         for (step = 0; step < Radius; step += Radius/Samples)
1343         {
1344             float angle     = random()*360.0;
1345             float sstep     = sloc+sin(angle)*step;
1346             float tstep     = tloc+cos(angle)*step;
1347             float Blocker   = float texture(depthmap, sstep, tstep, "samples", 1, "width", 0);
1348             if (Blocker < 3.402823466e+38 && Blocker < PsDepth)
1349             {
1350                 float w     = 1-0.9*(step/Radius);
1351                 weight      += w;
1352                 depth       += (PsDepth-Blocker)*w;
1353             }
1354         }
1355         if (weight > 0)
1356         {
1357             depth           = clamp(depth/weight, MinAvg, MaxAvg);
1358             if (Power > 1)
1359                 depth       = pow(depth, Power);
1360         }
1361     }
1362     return depth;
1363 }
1364 
1365 #endif
1366 
1367 
1368 //////// Volume Shader Utility Functions...
1369 
1370 #ifdef VOLUME_UTILITIES
1371 
1372 //// Uses a light passes environment and depth map to project blurred and attenuated surface color into surrounding volume
volumehaze(string colormap;string depthmap;point Pv;uniform float samples;uniform float radius;uniform float dist;)1373 color volumehaze(
1374     string colormap;        // The name of an image containing a color render from the lights perpective
1375     string depthmap;        // The name of an image containing a depth render from the lights perpective
1376     point Pv;               // Point shaded in volume in world coordinates
1377     uniform float samples;  // Number of random samples in volume
1378     uniform float radius;   // Size of radius around shading point to sample
1379     uniform float dist;)    // Distance of attenuation from surface torwards light
1380 {
1381     color haze              = color(0);
1382     if (dist > 0 && colormap != "" && depthmap != "")
1383     {
1384         uniform matrix      shadProjSpace;
1385         uniform matrix      shadCamSpace;
1386         textureinfo(depthmap, "projectionmatrix", shadProjSpace);
1387         textureinfo(depthmap, "viewingmatrix", shadCamSpace);
1388         point shadProjP     = transform(shadProjSpace, Pv);
1389         point shadCamP      = transform(shadCamSpace, Pv);
1390         float PvDepth       = zcomp(shadCamP);
1391         float sloc          = (1+xcomp(shadProjP))*0.5;
1392         float tloc          = (1-ycomp(shadProjP))*0.5;
1393         float step          = 0;
1394         for (step = 0; step < samples; step += 1)
1395         {
1396             float sstep     = sloc+(1-random()*2)*radius;
1397             float tstep     = tloc+(1-random()*2)*radius;
1398             float Blocker   = float texture(depthmap, sstep, tstep, "samples", 1, "width", 0);
1399             if (Blocker < 3.402823466e+38 && Blocker > PvDepth)
1400             {
1401                 float atten = 1-min((Blocker-PvDepth)/dist, 1);
1402                 if (atten > 0)
1403                     haze    += color texture(colormap, sstep, tstep, "samples", 1, "width", 0)*atten;
1404             }
1405         }
1406         if (samples > 1)
1407             haze            /= samples;
1408     }
1409     return haze;
1410 }
1411 
1412 #endif
1413 
1414 
1415 //////// Image Shader Utility Functions...
1416 
1417 #ifdef IMAGE_UTILITIES
1418     // None
1419 #endif
1420 
1421