Cycles: Fix NULL instead of false
[blender.git] / intern / cycles / kernel / osl / osl_services.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* TODO(sergey): There is a bit of headers dependency hell going on
18  * here, so for now we just put here. In the future it might be better
19  * to have dedicated file for such tweaks.
20  */
21 #if (defined(__GNUC__) && !defined(__clang__)) && defined(NDEBUG)
22 #  pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
23 #  pragma GCC diagnostic ignored "-Wuninitialized"
24 #endif
25
26 #include <string.h>
27
28 #include "render/colorspace.h"
29 #include "render/mesh.h"
30 #include "render/object.h"
31 #include "render/scene.h"
32
33 #include "kernel/osl/osl_closures.h"
34 #include "kernel/osl/osl_globals.h"
35 #include "kernel/osl/osl_services.h"
36 #include "kernel/osl/osl_shader.h"
37
38 #include "util/util_foreach.h"
39 #include "util/util_logging.h"
40 #include "util/util_string.h"
41
42 #include "kernel/kernel_compat_cpu.h"
43 #include "kernel/split/kernel_split_data_types.h"
44 #include "kernel/kernel_globals.h"
45 #include "kernel/kernel_color.h"
46 #include "kernel/kernel_random.h"
47 #include "kernel/kernel_projection.h"
48 #include "kernel/kernel_differential.h"
49 #include "kernel/kernel_montecarlo.h"
50 #include "kernel/kernel_camera.h"
51 #include "kernel/kernels/cpu/kernel_cpu_image.h"
52 #include "kernel/geom/geom.h"
53 #include "kernel/bvh/bvh.h"
54
55 #include "kernel/kernel_projection.h"
56 #include "kernel/kernel_accumulate.h"
57 #include "kernel/kernel_shader.h"
58
59 #ifdef WITH_PTEX
60 #  include <Ptexture.h>
61 #endif
62
63 CCL_NAMESPACE_BEGIN
64
65 /* RenderServices implementation */
66
67 static void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
68 {
69   ProjectionTransform t = projection_transpose(ProjectionTransform(tfm));
70   memcpy((void *)&m, &t, sizeof(m));
71 }
72
73 static void copy_matrix(OSL::Matrix44 &m, const ProjectionTransform &tfm)
74 {
75   ProjectionTransform t = projection_transpose(tfm);
76   memcpy((void *)&m, &t, sizeof(m));
77 }
78
79 /* static ustrings */
80 ustring OSLRenderServices::u_distance("distance");
81 ustring OSLRenderServices::u_index("index");
82 ustring OSLRenderServices::u_world("world");
83 ustring OSLRenderServices::u_camera("camera");
84 ustring OSLRenderServices::u_screen("screen");
85 ustring OSLRenderServices::u_raster("raster");
86 ustring OSLRenderServices::u_ndc("NDC");
87 ustring OSLRenderServices::u_object_location("object:location");
88 ustring OSLRenderServices::u_object_index("object:index");
89 ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
90 ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
91 ustring OSLRenderServices::u_material_index("material:index");
92 ustring OSLRenderServices::u_object_random("object:random");
93 ustring OSLRenderServices::u_particle_index("particle:index");
94 ustring OSLRenderServices::u_particle_random("particle:random");
95 ustring OSLRenderServices::u_particle_age("particle:age");
96 ustring OSLRenderServices::u_particle_lifetime("particle:lifetime");
97 ustring OSLRenderServices::u_particle_location("particle:location");
98 ustring OSLRenderServices::u_particle_rotation("particle:rotation");
99 ustring OSLRenderServices::u_particle_size("particle:size");
100 ustring OSLRenderServices::u_particle_velocity("particle:velocity");
101 ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity");
102 ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
103 ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
104 ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
105 ustring OSLRenderServices::u_geom_name("geom:name");
106 ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced");
107 ustring OSLRenderServices::u_is_smooth("geom:is_smooth");
108 ustring OSLRenderServices::u_is_curve("geom:is_curve");
109 ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
110 ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
111 ustring OSLRenderServices::u_curve_random("geom:curve_random");
112 ustring OSLRenderServices::u_path_ray_length("path:ray_length");
113 ustring OSLRenderServices::u_path_ray_depth("path:ray_depth");
114 ustring OSLRenderServices::u_path_diffuse_depth("path:diffuse_depth");
115 ustring OSLRenderServices::u_path_glossy_depth("path:glossy_depth");
116 ustring OSLRenderServices::u_path_transparent_depth("path:transparent_depth");
117 ustring OSLRenderServices::u_path_transmission_depth("path:transmission_depth");
118 ustring OSLRenderServices::u_trace("trace");
119 ustring OSLRenderServices::u_hit("hit");
120 ustring OSLRenderServices::u_hitdist("hitdist");
121 ustring OSLRenderServices::u_N("N");
122 ustring OSLRenderServices::u_Ng("Ng");
123 ustring OSLRenderServices::u_P("P");
124 ustring OSLRenderServices::u_I("I");
125 ustring OSLRenderServices::u_u("u");
126 ustring OSLRenderServices::u_v("v");
127 ustring OSLRenderServices::u_empty;
128
129 OSLRenderServices::OSLRenderServices()
130 {
131   kernel_globals = NULL;
132   osl_globals = NULL;
133   osl_ts = NULL;
134
135 #ifdef WITH_PTEX
136   size_t maxmem = 16384 * 1024;
137   ptex_cache = PtexCache::create(0, maxmem);
138 #endif
139 }
140
141 OSLRenderServices::~OSLRenderServices()
142 {
143   if (osl_ts) {
144     VLOG(2) << "OSL texture system stats:\n" << osl_ts->getstats();
145   }
146 #ifdef WITH_PTEX
147   ptex_cache->release();
148 #endif
149 }
150
151 void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_,
152                                     OSLGlobals *osl_globals_,
153                                     OSL::TextureSystem *osl_ts_)
154 {
155   kernel_globals = kernel_globals_;
156   osl_globals = osl_globals_;
157   osl_ts = osl_ts_;
158 }
159
160 bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
161                                    OSL::Matrix44 &result,
162                                    OSL::TransformationPtr xform,
163                                    float time)
164 {
165   /* this is only used for shader and object space, we don't really have
166    * a concept of shader space, so we just use object space for both. */
167   if (xform) {
168     const ShaderData *sd = (const ShaderData *)xform;
169     int object = sd->object;
170
171     if (object != OBJECT_NONE) {
172 #ifdef __OBJECT_MOTION__
173       Transform tfm;
174
175       if (time == sd->time)
176         tfm = sd->ob_tfm;
177       else
178         tfm = object_fetch_transform_motion_test(kernel_globals, object, time, NULL);
179 #else
180       Transform tfm = object_fetch_transform(kernel_globals, object, OBJECT_TRANSFORM);
181 #endif
182       copy_matrix(result, tfm);
183
184       return true;
185     }
186     else if (sd->type == PRIMITIVE_LAMP) {
187       copy_matrix(result, sd->ob_tfm);
188
189       return true;
190     }
191   }
192
193   return false;
194 }
195
196 bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
197                                            OSL::Matrix44 &result,
198                                            OSL::TransformationPtr xform,
199                                            float time)
200 {
201   /* this is only used for shader and object space, we don't really have
202    * a concept of shader space, so we just use object space for both. */
203   if (xform) {
204     const ShaderData *sd = (const ShaderData *)xform;
205     int object = sd->object;
206
207     if (object != OBJECT_NONE) {
208 #ifdef __OBJECT_MOTION__
209       Transform itfm;
210
211       if (time == sd->time)
212         itfm = sd->ob_itfm;
213       else
214         object_fetch_transform_motion_test(kernel_globals, object, time, &itfm);
215 #else
216       Transform itfm = object_fetch_transform(kernel_globals, object, OBJECT_INVERSE_TRANSFORM);
217 #endif
218       copy_matrix(result, itfm);
219
220       return true;
221     }
222     else if (sd->type == PRIMITIVE_LAMP) {
223       copy_matrix(result, sd->ob_itfm);
224
225       return true;
226     }
227   }
228
229   return false;
230 }
231
232 bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
233                                    OSL::Matrix44 &result,
234                                    ustring from,
235                                    float time)
236 {
237   KernelGlobals *kg = kernel_globals;
238
239   if (from == u_ndc) {
240     copy_matrix(result, kernel_data.cam.ndctoworld);
241     return true;
242   }
243   else if (from == u_raster) {
244     copy_matrix(result, kernel_data.cam.rastertoworld);
245     return true;
246   }
247   else if (from == u_screen) {
248     copy_matrix(result, kernel_data.cam.screentoworld);
249     return true;
250   }
251   else if (from == u_camera) {
252     copy_matrix(result, kernel_data.cam.cameratoworld);
253     return true;
254   }
255   else if (from == u_world) {
256     result.makeIdentity();
257     return true;
258   }
259
260   return false;
261 }
262
263 bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
264                                            OSL::Matrix44 &result,
265                                            ustring to,
266                                            float time)
267 {
268   KernelGlobals *kg = kernel_globals;
269
270   if (to == u_ndc) {
271     copy_matrix(result, kernel_data.cam.worldtondc);
272     return true;
273   }
274   else if (to == u_raster) {
275     copy_matrix(result, kernel_data.cam.worldtoraster);
276     return true;
277   }
278   else if (to == u_screen) {
279     copy_matrix(result, kernel_data.cam.worldtoscreen);
280     return true;
281   }
282   else if (to == u_camera) {
283     copy_matrix(result, kernel_data.cam.worldtocamera);
284     return true;
285   }
286   else if (to == u_world) {
287     result.makeIdentity();
288     return true;
289   }
290
291   return false;
292 }
293
294 bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
295                                    OSL::Matrix44 &result,
296                                    OSL::TransformationPtr xform)
297 {
298   /* this is only used for shader and object space, we don't really have
299    * a concept of shader space, so we just use object space for both. */
300   if (xform) {
301     const ShaderData *sd = (const ShaderData *)xform;
302     int object = sd->object;
303
304     if (object != OBJECT_NONE) {
305 #ifdef __OBJECT_MOTION__
306       Transform tfm = sd->ob_tfm;
307 #else
308       Transform tfm = object_fetch_transform(kernel_globals, object, OBJECT_TRANSFORM);
309 #endif
310       copy_matrix(result, tfm);
311
312       return true;
313     }
314     else if (sd->type == PRIMITIVE_LAMP) {
315       copy_matrix(result, sd->ob_tfm);
316
317       return true;
318     }
319   }
320
321   return false;
322 }
323
324 bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
325                                            OSL::Matrix44 &result,
326                                            OSL::TransformationPtr xform)
327 {
328   /* this is only used for shader and object space, we don't really have
329    * a concept of shader space, so we just use object space for both. */
330   if (xform) {
331     const ShaderData *sd = (const ShaderData *)xform;
332     int object = sd->object;
333
334     if (object != OBJECT_NONE) {
335 #ifdef __OBJECT_MOTION__
336       Transform tfm = sd->ob_itfm;
337 #else
338       Transform tfm = object_fetch_transform(kernel_globals, object, OBJECT_INVERSE_TRANSFORM);
339 #endif
340       copy_matrix(result, tfm);
341
342       return true;
343     }
344     else if (sd->type == PRIMITIVE_LAMP) {
345       copy_matrix(result, sd->ob_itfm);
346
347       return true;
348     }
349   }
350
351   return false;
352 }
353
354 bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from)
355 {
356   KernelGlobals *kg = kernel_globals;
357
358   if (from == u_ndc) {
359     copy_matrix(result, kernel_data.cam.ndctoworld);
360     return true;
361   }
362   else if (from == u_raster) {
363     copy_matrix(result, kernel_data.cam.rastertoworld);
364     return true;
365   }
366   else if (from == u_screen) {
367     copy_matrix(result, kernel_data.cam.screentoworld);
368     return true;
369   }
370   else if (from == u_camera) {
371     copy_matrix(result, kernel_data.cam.cameratoworld);
372     return true;
373   }
374
375   return false;
376 }
377
378 bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
379                                            OSL::Matrix44 &result,
380                                            ustring to)
381 {
382   KernelGlobals *kg = kernel_globals;
383
384   if (to == u_ndc) {
385     copy_matrix(result, kernel_data.cam.worldtondc);
386     return true;
387   }
388   else if (to == u_raster) {
389     copy_matrix(result, kernel_data.cam.worldtoraster);
390     return true;
391   }
392   else if (to == u_screen) {
393     copy_matrix(result, kernel_data.cam.worldtoscreen);
394     return true;
395   }
396   else if (to == u_camera) {
397     copy_matrix(result, kernel_data.cam.worldtocamera);
398     return true;
399   }
400
401   return false;
402 }
403
404 bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg,
405                                             bool derivatives,
406                                             ustring object,
407                                             TypeDesc type,
408                                             ustring name,
409                                             int index,
410                                             void *val)
411 {
412   return false;
413 }
414
415 static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val)
416 {
417   if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
418       type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
419     float *fval = (float *)val;
420
421     fval[0] = f[0].x;
422     fval[1] = f[0].y;
423     fval[2] = 0.0f;
424
425     if (derivatives) {
426       fval[3] = f[1].x;
427       fval[4] = f[1].y;
428       fval[5] = 0.0f;
429
430       fval[6] = f[2].x;
431       fval[7] = f[2].y;
432       fval[8] = 0.0f;
433     }
434
435     return true;
436   }
437   else if (type == TypeDesc::TypeFloat) {
438     float *fval = (float *)val;
439     fval[0] = average(f[0]);
440
441     if (derivatives) {
442       fval[1] = average(f[1]);
443       fval[2] = average(f[2]);
444     }
445
446     return true;
447   }
448
449   return false;
450 }
451
452 static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
453 {
454   if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
455       type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
456     float *fval = (float *)val;
457
458     fval[0] = f[0].x;
459     fval[1] = f[0].y;
460     fval[2] = f[0].z;
461
462     if (derivatives) {
463       fval[3] = f[1].x;
464       fval[4] = f[1].y;
465       fval[5] = f[1].z;
466
467       fval[6] = f[2].x;
468       fval[7] = f[2].y;
469       fval[8] = f[2].z;
470     }
471
472     return true;
473   }
474   else if (type == TypeDesc::TypeFloat) {
475     float *fval = (float *)val;
476     fval[0] = average(f[0]);
477
478     if (derivatives) {
479       fval[1] = average(f[1]);
480       fval[2] = average(f[2]);
481     }
482
483     return true;
484   }
485
486   return false;
487 }
488
489 static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val)
490 {
491   float3 fv[3];
492
493   fv[0] = f;
494   fv[1] = make_float3(0.0f, 0.0f, 0.0f);
495   fv[2] = make_float3(0.0f, 0.0f, 0.0f);
496
497   return set_attribute_float3(fv, type, derivatives, val);
498 }
499
500 static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
501 {
502   if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
503       type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
504     float *fval = (float *)val;
505     fval[0] = f[0];
506     fval[1] = f[1];
507     fval[2] = f[2];
508
509     if (derivatives) {
510       fval[3] = f[1];
511       fval[4] = f[1];
512       fval[5] = f[1];
513
514       fval[6] = f[2];
515       fval[7] = f[2];
516       fval[8] = f[2];
517     }
518
519     return true;
520   }
521   else if (type == TypeDesc::TypeFloat) {
522     float *fval = (float *)val;
523     fval[0] = f[0];
524
525     if (derivatives) {
526       fval[1] = f[1];
527       fval[2] = f[2];
528     }
529
530     return true;
531   }
532
533   return false;
534 }
535
536 static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val)
537 {
538   float fv[3];
539
540   fv[0] = f;
541   fv[1] = 0.0f;
542   fv[2] = 0.0f;
543
544   return set_attribute_float(fv, type, derivatives, val);
545 }
546
547 static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
548 {
549   if (type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
550     int *ival = (int *)val;
551     ival[0] = i;
552
553     if (derivatives) {
554       ival[1] = 0;
555       ival[2] = 0;
556     }
557
558     return true;
559   }
560
561   return false;
562 }
563
564 static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val)
565 {
566   if (type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR &&
567       type.arraylen == 0) {
568     ustring *sval = (ustring *)val;
569     sval[0] = str;
570
571     if (derivatives) {
572       sval[1] = OSLRenderServices::u_empty;
573       sval[2] = OSLRenderServices::u_empty;
574     }
575
576     return true;
577   }
578
579   return false;
580 }
581
582 static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val)
583 {
584   if (type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
585     float *fval = (float *)val;
586
587     fval[0] = P[0].x;
588     fval[1] = P[0].y;
589     fval[2] = P[0].z;
590
591     fval[3] = P[1].x;
592     fval[4] = P[1].y;
593     fval[5] = P[1].z;
594
595     fval[6] = P[2].x;
596     fval[7] = P[2].y;
597     fval[8] = P[2].z;
598
599     if (type.arraylen > 3)
600       memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3));
601     if (derivatives)
602       memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen);
603
604     return true;
605   }
606
607   return false;
608 }
609
610 static bool set_attribute_matrix(const Transform &tfm, TypeDesc type, void *val)
611 {
612   if (type == TypeDesc::TypeMatrix) {
613     copy_matrix(*(OSL::Matrix44 *)val, tfm);
614     return true;
615   }
616
617   return false;
618 }
619
620 static bool get_primitive_attribute(KernelGlobals *kg,
621                                     const ShaderData *sd,
622                                     const OSLGlobals::Attribute &attr,
623                                     const TypeDesc &type,
624                                     bool derivatives,
625                                     void *val)
626 {
627   if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
628       attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
629     float3 fval[3];
630     fval[0] = primitive_attribute_float3(
631         kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
632     return set_attribute_float3(fval, type, derivatives, val);
633   }
634   else if (attr.type == TypeFloat2) {
635     float2 fval[2];
636     fval[0] = primitive_attribute_float2(
637         kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
638     return set_attribute_float2(fval, type, derivatives, val);
639   }
640   else if (attr.type == TypeDesc::TypeFloat) {
641     float fval[3];
642     fval[0] = primitive_attribute_float(
643         kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
644     return set_attribute_float(fval, type, derivatives, val);
645   }
646   else {
647     return false;
648   }
649 }
650
651 static bool get_mesh_attribute(KernelGlobals *kg,
652                                const ShaderData *sd,
653                                const OSLGlobals::Attribute &attr,
654                                const TypeDesc &type,
655                                bool derivatives,
656                                void *val)
657 {
658   if (attr.type == TypeDesc::TypeMatrix) {
659     Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc);
660     return set_attribute_matrix(tfm, type, val);
661   }
662   else {
663     return false;
664   }
665 }
666
667 static void get_object_attribute(const OSLGlobals::Attribute &attr, bool derivatives, void *val)
668 {
669   size_t datasize = attr.value.datasize();
670
671   memcpy(val, attr.value.data(), datasize);
672   if (derivatives)
673     memset((char *)val + datasize, 0, datasize * 2);
674 }
675
676 bool OSLRenderServices::get_object_standard_attribute(
677     KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val)
678 {
679   /* todo: turn this into hash table? */
680
681   /* Object Attributes */
682   if (name == u_object_location) {
683     float3 f = object_location(kg, sd);
684     return set_attribute_float3(f, type, derivatives, val);
685   }
686   else if (name == u_object_index) {
687     float f = object_pass_id(kg, sd->object);
688     return set_attribute_float(f, type, derivatives, val);
689   }
690   else if (name == u_geom_dupli_generated) {
691     float3 f = object_dupli_generated(kg, sd->object);
692     return set_attribute_float3(f, type, derivatives, val);
693   }
694   else if (name == u_geom_dupli_uv) {
695     float3 f = object_dupli_uv(kg, sd->object);
696     return set_attribute_float3(f, type, derivatives, val);
697   }
698   else if (name == u_material_index) {
699     float f = shader_pass_id(kg, sd);
700     return set_attribute_float(f, type, derivatives, val);
701   }
702   else if (name == u_object_random) {
703     float f = object_random_number(kg, sd->object);
704     return set_attribute_float(f, type, derivatives, val);
705   }
706
707   /* Particle Attributes */
708   else if (name == u_particle_index) {
709     int particle_id = object_particle_id(kg, sd->object);
710     float f = particle_index(kg, particle_id);
711     return set_attribute_float(f, type, derivatives, val);
712   }
713   else if (name == u_particle_random) {
714     int particle_id = object_particle_id(kg, sd->object);
715     float f = hash_int_01(particle_index(kg, particle_id));
716     return set_attribute_float(f, type, derivatives, val);
717   }
718
719   else if (name == u_particle_age) {
720     int particle_id = object_particle_id(kg, sd->object);
721     float f = particle_age(kg, particle_id);
722     return set_attribute_float(f, type, derivatives, val);
723   }
724   else if (name == u_particle_lifetime) {
725     int particle_id = object_particle_id(kg, sd->object);
726     float f = particle_lifetime(kg, particle_id);
727     return set_attribute_float(f, type, derivatives, val);
728   }
729   else if (name == u_particle_location) {
730     int particle_id = object_particle_id(kg, sd->object);
731     float3 f = particle_location(kg, particle_id);
732     return set_attribute_float3(f, type, derivatives, val);
733   }
734 #if 0 /* unsupported */
735   else if (name == u_particle_rotation) {
736     int particle_id = object_particle_id(kg, sd->object);
737     float4 f = particle_rotation(kg, particle_id);
738     return set_attribute_float4(f, type, derivatives, val);
739   }
740 #endif
741   else if (name == u_particle_size) {
742     int particle_id = object_particle_id(kg, sd->object);
743     float f = particle_size(kg, particle_id);
744     return set_attribute_float(f, type, derivatives, val);
745   }
746   else if (name == u_particle_velocity) {
747     int particle_id = object_particle_id(kg, sd->object);
748     float3 f = particle_velocity(kg, particle_id);
749     return set_attribute_float3(f, type, derivatives, val);
750   }
751   else if (name == u_particle_angular_velocity) {
752     int particle_id = object_particle_id(kg, sd->object);
753     float3 f = particle_angular_velocity(kg, particle_id);
754     return set_attribute_float3(f, type, derivatives, val);
755   }
756
757   /* Geometry Attributes */
758   else if (name == u_geom_numpolyvertices) {
759     return set_attribute_int(3, type, derivatives, val);
760   }
761   else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) &&
762            sd->type & PRIMITIVE_ALL_TRIANGLE) {
763     float3 P[3];
764
765     if (sd->type & PRIMITIVE_TRIANGLE)
766       triangle_vertices(kg, sd->prim, P);
767     else
768       motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
769
770     if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
771       object_position_transform(kg, sd, &P[0]);
772       object_position_transform(kg, sd, &P[1]);
773       object_position_transform(kg, sd, &P[2]);
774     }
775
776     return set_attribute_float3_3(P, type, derivatives, val);
777   }
778   else if (name == u_geom_name) {
779     ustring object_name = kg->osl->object_names[sd->object];
780     return set_attribute_string(object_name, type, derivatives, val);
781   }
782   else if (name == u_is_smooth) {
783     float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
784     return set_attribute_float(f, type, derivatives, val);
785   }
786   /* Hair Attributes */
787   else if (name == u_is_curve) {
788     float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
789     return set_attribute_float(f, type, derivatives, val);
790   }
791   else if (name == u_curve_thickness) {
792     float f = curve_thickness(kg, sd);
793     return set_attribute_float(f, type, derivatives, val);
794   }
795   else if (name == u_curve_tangent_normal) {
796     float3 f = curve_tangent_normal(kg, sd);
797     return set_attribute_float3(f, type, derivatives, val);
798   }
799   else
800     return false;
801 }
802
803 bool OSLRenderServices::get_background_attribute(
804     KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val)
805 {
806   if (name == u_path_ray_length) {
807     /* Ray Length */
808     float f = sd->ray_length;
809     return set_attribute_float(f, type, derivatives, val);
810   }
811   else if (name == u_path_ray_depth) {
812     /* Ray Depth */
813     PathState *state = sd->osl_path_state;
814     int f = state->bounce;
815     return set_attribute_int(f, type, derivatives, val);
816   }
817   else if (name == u_path_diffuse_depth) {
818     /* Diffuse Ray Depth */
819     PathState *state = sd->osl_path_state;
820     int f = state->diffuse_bounce;
821     return set_attribute_int(f, type, derivatives, val);
822   }
823   else if (name == u_path_glossy_depth) {
824     /* Glossy Ray Depth */
825     PathState *state = sd->osl_path_state;
826     int f = state->glossy_bounce;
827     return set_attribute_int(f, type, derivatives, val);
828   }
829   else if (name == u_path_transmission_depth) {
830     /* Transmission Ray Depth */
831     PathState *state = sd->osl_path_state;
832     int f = state->transmission_bounce;
833     return set_attribute_int(f, type, derivatives, val);
834   }
835   else if (name == u_path_transparent_depth) {
836     /* Transparent Ray Depth */
837     PathState *state = sd->osl_path_state;
838     int f = state->transparent_bounce;
839     return set_attribute_int(f, type, derivatives, val);
840   }
841   else if (name == u_path_transmission_depth) {
842     /* Transmission Ray Depth */
843     PathState *state = sd->osl_path_state;
844     int f = state->transmission_bounce;
845     return set_attribute_int(f, type, derivatives, val);
846   }
847   else if (name == u_ndc) {
848     /* NDC coordinates with special exception for otho */
849     OSLThreadData *tdata = kg->osl_tdata;
850     OSL::ShaderGlobals *globals = &tdata->globals;
851     float3 ndc[3];
852
853     if ((globals->raytype & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
854         kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
855       ndc[0] = camera_world_to_ndc(kg, sd, sd->ray_P);
856
857       if (derivatives) {
858         ndc[1] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx) - ndc[0];
859         ndc[2] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy) - ndc[0];
860       }
861     }
862     else {
863       ndc[0] = camera_world_to_ndc(kg, sd, sd->P);
864
865       if (derivatives) {
866         ndc[1] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx) - ndc[0];
867         ndc[2] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy) - ndc[0];
868       }
869     }
870
871     return set_attribute_float3(ndc, type, derivatives, val);
872   }
873   else
874     return false;
875 }
876
877 bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
878                                       bool derivatives,
879                                       ustring object_name,
880                                       TypeDesc type,
881                                       ustring name,
882                                       void *val)
883 {
884   if (sg == NULL || sg->renderstate == NULL)
885     return false;
886
887   ShaderData *sd = (ShaderData *)(sg->renderstate);
888   return get_attribute(sd, derivatives, object_name, type, name, val);
889 }
890
891 bool OSLRenderServices::get_attribute(
892     ShaderData *sd, bool derivatives, ustring object_name, TypeDesc type, ustring name, void *val)
893 {
894   KernelGlobals *kg = kernel_globals;
895   int prim_type = 0;
896   int object;
897
898   /* lookup of attribute on another object */
899   if (object_name != u_empty) {
900     OSLGlobals::ObjectNameMap::iterator it = osl_globals->object_name_map.find(object_name);
901
902     if (it == osl_globals->object_name_map.end())
903       return false;
904
905     object = it->second;
906   }
907   else {
908     object = sd->object;
909     prim_type = attribute_primitive_type(kg, sd);
910
911     if (object == OBJECT_NONE)
912       return get_background_attribute(kg, sd, name, type, derivatives, val);
913   }
914
915   /* find attribute on object */
916   object = object * ATTR_PRIM_TYPES + prim_type;
917   OSLGlobals::AttributeMap &attribute_map = osl_globals->attribute_map[object];
918   OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
919
920   if (it != attribute_map.end()) {
921     const OSLGlobals::Attribute &attr = it->second;
922
923     if (attr.desc.element != ATTR_ELEMENT_OBJECT) {
924       /* triangle and vertex attributes */
925       if (get_primitive_attribute(kg, sd, attr, type, derivatives, val))
926         return true;
927       else
928         return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
929     }
930     else {
931       /* object attribute */
932       get_object_attribute(attr, derivatives, val);
933       return true;
934     }
935   }
936   else {
937     /* not found in attribute, check standard object info */
938     bool is_std_object_attribute = get_object_standard_attribute(
939         kg, sd, name, type, derivatives, val);
940
941     if (is_std_object_attribute)
942       return true;
943
944     return get_background_attribute(kg, sd, name, type, derivatives, val);
945   }
946
947   return false;
948 }
949
950 bool OSLRenderServices::get_userdata(
951     bool derivatives, ustring name, TypeDesc type, OSL::ShaderGlobals *sg, void *val)
952 {
953   return false; /* disabled by lockgeom */
954 }
955
956 TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring filename)
957 {
958   OSLTextureHandleMap::iterator it = osl_globals->textures.find(filename);
959
960   /* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */
961   if (it != osl_globals->textures.end()) {
962     if (it->second->type != OSLTextureHandle::OIIO) {
963       return (TextureSystem::TextureHandle *)it->second.get();
964     }
965   }
966
967   /* Get handle from OpenImageIO. */
968   OSL::TextureSystem *ts = osl_ts;
969   TextureSystem::TextureHandle *handle = ts->get_texture_handle(filename);
970   if (handle == NULL) {
971     return NULL;
972   }
973
974   /* Insert new OSLTextureHandle if needed. */
975   if (it == osl_globals->textures.end()) {
976     osl_globals->textures.insert(filename, new OSLTextureHandle(OSLTextureHandle::OIIO));
977     it = osl_globals->textures.find(filename);
978   }
979
980   /* Assign OIIO texture handle and return. */
981   it->second->oiio_handle = handle;
982   return (TextureSystem::TextureHandle *)it->second.get();
983 }
984
985 bool OSLRenderServices::good(TextureSystem::TextureHandle *texture_handle)
986 {
987   OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
988
989   if (handle->oiio_handle) {
990     OSL::TextureSystem *ts = osl_ts;
991     return ts->good(handle->oiio_handle);
992   }
993   else {
994     return true;
995   }
996 }
997
998 bool OSLRenderServices::texture(ustring filename,
999                                 TextureHandle *texture_handle,
1000                                 TexturePerthread *texture_thread_info,
1001                                 TextureOpt &options,
1002                                 OSL::ShaderGlobals *sg,
1003                                 float s,
1004                                 float t,
1005                                 float dsdx,
1006                                 float dtdx,
1007                                 float dsdy,
1008                                 float dtdy,
1009                                 int nchannels,
1010                                 float *result,
1011                                 float *dresultds,
1012                                 float *dresultdt,
1013                                 ustring *errormessage)
1014 {
1015   OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1016   OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
1017   bool status = false;
1018
1019   switch (texture_type) {
1020     case OSLTextureHandle::BEVEL: {
1021       /* Bevel shader hack. */
1022       if (nchannels >= 3) {
1023         ShaderData *sd = (ShaderData *)(sg->renderstate);
1024         PathState *state = sd->osl_path_state;
1025         int num_samples = (int)s;
1026         float radius = t;
1027         float3 N = svm_bevel(kernel_globals, sd, state, radius, num_samples);
1028         result[0] = N.x;
1029         result[1] = N.y;
1030         result[2] = N.z;
1031         status = true;
1032       }
1033       break;
1034     }
1035     case OSLTextureHandle::AO: {
1036       /* AO shader hack. */
1037       ShaderData *sd = (ShaderData *)(sg->renderstate);
1038       PathState *state = sd->osl_path_state;
1039       int num_samples = (int)s;
1040       float radius = t;
1041       float3 N = make_float3(dsdx, dtdx, dsdy);
1042       int flags = 0;
1043       if ((int)dtdy) {
1044         flags |= NODE_AO_INSIDE;
1045       }
1046       if ((int)options.sblur) {
1047         flags |= NODE_AO_ONLY_LOCAL;
1048       }
1049       if ((int)options.tblur) {
1050         flags |= NODE_AO_GLOBAL_RADIUS;
1051       }
1052       result[0] = svm_ao(kernel_globals, sd, N, state, radius, num_samples, flags);
1053       status = true;
1054       break;
1055     }
1056     case OSLTextureHandle::SVM: {
1057       /* Packed texture. */
1058       float4 rgba = kernel_tex_image_interp(kernel_globals, handle->svm_slot, s, 1.0f - t);
1059
1060       result[0] = rgba[0];
1061       if (nchannels > 1)
1062         result[1] = rgba[1];
1063       if (nchannels > 2)
1064         result[2] = rgba[2];
1065       if (nchannels > 3)
1066         result[3] = rgba[3];
1067       status = true;
1068       break;
1069     }
1070     case OSLTextureHandle::IES: {
1071       /* IES light. */
1072       result[0] = kernel_ies_interp(kernel_globals, handle->svm_slot, s, t);
1073       status = true;
1074       break;
1075     }
1076     case OSLTextureHandle::OIIO: {
1077       /* OpenImageIO texture cache. */
1078       OSL::TextureSystem *ts = osl_ts;
1079
1080       if (handle && handle->oiio_handle) {
1081         if (texture_thread_info == NULL) {
1082           OSLThreadData *tdata = kernel_globals->osl_tdata;
1083           texture_thread_info = tdata->oiio_thread_info;
1084         }
1085
1086         status = ts->texture(handle->oiio_handle,
1087                              texture_thread_info,
1088                              options,
1089                              s,
1090                              t,
1091                              dsdx,
1092                              dtdx,
1093                              dsdy,
1094                              dtdy,
1095                              nchannels,
1096                              result,
1097                              dresultds,
1098                              dresultdt);
1099       }
1100       else {
1101         status = ts->texture(filename,
1102                              options,
1103                              s,
1104                              t,
1105                              dsdx,
1106                              dtdx,
1107                              dsdy,
1108                              dtdy,
1109                              nchannels,
1110                              result,
1111                              dresultds,
1112                              dresultdt);
1113       }
1114
1115       if (!status) {
1116         /* This might be slow, but prevents error messages leak and
1117          * other nasty stuff happening. */
1118         ts->geterror();
1119       }
1120       else if (handle && handle->processor) {
1121         ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
1122       }
1123       break;
1124     }
1125   }
1126
1127   if (!status) {
1128     if (nchannels == 3 || nchannels == 4) {
1129       result[0] = 1.0f;
1130       result[1] = 0.0f;
1131       result[2] = 1.0f;
1132
1133       if (nchannels == 4)
1134         result[3] = 1.0f;
1135     }
1136   }
1137
1138   return status;
1139 }
1140
1141 bool OSLRenderServices::texture3d(ustring filename,
1142                                   TextureHandle *texture_handle,
1143                                   TexturePerthread *texture_thread_info,
1144                                   TextureOpt &options,
1145                                   OSL::ShaderGlobals *sg,
1146                                   const OSL::Vec3 &P,
1147                                   const OSL::Vec3 &dPdx,
1148                                   const OSL::Vec3 &dPdy,
1149                                   const OSL::Vec3 &dPdz,
1150                                   int nchannels,
1151                                   float *result,
1152                                   float *dresultds,
1153                                   float *dresultdt,
1154                                   float *dresultdr,
1155                                   ustring *errormessage)
1156 {
1157   OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1158   OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
1159   bool status = false;
1160
1161   switch (texture_type) {
1162     case OSLTextureHandle::SVM: {
1163       /* Packed texture. */
1164       int slot = handle->svm_slot;
1165       float4 rgba = kernel_tex_image_interp_3d(
1166           kernel_globals, slot, P.x, P.y, P.z, INTERPOLATION_NONE);
1167
1168       result[0] = rgba[0];
1169       if (nchannels > 1)
1170         result[1] = rgba[1];
1171       if (nchannels > 2)
1172         result[2] = rgba[2];
1173       if (nchannels > 3)
1174         result[3] = rgba[3];
1175       status = true;
1176       break;
1177     }
1178     case OSLTextureHandle::OIIO: {
1179       /* OpenImageIO texture cache. */
1180       OSL::TextureSystem *ts = osl_ts;
1181
1182       if (handle && handle->oiio_handle) {
1183         if (texture_thread_info == NULL) {
1184           OSLThreadData *tdata = kernel_globals->osl_tdata;
1185           texture_thread_info = tdata->oiio_thread_info;
1186         }
1187
1188         status = ts->texture3d(handle->oiio_handle,
1189                                texture_thread_info,
1190                                options,
1191                                P,
1192                                dPdx,
1193                                dPdy,
1194                                dPdz,
1195                                nchannels,
1196                                result,
1197                                dresultds,
1198                                dresultdt,
1199                                dresultdr);
1200       }
1201       else {
1202         status = ts->texture3d(filename,
1203                                options,
1204                                P,
1205                                dPdx,
1206                                dPdy,
1207                                dPdz,
1208                                nchannels,
1209                                result,
1210                                dresultds,
1211                                dresultdt,
1212                                dresultdr);
1213       }
1214
1215       if (!status) {
1216         /* This might be slow, but prevents error messages leak and
1217          * other nasty stuff happening. */
1218         ts->geterror();
1219       }
1220       else if (handle && handle->processor) {
1221         ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
1222       }
1223       break;
1224     }
1225     case OSLTextureHandle::IES:
1226     case OSLTextureHandle::AO:
1227     case OSLTextureHandle::BEVEL: {
1228       status = false;
1229       break;
1230     }
1231   }
1232
1233   if (!status) {
1234     if (nchannels == 3 || nchannels == 4) {
1235       result[0] = 1.0f;
1236       result[1] = 0.0f;
1237       result[2] = 1.0f;
1238
1239       if (nchannels == 4)
1240         result[3] = 1.0f;
1241     }
1242   }
1243
1244   return status;
1245 }
1246
1247 bool OSLRenderServices::environment(ustring filename,
1248                                     TextureHandle *texture_handle,
1249                                     TexturePerthread *thread_info,
1250                                     TextureOpt &options,
1251                                     OSL::ShaderGlobals *sg,
1252                                     const OSL::Vec3 &R,
1253                                     const OSL::Vec3 &dRdx,
1254                                     const OSL::Vec3 &dRdy,
1255                                     int nchannels,
1256                                     float *result,
1257                                     float *dresultds,
1258                                     float *dresultdt,
1259                                     ustring *errormessage)
1260 {
1261   OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1262   OSL::TextureSystem *ts = osl_ts;
1263   bool status = false;
1264
1265   if (handle && handle->oiio_handle) {
1266     if (thread_info == NULL) {
1267       OSLThreadData *tdata = kernel_globals->osl_tdata;
1268       thread_info = tdata->oiio_thread_info;
1269     }
1270
1271     status = ts->environment(handle->oiio_handle,
1272                              thread_info,
1273                              options,
1274                              R,
1275                              dRdx,
1276                              dRdy,
1277                              nchannels,
1278                              result,
1279                              dresultds,
1280                              dresultdt);
1281   }
1282   else {
1283     status = ts->environment(
1284         filename, options, R, dRdx, dRdy, nchannels, result, dresultds, dresultdt);
1285   }
1286
1287   if (!status) {
1288     if (nchannels == 3 || nchannels == 4) {
1289       result[0] = 1.0f;
1290       result[1] = 0.0f;
1291       result[2] = 1.0f;
1292
1293       if (nchannels == 4)
1294         result[3] = 1.0f;
1295     }
1296   }
1297   else if (handle && handle->processor) {
1298     ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
1299   }
1300
1301   return status;
1302 }
1303
1304 bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
1305                                          ustring filename,
1306                                          TextureHandle *texture_handle,
1307                                          int subimage,
1308                                          ustring dataname,
1309                                          TypeDesc datatype,
1310                                          void *data)
1311 {
1312   OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1313
1314   /* No texture info for other texture types. */
1315   if (handle && handle->type != OSLTextureHandle::OIIO) {
1316     return false;
1317   }
1318
1319   /* Get texture info from OpenImageIO. */
1320   OSL::TextureSystem *ts = osl_ts;
1321   return ts->get_texture_info(filename, subimage, dataname, datatype, data);
1322 }
1323
1324 int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg,
1325                                          ustring filename,
1326                                          const OSL::Vec3 &center,
1327                                          float radius,
1328                                          int max_points,
1329                                          bool sort,
1330                                          size_t *out_indices,
1331                                          float *out_distances,
1332                                          int derivs_offset)
1333 {
1334   return 0;
1335 }
1336
1337 int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals *sg,
1338                                       ustring filename,
1339                                       size_t *indices,
1340                                       int count,
1341                                       ustring attr_name,
1342                                       TypeDesc attr_type,
1343                                       void *out_data)
1344 {
1345   return 0;
1346 }
1347
1348 bool OSLRenderServices::pointcloud_write(OSL::ShaderGlobals *sg,
1349                                          ustring filename,
1350                                          const OSL::Vec3 &pos,
1351                                          int nattribs,
1352                                          const ustring *names,
1353                                          const TypeDesc *types,
1354                                          const void **data)
1355 {
1356   return false;
1357 }
1358
1359 bool OSLRenderServices::trace(TraceOpt &options,
1360                               OSL::ShaderGlobals *sg,
1361                               const OSL::Vec3 &P,
1362                               const OSL::Vec3 &dPdx,
1363                               const OSL::Vec3 &dPdy,
1364                               const OSL::Vec3 &R,
1365                               const OSL::Vec3 &dRdx,
1366                               const OSL::Vec3 &dRdy)
1367 {
1368   /* todo: options.shader support, maybe options.traceset */
1369   ShaderData *sd = (ShaderData *)(sg->renderstate);
1370
1371   /* setup ray */
1372   Ray ray;
1373
1374   ray.P = TO_FLOAT3(P);
1375   ray.D = TO_FLOAT3(R);
1376   ray.t = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
1377   ray.time = sd->time;
1378
1379   if (options.mindist == 0.0f) {
1380     /* avoid self-intersections */
1381     if (ray.P == sd->P) {
1382       bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
1383       ray.P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
1384     }
1385   }
1386   else {
1387     /* offset for minimum distance */
1388     ray.P += options.mindist * ray.D;
1389   }
1390
1391   /* ray differentials */
1392   ray.dP.dx = TO_FLOAT3(dPdx);
1393   ray.dP.dy = TO_FLOAT3(dPdy);
1394   ray.dD.dx = TO_FLOAT3(dRdx);
1395   ray.dD.dy = TO_FLOAT3(dRdy);
1396
1397   /* allocate trace data */
1398   OSLTraceData *tracedata = (OSLTraceData *)sg->tracedata;
1399   tracedata->ray = ray;
1400   tracedata->setup = false;
1401   tracedata->init = true;
1402
1403   /* Raytrace, leaving out shadow opaque to avoid early exit. */
1404   uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
1405   return scene_intersect(kernel_globals, ray, visibility, &tracedata->isect);
1406 }
1407
1408 bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg,
1409                                    ustring source,
1410                                    ustring name,
1411                                    TypeDesc type,
1412                                    void *val,
1413                                    bool derivatives)
1414 {
1415   OSLTraceData *tracedata = (OSLTraceData *)sg->tracedata;
1416
1417   if (source == u_trace && tracedata->init) {
1418     if (name == u_hit) {
1419       return set_attribute_int((tracedata->isect.prim != PRIM_NONE), type, derivatives, val);
1420     }
1421     else if (tracedata->isect.prim != PRIM_NONE) {
1422       if (name == u_hitdist) {
1423         float f[3] = {tracedata->isect.t, 0.0f, 0.0f};
1424         return set_attribute_float(f, type, derivatives, val);
1425       }
1426       else {
1427         ShaderData *sd = &tracedata->sd;
1428
1429         if (!tracedata->setup) {
1430           /* lazy shader data setup */
1431           shader_setup_from_ray(kernel_globals, sd, &tracedata->isect, &tracedata->ray);
1432           tracedata->setup = true;
1433         }
1434
1435         if (name == u_N) {
1436           return set_attribute_float3(sd->N, type, derivatives, val);
1437         }
1438         else if (name == u_Ng) {
1439           return set_attribute_float3(sd->Ng, type, derivatives, val);
1440         }
1441         else if (name == u_P) {
1442           float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy};
1443           return set_attribute_float3(f, type, derivatives, val);
1444         }
1445         else if (name == u_I) {
1446           float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy};
1447           return set_attribute_float3(f, type, derivatives, val);
1448         }
1449         else if (name == u_u) {
1450           float f[3] = {sd->u, sd->du.dx, sd->du.dy};
1451           return set_attribute_float(f, type, derivatives, val);
1452         }
1453         else if (name == u_v) {
1454           float f[3] = {sd->v, sd->dv.dx, sd->dv.dy};
1455           return set_attribute_float(f, type, derivatives, val);
1456         }
1457
1458         return get_attribute(sd, derivatives, u_empty, type, name, val);
1459       }
1460     }
1461   }
1462
1463   return false;
1464 }
1465
1466 CCL_NAMESPACE_END