Blender V5.0
services.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5/* TODO(sergey): There is a bit of headers dependency hell going on
6 * here, so for now we just put here. In the future it might be better
7 * to have dedicated file for such tweaks.
8 */
9#if (defined(__GNUC__) && !defined(__clang__)) && defined(NDEBUG)
10# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
11# pragma GCC diagnostic ignored "-Wuninitialized"
12#endif
13
14#include <cstring>
15
16#include "scene/colorspace.h"
17#include "scene/object.h"
18
19#include "util/log.h"
20#include "util/string.h"
21
23
24#include "kernel/osl/globals.h"
25#include "kernel/osl/services.h"
27#include "kernel/osl/types.h"
28
30
33
34#include "kernel/bvh/bvh.h"
35
37
38#include "kernel/svm/ao.h"
39#include "kernel/svm/bevel.h"
40
41#include "kernel/util/ies.h"
43
45
46/* RenderServices implementation */
47
48static void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
49{
51 memcpy((float *)&m, (const float *)&t, sizeof(m));
52}
53
54static void copy_matrix(OSL::Matrix44 &m, const ProjectionTransform &tfm)
55{
57 memcpy((float *)&m, (const float *)&t, sizeof(m));
58}
59
60/* static ustrings */
61ustring OSLRenderServices::u_distance("distance");
62ustring OSLRenderServices::u_index("index");
63ustring OSLRenderServices::u_world("world");
64ustring OSLRenderServices::u_camera("camera");
65ustring OSLRenderServices::u_screen("screen");
66ustring OSLRenderServices::u_raster("raster");
67ustring OSLRenderServices::u_ndc("NDC");
68ustring OSLRenderServices::u_object_location("object:location");
69ustring OSLRenderServices::u_object_color("object:color");
70ustring OSLRenderServices::u_object_alpha("object:alpha");
71ustring OSLRenderServices::u_object_index("object:index");
72ustring OSLRenderServices::u_object_is_light("object:is_light");
73ustring OSLRenderServices::u_bump_map_normal("geom:bump_map_normal");
74ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
75ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
76ustring OSLRenderServices::u_material_index("material:index");
77ustring OSLRenderServices::u_object_random("object:random");
78ustring OSLRenderServices::u_particle_index("particle:index");
79ustring OSLRenderServices::u_particle_random("particle:random");
80ustring OSLRenderServices::u_particle_age("particle:age");
81ustring OSLRenderServices::u_particle_lifetime("particle:lifetime");
82ustring OSLRenderServices::u_particle_location("particle:location");
83ustring OSLRenderServices::u_particle_rotation("particle:rotation");
84ustring OSLRenderServices::u_particle_size("particle:size");
85ustring OSLRenderServices::u_particle_velocity("particle:velocity");
86ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity");
87ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices");
88ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices");
89ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
90ustring OSLRenderServices::u_geom_name("geom:name");
91ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced");
92ustring OSLRenderServices::u_is_smooth("geom:is_smooth");
93ustring OSLRenderServices::u_is_curve("geom:is_curve");
94ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
95ustring OSLRenderServices::u_curve_length("geom:curve_length");
96ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
97ustring OSLRenderServices::u_curve_random("geom:curve_random");
98ustring OSLRenderServices::u_is_point("geom:is_point");
99ustring OSLRenderServices::u_point_radius("geom:point_radius");
100ustring OSLRenderServices::u_point_position("geom:point_position");
101ustring OSLRenderServices::u_point_random("geom:point_random");
102ustring OSLRenderServices::u_normal_map_normal("geom:normal_map_normal");
103ustring OSLRenderServices::u_path_ray_length("path:ray_length");
104ustring OSLRenderServices::u_path_ray_depth("path:ray_depth");
105ustring OSLRenderServices::u_path_diffuse_depth("path:diffuse_depth");
106ustring OSLRenderServices::u_path_glossy_depth("path:glossy_depth");
107ustring OSLRenderServices::u_path_transparent_depth("path:transparent_depth");
108ustring OSLRenderServices::u_path_transmission_depth("path:transmission_depth");
109ustring OSLRenderServices::u_path_portal_depth("path:portal_depth");
110ustring OSLRenderServices::u_trace("trace");
111ustring OSLRenderServices::u_hit("hit");
112ustring OSLRenderServices::u_hitdist("hitdist");
113ustring OSLRenderServices::u_N("N");
114ustring OSLRenderServices::u_Ng("Ng");
115ustring OSLRenderServices::u_P("P");
116ustring OSLRenderServices::u_I("I");
117ustring OSLRenderServices::u_u("u");
118ustring OSLRenderServices::u_v("v");
120
121ustring OSLRenderServices::u_sensor_size("cam:sensor_size");
122ustring OSLRenderServices::u_image_resolution("cam:image_resolution");
123ustring OSLRenderServices::u_aperture_aspect_ratio("cam:aperture_aspect_ratio");
124ustring OSLRenderServices::u_aperture_size("cam:aperture_size");
125ustring OSLRenderServices::u_aperture_position("cam:aperture_position");
126ustring OSLRenderServices::u_focal_distance("cam:focal_distance");
127
129
130OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system, const int device_type)
131 : OSL::RendererServices(texture_system), device_type_(device_type)
132{
133}
134
136{
137 if (m_texturesys) {
138 LOG_INFO << "OSL texture system stats:\n" << m_texturesys->getstats();
139 }
140}
141
142int OSLRenderServices::supports(string_view feature) const
143{
144#ifdef WITH_OPTIX
145 if (feature == "OptiX") {
146 return device_type_ == DEVICE_OPTIX;
147 }
148#else
149 (void)feature;
150#endif
151
152 return false;
153}
154
155bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
156 OSL::Matrix44 &result,
157 OSL::TransformationPtr /*xform*/,
158 const float time)
159{
160 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
161
162 if (globals == nullptr || globals->sd == nullptr) {
163 return false;
164 }
165
166 /* this is only used for shader and object space, we don't really have
167 * a concept of shader space, so we just use object space for both. */
168 const ShaderData *sd = globals->sd;
169 const ThreadKernelGlobalsCPU *kg = globals->kg;
170 const int object = sd->object;
171
172 if (object != OBJECT_NONE) {
173#ifdef __OBJECT_MOTION__
174 Transform tfm;
175
176 if (time == sd->time) {
177 tfm = object_get_transform(kg, sd);
178 }
179 else {
180 tfm = object_fetch_transform_motion_test(kg, object, time, nullptr);
181 }
182#else
183 const Transform tfm = object_get_transform(kg, sd);
184#endif
185 copy_matrix(result, tfm);
186
187 return true;
188 }
189
190 return false;
191}
192
193bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
194 OSL::Matrix44 &result,
195 OSL::TransformationPtr /*xform*/,
196 const float time)
197{
198 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
199
200 if (globals == nullptr || globals->sd == nullptr) {
201 return false;
202 }
203
204 /* this is only used for shader and object space, we don't really have
205 * a concept of shader space, so we just use object space for both. */
206 const ShaderData *sd = globals->sd;
207 const ThreadKernelGlobalsCPU *kg = globals->kg;
208 const int object = sd->object;
209
210 if (object != OBJECT_NONE) {
211#ifdef __OBJECT_MOTION__
212 Transform itfm;
213
214 if (time == sd->time) {
215 itfm = object_get_inverse_transform(kg, sd);
216 }
217 else {
218 object_fetch_transform_motion_test(kg, object, time, &itfm);
219 }
220#else
221 const Transform itfm = object_get_inverse_transform(kg, sd);
222#endif
223 copy_matrix(result, itfm);
224
225 return true;
226 }
227
228 return false;
229}
230
231bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
232 OSL::Matrix44 &result,
233 OSLUStringHash from,
234 const float /*time*/)
235{
236 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
237 const ThreadKernelGlobalsCPU *kg = globals->kg;
238
239 if (from == u_ndc) {
240 copy_matrix(result, kernel_data.cam.ndctoworld);
241 return true;
242 }
243 if (from == u_raster) {
244 copy_matrix(result, kernel_data.cam.rastertoworld);
245 return true;
246 }
247 if (from == u_screen) {
248 copy_matrix(result, kernel_data.cam.screentoworld);
249 return true;
250 }
251 if (from == u_camera) {
252 copy_matrix(result, kernel_data.cam.cameratoworld);
253 return true;
254 }
255 if (from == u_world) {
256 result.makeIdentity();
257 return true;
258 }
259
260 return false;
261}
262
263bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
264 OSL::Matrix44 &result,
266 const float /*time*/)
267{
268 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
269 const ThreadKernelGlobalsCPU *kg = globals->kg;
270
271 if (to == u_ndc) {
272 copy_matrix(result, kernel_data.cam.worldtondc);
273 return true;
274 }
275 if (to == u_raster) {
276 copy_matrix(result, kernel_data.cam.worldtoraster);
277 return true;
278 }
279 if (to == u_screen) {
280 copy_matrix(result, kernel_data.cam.worldtoscreen);
281 return true;
282 }
283 if (to == u_camera) {
284 copy_matrix(result, kernel_data.cam.worldtocamera);
285 return true;
286 }
287 if (to == u_world) {
288 result.makeIdentity();
289 return true;
290 }
291
292 return false;
293}
294
295bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
296 OSL::Matrix44 &result,
297 OSL::TransformationPtr /*xform*/)
298{
299 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
300
301 if (globals == nullptr || globals->sd == nullptr) {
302 return false;
303 }
304
305 /* this is only used for shader and object space, we don't really have
306 * a concept of shader space, so we just use object space for both. */
307 const ShaderData *sd = globals->sd;
308 const ThreadKernelGlobalsCPU *kg = globals->kg;
309 const int object = sd->object;
310
311 if (object != OBJECT_NONE) {
312 const Transform tfm = object_get_transform(kg, sd);
313 copy_matrix(result, tfm);
314
315 return true;
316 }
317
318 return false;
319}
320
321bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
322 OSL::Matrix44 &result,
323 OSL::TransformationPtr /*xform*/)
324{
325 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
326
327 if (globals == nullptr || globals->sd == nullptr) {
328 return false;
329 }
330
331 /* this is only used for shader and object space, we don't really have
332 * a concept of shader space, so we just use object space for both. */
333 const ShaderData *sd = globals->sd;
334 const ThreadKernelGlobalsCPU *kg = globals->kg;
335 const int object = sd->object;
336
337 if (object != OBJECT_NONE) {
338 const Transform tfm = object_get_inverse_transform(kg, sd);
339 copy_matrix(result, tfm);
340
341 return true;
342 }
343
344 return false;
345}
346
347bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
348 OSL::Matrix44 &result,
349 OSLUStringHash from)
350{
351 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
352 const ThreadKernelGlobalsCPU *kg = globals->kg;
353
354 if (from == u_ndc) {
355 copy_matrix(result, kernel_data.cam.ndctoworld);
356 return true;
357 }
358 if (from == u_raster) {
359 copy_matrix(result, kernel_data.cam.rastertoworld);
360 return true;
361 }
362 if (from == u_screen) {
363 copy_matrix(result, kernel_data.cam.screentoworld);
364 return true;
365 }
366 if (from == u_camera) {
367 copy_matrix(result, kernel_data.cam.cameratoworld);
368 return true;
369 }
370
371 return false;
372}
373
374bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
375 OSL::Matrix44 &result,
377{
378 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
379 const ThreadKernelGlobalsCPU *kg = globals->kg;
380
381 if (to == u_ndc) {
382 copy_matrix(result, kernel_data.cam.worldtondc);
383 return true;
384 }
385 if (to == u_raster) {
386 copy_matrix(result, kernel_data.cam.worldtoraster);
387 return true;
388 }
389 if (to == u_screen) {
390 copy_matrix(result, kernel_data.cam.worldtoscreen);
391 return true;
392 }
393 if (to == u_camera) {
394 copy_matrix(result, kernel_data.cam.worldtocamera);
395 return true;
396 }
397
398 return false;
399}
400
401bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals * /*sg*/,
402 bool /* derivatives*/,
403 OSLUStringHash /* object*/,
404 const TypeDesc /* type*/,
405 OSLUStringHash /* name*/,
406 const int /* index*/,
407 void * /*val*/)
408{
409 return false;
410}
411
413 TypeDesc type,
414 bool derivatives,
415 void *val)
416{
417 if (type == TypeFloatArray4) {
418 set_data_float4(make_float4(make_float3(v)), derivatives, val);
419 return true;
420 }
421 if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
422 set_data_float3(make_float3(v), derivatives, val);
423 return true;
424 }
425 if (type == TypeFloat) {
426 set_data_float(v, derivatives, val);
427 return true;
428 }
429
430 return false;
431}
432
434 TypeDesc type,
435 bool derivatives,
436 void *val)
437{
438 if (type == TypeFloatArray4) {
439 set_data_float4(make_float4(make_float3(v)), derivatives, val);
440 return true;
441 }
442 if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
443 set_data_float3(make_float3(v), derivatives, val);
444 return true;
445 }
446 if (type == TypeFloat) {
447 set_data_float(average(v), derivatives, val);
448 return true;
449 }
450
451 return false;
452}
453
455 TypeDesc type,
456 bool derivatives,
457 void *val)
458{
459 if (type == TypeFloatArray4) {
460 set_data_float4(make_float4(v), derivatives, val);
461 return true;
462 }
463 if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
464 set_data_float3(v, derivatives, val);
465 return true;
466 }
467 if (type == TypeFloat) {
468 set_data_float(average(v), derivatives, val);
469 return true;
470 }
471
472 return false;
473}
474
475/* Attributes with the TypeRGBA type descriptor should be retrieved and stored
476 * in a float array of size 4 (e.g. node_vertex_color.osl), this array have
477 * a type descriptor TypeFloatArray4. If the storage is not a TypeFloatArray4,
478 * we either store the first three components in a vector, store the average of
479 * the components in a float, or fail the retrieval and do nothing. We allow
480 * this for the correct operation of the Attribute node.
481 */
482
484 TypeDesc type,
485 bool derivatives,
486 void *val)
487{
488 if (type == TypeFloatArray4) {
489 set_data_float4(v, derivatives, val);
490 return true;
491 }
492 if (type == TypePoint || type == TypeVector || type == TypeNormal || type == TypeColor) {
493 set_data_float3(make_float3(v), derivatives, val);
494 return true;
495 }
496 if (type == TypeFloat) {
497 set_data_float(average(make_float3(v)), derivatives, val);
498 return true;
499 }
500 return false;
501}
502
503template<typename T>
504ccl_device_inline bool set_attribute(const T f, const TypeDesc type, bool derivatives, void *val)
505{
506 return set_attribute(dual<T>(f), type, derivatives, val);
507}
508
510 const TypeDesc type,
511 bool derivatives,
512 void *val)
513{
514 if (type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
515 int *ival = (int *)val;
516 ival[0] = i;
517
518 if (derivatives) {
519 ival[1] = 0;
520 ival[2] = 0;
521 }
522
523 return true;
524 }
525
526 return false;
527}
528
530 const TypeDesc type,
531 bool derivatives,
532 void *val)
533{
534 if (type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR &&
535 type.arraylen == 0)
536 {
537 OSLUStringHash *sval = (OSLUStringHash *)val;
538 sval[0] = str;
539
540 if (derivatives) {
541 sval[1] = OSLUStringHash();
542 sval[2] = OSLUStringHash();
543 }
544
545 return true;
546 }
547
548 return false;
549}
550
551static bool set_attribute_float3_3(const float3 P[3], TypeDesc type, bool derivatives, void *val)
552{
553 if (type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
554 float *fval = (float *)val;
555
556 copy_v3_v3(fval, P[0]);
557 copy_v3_v3(fval + 3, P[1]);
558 copy_v3_v3(fval + 6, P[2]);
559
560 if (type.arraylen > 3) {
561 memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3));
562 }
563 if (derivatives) {
564 memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen);
565 }
566
567 return true;
568 }
569
570 return false;
571}
572
573static bool set_attribute_matrix(const Transform &tfm, const TypeDesc type, void *val)
574{
575 if (type == TypeMatrix) {
576 copy_matrix(*(OSL::Matrix44 *)val, tfm);
577 return true;
578 }
579
580 return false;
581}
582
583template<typename T>
585 ShaderData *sd,
586 const AttributeDescriptor &desc,
587 const TypeDesc &type,
588 bool derivatives,
589 void *val)
590{
592#ifdef __VOLUME__
593 if (primitive_is_volume_attribute(sd)) {
594 data.val = primitive_volume_attribute<T>(kg, sd, desc, true);
595 }
596 else
597#endif
598 {
599 data = primitive_surface_attribute<T>(kg, sd, desc, derivatives, derivatives);
600 }
601 return set_attribute(data, type, derivatives, val);
602}
603
605 ShaderData *sd,
606 const AttributeDescriptor &desc,
607 const TypeDesc &type,
608 bool derivatives,
609 void *val)
610{
611 if (desc.type == NODE_ATTR_FLOAT) {
612 return get_object_attribute_impl<float>(kg, sd, desc, type, derivatives, val);
613 }
614 if (desc.type == NODE_ATTR_FLOAT2) {
615 return get_object_attribute_impl<float2>(kg, sd, desc, type, derivatives, val);
616 }
617 if (desc.type == NODE_ATTR_FLOAT3) {
618 return get_object_attribute_impl<float3>(kg, sd, desc, type, derivatives, val);
619 }
620 if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
621 return get_object_attribute_impl<float4>(kg, sd, desc, type, derivatives, val);
622 }
623 if (desc.type == NODE_ATTR_MATRIX) {
624 const Transform tfm = primitive_attribute_matrix(kg, desc);
625 return set_attribute_matrix(tfm, type, val);
626 }
627 return false;
628}
629
631 ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
632{
633 ShaderData *sd = globals->sd;
634 const ThreadKernelGlobalsCPU *kg = globals->kg;
635 /* todo: turn this into hash table? */
636
637 /* Object Attributes */
638 if (name == u_object_location) {
639 const float3 f = object_location(kg, sd);
640 return set_attribute(f, type, derivatives, val);
641 }
642 if (name == u_object_color) {
643 const float3 f = object_color(kg, sd->object);
644 return set_attribute(f, type, derivatives, val);
645 }
646 if (name == u_object_alpha) {
647 const float f = object_alpha(kg, sd->object);
648 return set_attribute(f, type, derivatives, val);
649 }
650 if (name == u_object_index) {
651 const float f = object_pass_id(kg, sd->object);
652 return set_attribute(f, type, derivatives, val);
653 }
654 if (name == u_object_is_light) {
655 const float f = (sd->type & PRIMITIVE_LAMP) != 0;
656 return set_attribute(f, type, derivatives, val);
657 }
659 const float3 f = object_dupli_generated(kg, sd->object);
660 return set_attribute(f, type, derivatives, val);
661 }
662 if (name == u_geom_dupli_uv) {
663 const float3 f = object_dupli_uv(kg, sd->object);
664 return set_attribute(f, type, derivatives, val);
665 }
666 if (name == u_material_index) {
667 const float f = shader_pass_id(kg, sd);
668 return set_attribute(f, type, derivatives, val);
669 }
670 if (name == u_object_random) {
671 const float f = object_random_number(kg, sd->object);
672 return set_attribute(f, type, derivatives, val);
673 }
674
675 /* Particle Attributes */
676 if (name == u_particle_index) {
677 const int particle_id = object_particle_id(kg, sd->object);
678 const float f = particle_index(kg, particle_id);
679 return set_attribute(f, type, derivatives, val);
680 }
681 if (name == u_particle_random) {
682 const int particle_id = object_particle_id(kg, sd->object);
683 const float f = hash_uint2_to_float(particle_index(kg, particle_id), 0);
684 return set_attribute(f, type, derivatives, val);
685 }
686 if (name == u_particle_age) {
687 const int particle_id = object_particle_id(kg, sd->object);
688 const float f = particle_age(kg, particle_id);
689 return set_attribute(f, type, derivatives, val);
690 }
691 if (name == u_particle_lifetime) {
692 const int particle_id = object_particle_id(kg, sd->object);
693 const float f = particle_lifetime(kg, particle_id);
694 return set_attribute(f, type, derivatives, val);
695 }
696 if (name == u_particle_location) {
697 const int particle_id = object_particle_id(kg, sd->object);
698 const float3 f = particle_location(kg, particle_id);
699 return set_attribute(f, type, derivatives, val);
700 }
701#if 0 /* unsupported */
702 if (name == u_particle_rotation) {
703 int particle_id = object_particle_id(kg, sd->object);
704 float4 f = particle_rotation(kg, particle_id);
705 return set_attribute(f, type, derivatives, val);
706 }
707#endif
708 if (name == u_particle_size) {
709 const int particle_id = object_particle_id(kg, sd->object);
710 const float f = particle_size(kg, particle_id);
711 return set_attribute(f, type, derivatives, val);
712 }
713 if (name == u_particle_velocity) {
714 const int particle_id = object_particle_id(kg, sd->object);
715 const float3 f = particle_velocity(kg, particle_id);
716 return set_attribute(f, type, derivatives, val);
717 }
719 const int particle_id = object_particle_id(kg, sd->object);
720 const float3 f = particle_angular_velocity(kg, particle_id);
721 return set_attribute(f, type, derivatives, val);
722 }
723
724 /* Geometry Attributes */
726 return set_attribute(3, type, derivatives, val);
727 }
729 sd->type & PRIMITIVE_TRIANGLE)
730 {
731 float3 P[3];
732
733 if (sd->type & PRIMITIVE_MOTION) {
734 motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
735 }
736 else {
737 triangle_vertices(kg, sd->prim, P);
738 }
739
740 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
741 object_position_transform(kg, sd, &P[0]);
742 object_position_transform(kg, sd, &P[1]);
743 object_position_transform(kg, sd, &P[2]);
744 }
745
746 return set_attribute_float3_3(P, type, derivatives, val);
747 }
748 if (name == u_geom_name) {
749 const ustring object_name = kg->osl.globals->object_names[sd->object];
750 return set_attribute(object_name, type, derivatives, val);
751 }
752 if (name == u_is_smooth) {
753 const float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
754 return set_attribute(f, type, derivatives, val);
755 }
756#ifdef __HAIR__
757 /* Hair Attributes */
758 if (name == u_is_curve) {
759 const float f = (sd->type & PRIMITIVE_CURVE) != 0;
760 return set_attribute(f, type, derivatives, val);
761 }
762 if (name == u_curve_thickness) {
763 const float f = curve_thickness(kg, sd);
764 return set_attribute(f, type, derivatives, val);
765 }
767 const float3 f = curve_tangent_normal(sd);
768 return set_attribute(f, type, derivatives, val);
769 }
770 if (name == u_curve_random) {
771 const float f = curve_random(kg, sd);
772 return set_attribute(f, type, derivatives, val);
773 }
774#endif
775#ifdef __POINTCLOUD__
776 /* point attributes */
777 if (name == u_is_point) {
778 const float f = (sd->type & PRIMITIVE_POINT) != 0;
779 return set_attribute(f, type, derivatives, val);
780 }
781 if (name == u_point_radius) {
782 const float f = point_radius(kg, sd);
783 return set_attribute(f, type, derivatives, val);
784 }
785 if (name == u_point_position) {
786 const float3 f = point_position(kg, sd);
787 return set_attribute(f, type, derivatives, val);
788 }
789 if (name == u_point_random) {
790 const float f = point_random(kg, sd);
791 return set_attribute(f, type, derivatives, val);
792 }
793#endif
794 if (name == u_normal_map_normal) {
795 if (sd->type & PRIMITIVE_TRIANGLE) {
797 kg, sd->object, sd->prim, ATTR_STD_NORMAL_UNDISPLACED);
798 if (desc.offset != ATTR_STD_NOT_FOUND) {
799 return get_object_attribute(kg, sd, desc, type, derivatives, val);
800 }
801 const float3 f = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
802 return set_attribute(f, type, derivatives, val);
803 }
804 return false;
805 }
806 if (name == u_bump_map_normal) {
807 dual3 f;
808 if (!attribute_bump_map_normal(kg, sd, f)) {
809 return false;
810 }
811 return set_attribute(f, type, derivatives, val);
812 }
813 return get_background_attribute(globals, name, type, derivatives, val);
814}
815
817 ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
818{
819 ShaderData *sd = globals->sd;
820 const ThreadKernelGlobalsCPU *kg = globals->kg;
821 const IntegratorStateCPU *state = globals->path_state;
822 const IntegratorShadowStateCPU *shadow_state = globals->shadow_path_state;
823 if (name == u_path_ray_length) {
824 /* Ray Length */
825 const float f = sd->ray_length;
826 return set_attribute(f, type, derivatives, val);
827 }
828
829#define READ_PATH_STATE(elem) \
830 ((state != nullptr) ? state->path.elem : \
831 (shadow_state != nullptr) ? shadow_state->shadow_path.elem : \
832 0)
833
834 if (name == u_path_ray_depth) {
835 /* Ray Depth */
836 int f = READ_PATH_STATE(bounce);
837
838 /* Read bounce from different locations depending on if this is a shadow path. For background,
839 * light emission and shadow evaluation from a surface or volume we are effectively one bounce
840 * further. */
841 if (globals->raytype & (PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
842 f += 1;
843 }
844
845 return set_attribute(f, type, derivatives, val);
846 }
847 if (name == u_path_diffuse_depth) {
848 /* Diffuse Ray Depth */
849 const int f = READ_PATH_STATE(diffuse_bounce);
850 return set_attribute(f, type, derivatives, val);
851 }
852 if (name == u_path_glossy_depth) {
853 /* Glossy Ray Depth */
854 const int f = READ_PATH_STATE(glossy_bounce);
855 return set_attribute(f, type, derivatives, val);
856 }
858 /* Transmission Ray Depth */
859 const int f = READ_PATH_STATE(transmission_bounce);
860 return set_attribute(f, type, derivatives, val);
861 }
863 /* Transparent Ray Depth */
864 const int f = READ_PATH_STATE(transparent_bounce);
865 return set_attribute(f, type, derivatives, val);
866 }
867 if (name == u_path_portal_depth) {
868 /* Portal Ray Depth */
869 const int f = READ_PATH_STATE(portal_bounce);
870 return set_attribute(f, type, derivatives, val);
871 }
872#undef READ_PATH_STATE
873
874 if (name == u_ndc) {
875 /* NDC coordinates with special exception for orthographic projection. */
876 dual3 ndc;
877
878 if ((globals->raytype & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
880 {
881 ndc.val = camera_world_to_ndc(kg, sd, sd->ray_P);
882 }
883 else {
884 ndc.val = camera_world_to_ndc(kg, sd, sd->P);
885
886 if (derivatives) {
887 const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
888 ndc.dx = camera_world_to_ndc(kg, sd, sd->P + dP.dx) - ndc.val;
889 ndc.dy = camera_world_to_ndc(kg, sd, sd->P + dP.dy) - ndc.val;
890 }
891 }
892
893 return set_attribute(ndc, type, derivatives, val);
894 }
895
896 return false;
897}
898
900 ShaderGlobals *globals, OSLUStringHash name, TypeDesc type, bool derivatives, void *val)
901{
902 const ThreadKernelGlobalsCPU *kg = globals->kg;
903 if (name == u_sensor_size) {
904 const float2 sensor = make_float2(kernel_data.cam.sensorwidth, kernel_data.cam.sensorheight);
905 return set_attribute(sensor, type, derivatives, val);
906 }
907 if (name == u_image_resolution) {
908 const float2 image = make_float2(kernel_data.cam.width, kernel_data.cam.height);
909 return set_attribute(image, type, derivatives, val);
910 }
912 return set_attribute(1.0f / kernel_data.cam.inv_aperture_ratio, type, derivatives, val);
913 }
914 if (name == u_aperture_size) {
915 return set_attribute(kernel_data.cam.aperturesize, type, derivatives, val);
916 }
917 if (name == u_aperture_position) {
918 /* The random numbers for aperture sampling are packed into N. */
919 const float2 rand_lens = make_float2(globals->N.x, globals->N.y);
920 const float2 pos = camera_sample_aperture(&kernel_data.cam, rand_lens);
921 return set_attribute(pos * kernel_data.cam.aperturesize, type, derivatives, val);
922 }
923 if (name == u_focal_distance) {
924 return set_attribute(kernel_data.cam.focaldistance, type, derivatives, val);
925 }
926 return false;
927}
928
929bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
930 bool derivatives,
931 OSLUStringHash object_name,
932 const TypeDesc type,
934 void *val)
935{
936 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
937 if (globals == nullptr) {
938 return false;
939 }
940
941 ShaderData *sd = globals->sd;
942 const ThreadKernelGlobalsCPU *kg = globals->kg;
943 if (sd == nullptr) {
944 /* Camera shader. */
945 return get_camera_attribute(globals, name, type, derivatives, val);
946 }
947
948 /* lookup of attribute on another object */
949 int object;
950 if (object_name != u_empty) {
951 const OSLGlobals::ObjectNameMap::iterator it = kg->osl.globals->object_name_map.find(
952 object_name);
953
954 if (it == kg->osl.globals->object_name_map.end()) {
955 return false;
956 }
957
958 object = it->second;
959 }
960 else {
961 object = sd->object;
962 }
963
964 /* find attribute on object */
965 const AttributeDescriptor desc = find_attribute(kg, object, sd->prim, name.hash());
966 if (desc.offset != ATTR_STD_NOT_FOUND) {
967 return get_object_attribute(kg, sd, desc, type, derivatives, val);
968 }
969
970 /* not found in attribute, check standard object info */
971 return get_object_standard_attribute(globals, name, type, derivatives, val);
972}
973
974bool OSLRenderServices::get_userdata(bool /*derivatives*/,
975 OSLUStringHash /* name*/,
976 const TypeDesc /* type*/,
977 OSL::ShaderGlobals * /*sg*/,
978 void * /*val*/)
979{
980 return false; /* disabled by lockgeom */
981}
982
983OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
984 OSLUStringHash filename, OSL::ShadingContext *context, const OSL::TextureOpt *opt)
985{
986 return get_texture_handle(to_ustring(filename), context, opt);
987}
988
989OSL::TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(
990 OSL::ustring filename, OSL::ShadingContext * /*context*/, const OSL::TextureOpt * /*options*/)
991{
992 OSLTextureHandleMap::iterator it = textures.find(filename);
993
994 if (device_type_ == DEVICE_CPU) {
995 /* For non-OIIO textures, just return a pointer to our own OSLTextureHandle. */
996 if (it != textures.end()) {
997 if (it->second.type != OSLTextureHandle::OIIO) {
998 return (OSL::TextureSystem::TextureHandle *)(&it->second);
999 }
1000 }
1001
1002 /* Get handle from OpenImageIO. */
1003 OSL::TextureSystem *ts = m_texturesys;
1004 OSL::TextureSystem::TextureHandle *handle = ts->get_texture_handle(to_ustring(filename));
1005 if (handle == nullptr) {
1006 return nullptr;
1007 }
1008
1009 /* Insert new OSLTextureHandle if needed. */
1010 if (it == textures.end()) {
1012 it = textures.find(filename);
1013 }
1014
1015 /* Assign OIIO texture handle and return.
1016 * OIIO::unordered_map_concurrent always returns a const handle even if the underlying
1017 * std::unordered_map supports updating values just fine. */
1018 const_cast<OSLTextureHandle &>(it->second).oiio_handle = handle;
1019 return (OSL::TextureSystem::TextureHandle *)(&it->second);
1020 }
1021
1022 /* Construct GPU texture handle for existing textures. */
1023 if (it != textures.end()) {
1024 switch (it->second.type) {
1026 return nullptr;
1028 if (!it->second.handle.empty() && it->second.handle.get_manager() != image_manager) {
1029 it.clear();
1030 break;
1031 }
1032 return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
1033 it->second.svm_slots[0].y);
1035 if (!it->second.handle.empty() && it->second.handle.get_manager() != image_manager) {
1036 it.clear();
1037 break;
1038 }
1039 return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_IES |
1040 it->second.svm_slots[0].y);
1042 return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(
1045 return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(
1047 }
1048 }
1049
1050 if (!image_manager) {
1051 return nullptr;
1052 }
1053
1054 /* Load new textures using SVM image manager. */
1055 const ImageHandle handle = image_manager->add_image(filename.string(), ImageParams());
1056 if (handle.empty()) {
1057 return nullptr;
1058 }
1059
1060 if (!textures.insert(filename, OSLTextureHandle(handle))) {
1061 return nullptr;
1062 }
1063
1064 return reinterpret_cast<OSL::TextureSystem::TextureHandle *>(OSL_TEXTURE_HANDLE_TYPE_SVM |
1065 handle.svm_slot());
1066}
1067
1068bool OSLRenderServices::good(OSL::TextureSystem::TextureHandle *texture_handle)
1069{
1070 OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1071
1072 if (handle->oiio_handle) {
1073 OSL::TextureSystem *ts = m_texturesys;
1074 return ts->good(handle->oiio_handle);
1075 }
1076 return true;
1077}
1078
1080 TextureHandle *texture_handle,
1081 TexturePerthread *texture_thread_info,
1082 OSL::TextureOpt &options,
1083 OSL::ShaderGlobals *sg,
1084 float s,
1085 float t,
1086 const float dsdx,
1087 const float dtdx,
1088 const float dsdy,
1089 const float dtdy,
1090 const int nchannels,
1091 float *result,
1092 float *dresultds,
1093 float *dresultdt,
1094 OSLUStringHash * /*errormessage*/)
1095{
1096 OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1097 const OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
1098 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
1099 ShaderData *sd = globals->sd;
1100 const ThreadKernelGlobalsCPU *kernel_globals = globals->kg;
1101 const IntegratorStateCPU *state = globals->path_state;
1102 bool status = false;
1103
1104 switch (texture_type) {
1106#ifdef __SHADER_RAYTRACE__
1107 /* Bevel shader hack. */
1108 if (nchannels >= 3 && state != nullptr) {
1109 const int num_samples = (int)s;
1110 const float radius = t;
1111 const float3 N = svm_bevel(kernel_globals, state, sd, radius, num_samples);
1112 result[0] = N.x;
1113 result[1] = N.y;
1114 result[2] = N.z;
1115 status = true;
1116 }
1117#endif
1118 break;
1119 }
1120 case OSLTextureHandle::AO: {
1121#ifdef __SHADER_RAYTRACE__
1122 /* AO shader hack. */
1123 if (state != nullptr) {
1124 const int num_samples = (int)s;
1125 const float radius = t;
1126 const float3 N = make_float3(dsdx, dtdx, dsdy);
1127 int flags = 0;
1128 if ((int)dtdy) {
1129 flags |= NODE_AO_INSIDE;
1130 }
1131 if ((int)options.sblur) {
1132 flags |= NODE_AO_ONLY_LOCAL;
1133 }
1134 if ((int)options.tblur) {
1135 flags |= NODE_AO_GLOBAL_RADIUS;
1136 }
1137 result[0] = svm_ao(kernel_globals, state, sd, N, radius, num_samples, flags);
1138 status = true;
1139 }
1140#endif
1141 break;
1142 }
1143 case OSLTextureHandle::SVM: {
1144 int id = -1;
1145 if (handle->svm_slots[0].w == -1) {
1146 /* Packed single texture. */
1147 id = handle->svm_slots[0].y;
1148 }
1149 else {
1150 /* Packed tiled texture. */
1151 const int tx = (int)s;
1152 const int ty = (int)t;
1153 const int tile = 1001 + 10 * ty + tx;
1154 for (const int4 &tile_node : handle->svm_slots) {
1155 if (tile_node.x == tile) {
1156 id = tile_node.y;
1157 break;
1158 }
1159 if (tile_node.z == tile) {
1160 id = tile_node.w;
1161 break;
1162 }
1163 }
1164 s -= tx;
1165 t -= ty;
1166 }
1167
1168 float4 rgba;
1169 if (id == -1) {
1170 rgba = make_float4(
1172 }
1173 else {
1174 rgba = kernel_tex_image_interp(kernel_globals, id, s, 1.0f - t);
1175 }
1176
1177 result[0] = rgba[0];
1178 if (nchannels > 1) {
1179 result[1] = rgba[1];
1180 }
1181 if (nchannels > 2) {
1182 result[2] = rgba[2];
1183 }
1184 if (nchannels > 3) {
1185 result[3] = rgba[3];
1186 }
1187 status = true;
1188 break;
1189 }
1190 case OSLTextureHandle::IES: {
1191 /* IES light. */
1192 result[0] = kernel_ies_interp(kernel_globals, handle->svm_slots[0].y, s, t);
1193 status = true;
1194 break;
1195 }
1197 /* OpenImageIO texture cache. */
1198 OSL::TextureSystem *ts = m_texturesys;
1199
1200 if (handle && handle->oiio_handle) {
1201 if (texture_thread_info == nullptr) {
1202 texture_thread_info = kernel_globals->osl.oiio_thread_info;
1203 }
1204
1205 status = ts->texture(handle->oiio_handle,
1206 texture_thread_info,
1207 options,
1208 s,
1209 t,
1210 dsdx,
1211 dtdx,
1212 dsdy,
1213 dtdy,
1214 nchannels,
1215 result,
1216 dresultds,
1217 dresultdt);
1218 }
1219 else {
1220 status = ts->texture(to_ustring(filename),
1221 options,
1222 s,
1223 t,
1224 dsdx,
1225 dtdx,
1226 dsdy,
1227 dtdy,
1228 nchannels,
1229 result,
1230 dresultds,
1231 dresultdt);
1232 }
1233
1234 if (!status) {
1235 /* This might be slow, but prevents error messages leak and
1236 * other nasty stuff happening. */
1237 ts->geterror();
1238 }
1239 else if (handle && handle->processor) {
1241 }
1242 break;
1243 }
1244 }
1245
1246 if (!status) {
1247 if (nchannels == 3 || nchannels == 4) {
1248 result[0] = 1.0f;
1249 result[1] = 0.0f;
1250 result[2] = 1.0f;
1251
1252 if (nchannels == 4) {
1253 result[3] = 1.0f;
1254 }
1255 }
1256 }
1257
1258 return status;
1259}
1260
1262 TextureHandle *texture_handle,
1263 TexturePerthread *texture_thread_info,
1264 OSL::TextureOpt &options,
1265 OSL::ShaderGlobals *sg,
1266 const OSL::Vec3 &P,
1267 const OSL::Vec3 &dPdx,
1268 const OSL::Vec3 &dPdy,
1269 const OSL::Vec3 &dPdz,
1270 const int nchannels,
1271 float *result,
1272 float *dresultds,
1273 float *dresultdt,
1274 float *dresultdr,
1275 OSLUStringHash * /*errormessage*/)
1276{
1277 OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1278 const OSLTextureHandle::Type texture_type = (handle) ? handle->type : OSLTextureHandle::OIIO;
1279 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
1280 const ThreadKernelGlobalsCPU *kernel_globals = globals->kg;
1281 bool status = false;
1282
1283 switch (texture_type) {
1284 case OSLTextureHandle::SVM: {
1285 /* Packed texture. */
1286 const int slot = handle->svm_slots[0].y;
1287 const float3 P_float3 = make_float3(P.x, P.y, P.z);
1288 float4 rgba = kernel_tex_image_interp_3d(
1289 kernel_globals, globals->sd, slot, P_float3, INTERPOLATION_NONE, false);
1290
1291 result[0] = rgba[0];
1292 if (nchannels > 1) {
1293 result[1] = rgba[1];
1294 }
1295 if (nchannels > 2) {
1296 result[2] = rgba[2];
1297 }
1298 if (nchannels > 3) {
1299 result[3] = rgba[3];
1300 }
1301 status = true;
1302 break;
1303 }
1305 /* OpenImageIO texture cache. */
1306 OSL::TextureSystem *ts = m_texturesys;
1307
1308 if (handle && handle->oiio_handle) {
1309 if (texture_thread_info == nullptr) {
1310 texture_thread_info = kernel_globals->osl.oiio_thread_info;
1311 }
1312
1313 status = ts->texture3d(handle->oiio_handle,
1314 texture_thread_info,
1315 options,
1316 P,
1317 dPdx,
1318 dPdy,
1319 dPdz,
1320 nchannels,
1321 result,
1322 dresultds,
1323 dresultdt,
1324 dresultdr);
1325 }
1326 else {
1327 status = ts->texture3d(to_ustring(filename),
1328 options,
1329 P,
1330 dPdx,
1331 dPdy,
1332 dPdz,
1333 nchannels,
1334 result,
1335 dresultds,
1336 dresultdt,
1337 dresultdr);
1338 }
1339
1340 if (!status) {
1341 /* This might be slow, but prevents error messages leak and
1342 * other nasty stuff happening. */
1343 ts->geterror();
1344 }
1345 else if (handle && handle->processor) {
1347 }
1348 break;
1349 }
1353 status = false;
1354 break;
1355 }
1356 }
1357
1358 if (!status) {
1359 if (nchannels == 3 || nchannels == 4) {
1360 result[0] = 1.0f;
1361 result[1] = 0.0f;
1362 result[2] = 1.0f;
1363
1364 if (nchannels == 4) {
1365 result[3] = 1.0f;
1366 }
1367 }
1368 }
1369
1370 return status;
1371}
1372
1374 TextureHandle *texture_handle,
1375 TexturePerthread *thread_info,
1376 OSL::TextureOpt &options,
1377 OSL::ShaderGlobals *sg,
1378 const OSL::Vec3 &R,
1379 const OSL::Vec3 &dRdx,
1380 const OSL::Vec3 &dRdy,
1381 const int nchannels,
1382 float *result,
1383 float *dresultds,
1384 float *dresultdt,
1385 OSLUStringHash * /*errormessage*/)
1386{
1387 OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1388 OSL::TextureSystem *ts = m_texturesys;
1389 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
1390 bool status = false;
1391
1392 if (handle && handle->oiio_handle) {
1393 if (thread_info == nullptr) {
1394 thread_info = globals->kg->osl.oiio_thread_info;
1395 }
1396
1397 status = ts->environment(handle->oiio_handle,
1398 thread_info,
1399 options,
1400 R,
1401 dRdx,
1402 dRdy,
1403 nchannels,
1404 result,
1405 dresultds,
1406 dresultdt);
1407 }
1408 else {
1409 status = ts->environment(
1410 to_ustring(filename), options, R, dRdx, dRdy, nchannels, result, dresultds, dresultdt);
1411 }
1412
1413 if (!status) {
1414 if (nchannels == 3 || nchannels == 4) {
1415 result[0] = 1.0f;
1416 result[1] = 0.0f;
1417 result[2] = 1.0f;
1418
1419 if (nchannels == 4) {
1420 result[3] = 1.0f;
1421 }
1422 }
1423 }
1424 else if (handle && handle->processor) {
1426 }
1427
1428 return status;
1429}
1430
1432 TextureHandle *texture_handle,
1433 TexturePerthread *texture_thread_info,
1434 OSL::ShaderGlobals * /*sg*/,
1435 const int subimage,
1436 OSLUStringHash dataname,
1437 const TypeDesc datatype,
1438 void *data,
1439 OSLUStringHash * /*errormessage*/)
1440{
1441 OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
1442 OSL::TextureSystem *ts = m_texturesys;
1443
1444 if (handle) {
1445 /* No texture info for other texture types. */
1446 if (handle->type != OSLTextureHandle::OIIO) {
1447 return false;
1448 }
1449
1450 if (handle->oiio_handle) {
1451 /* Get texture info from OpenImageIO. */
1452 return ts->get_texture_info(handle->oiio_handle,
1453 texture_thread_info,
1454 subimage,
1455 to_ustring(dataname),
1456 datatype,
1457 data);
1458 }
1459 }
1460
1461 /* Get texture info from OpenImageIO, slower using filename. */
1462 return ts->get_texture_info(
1463 to_ustring(filename), subimage, to_ustring(dataname), datatype, data);
1464}
1465
1466int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals * /*sg*/,
1467 OSLUStringHash /*filename*/,
1468 const OSL::Vec3 & /*center*/,
1469 const float /*radius*/,
1470 const int /*max_points*/,
1471 bool /*sort*/,
1472#if OSL_LIBRARY_VERSION_CODE >= 11400
1473 int * /*indices*/,
1474#else
1475 size_t * /*out_indices*/,
1476#endif
1477 float * /*out_distances*/,
1478 const int /*derivs_offset*/)
1479{
1480 return 0;
1481}
1482
1483int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals * /*sg*/
1484 ,
1485 OSLUStringHash /*filename*/,
1486#if OSL_LIBRARY_VERSION_CODE >= 11400
1487 const int * /*indices*/,
1488#else
1489 size_t * /*indices*/,
1490#endif
1491 const int /*count*/,
1492 OSLUStringHash /*attr_name*/,
1493 const TypeDesc /*attr_type*/,
1494 void * /*out_data*/)
1495{
1496 return 0;
1497}
1498
1499bool OSLRenderServices::pointcloud_write(OSL::ShaderGlobals * /*sg*/,
1500 OSLUStringHash /*filename*/,
1501 const OSL::Vec3 & /*pos*/,
1502 const int /*nattribs*/,
1503 const OSLUStringRep * /*names*/,
1504 const TypeDesc * /*types*/,
1505 const void ** /*data*/)
1506{
1507 return false;
1508}
1509
1511 OSL::ShaderGlobals *sg,
1512 const OSL::Vec3 &P,
1513 const OSL::Vec3 &dPdx,
1514 const OSL::Vec3 &dPdy,
1515 const OSL::Vec3 &R,
1516 const OSL::Vec3 &dRdx,
1517 const OSL::Vec3 &dRdy)
1518{
1519 /* todo: options.shader support, maybe options.traceset */
1520 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
1521 ShaderData *sd = globals->sd;
1522 const ThreadKernelGlobalsCPU *kg = globals->kg;
1523
1524 if (sd == nullptr) {
1525 return false;
1526 }
1527
1528 /* setup ray */
1529 Ray ray;
1530
1531 ray.P = make_float3(P.x, P.y, P.z);
1532 ray.D = make_float3(R.x, R.y, R.z);
1533 ray.tmin = 0.0f;
1534 ray.tmax = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
1535 ray.time = sd->time;
1536 ray.self.object = OBJECT_NONE;
1537 ray.self.prim = PRIM_NONE;
1540
1541 if (options.mindist == 0.0f) {
1542 /* avoid self-intersections */
1543 if (ray.P == sd->P) {
1544 ray.self.object = sd->object;
1545 ray.self.prim = sd->prim;
1546 }
1547 }
1548 else {
1549 /* offset for minimum distance */
1550 ray.P += options.mindist * ray.D;
1551 }
1552
1553 /* ray differentials */
1554 differential3 dP;
1555 dP.dx = make_float3(dPdx.x, dPdx.y, dPdx.z);
1556 dP.dy = make_float3(dPdy.x, dPdy.y, dPdy.z);
1557 ray.dP = differential_make_compact(dP);
1558 differential3 dD;
1559 dD.dx = make_float3(dRdx.x, dRdx.y, dRdx.z);
1560 dD.dy = make_float3(dRdy.x, dRdy.y, dRdy.z);
1561 ray.dD = differential_make_compact(dD);
1562
1563 /* allocate trace data */
1564 OSLTraceData *tracedata = globals->tracedata;
1565 tracedata->ray = ray;
1566 tracedata->setup = false;
1567 tracedata->init = true;
1568 tracedata->hit = false;
1569
1570 /* Can't ray-trace from shaders like displacement, before BVH exists. */
1571 if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
1572 return false;
1573 }
1574
1575 /* Ray-trace, leaving out shadow opaque to avoid early exit. */
1577 tracedata->hit = scene_intersect(kg, &ray, visibility, &tracedata->isect);
1578 return tracedata->hit;
1579}
1580
1581bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg,
1582 OSLUStringHash source,
1584 const TypeDesc type,
1585 void *val,
1586 bool derivatives)
1587{
1588 ShaderGlobals *globals = reinterpret_cast<ShaderGlobals *>(sg);
1589 const ThreadKernelGlobalsCPU *kg = globals->kg;
1590 OSLTraceData *tracedata = globals->tracedata;
1591
1592 if (source == u_trace && tracedata->init) {
1593 if (name == u_hit) {
1594 return set_attribute<int>(tracedata->hit, type, derivatives, val);
1595 }
1596 if (tracedata->hit) {
1597 if (name == u_hitdist) {
1598 return set_attribute(tracedata->isect.t, type, derivatives, val);
1599 }
1600
1601 ShaderData *sd = &tracedata->sd;
1602
1603 if (!tracedata->setup) {
1604 /* lazy shader data setup */
1605 shader_setup_from_ray(kg, sd, &tracedata->ray, &tracedata->isect);
1606 tracedata->setup = true;
1607 }
1608
1609 if (name == u_N) {
1610 return set_attribute(sd->N, type, derivatives, val);
1611 }
1612 if (name == u_Ng) {
1613 return set_attribute(sd->Ng, type, derivatives, val);
1614 }
1615 if (name == u_P) {
1616 const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
1617 return set_attribute(dual3(sd->P, dP.dx, dP.dy), type, derivatives, val);
1618 }
1619 if (name == u_I) {
1620 const differential3 dI = differential_from_compact(sd->wi, sd->dI);
1621 return set_attribute(dual3(sd->wi, dI.dx, dI.dy), type, derivatives, val);
1622 }
1623 if (name == u_u) {
1624 return set_attribute(dual1(sd->u, sd->du.dx, sd->du.dy), type, derivatives, val);
1625 }
1626 if (name == u_v) {
1627 return set_attribute(dual1(sd->v, sd->dv.dx, sd->dv.dy), type, derivatives, val);
1628 }
1629
1630 return get_attribute(sg, derivatives, u_empty, type, name, val);
1631 }
1632 }
1633
1634 return false;
1635}
1636
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned int uint
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
static void to_scene_linear(ustring colorspace, T *pixels, const size_t num_pixels, bool is_rgba, bool compress_as_srgb, bool ignore_alpha)
bool empty() const
int svm_slot(const int slot_index=0) const
static ustring u_bump_map_normal
Definition services.h:276
static ustring u_path_transmission_depth
Definition services.h:311
static bool get_background_attribute(ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
Definition services.cpp:816
static ustring u_particle_location
Definition services.h:285
static ImageManager * image_manager
Definition services.h:340
static ustring u_object_alpha
Definition services.h:273
bool get_texture_info(OSLUStringHash filename, TextureHandle *texture_handle, TexturePerthread *texture_thread_info, OSL::ShaderGlobals *sg, const int subimage, OSLUStringHash dataname, const TypeDesc datatype, void *data, OSLUStringHash *errormessage) override
static ustring u_u
Definition services.h:320
static ustring u_sensor_size
Definition services.h:327
bool texture(OSLUStringHash filename, OSL::TextureSystem::TextureHandle *texture_handle, TexturePerthread *texture_thread_info, OSL::TextureOpt &options, OSL::ShaderGlobals *sg, const float s, const float t, const float dsdx, const float dtdx, const float dsdy, const float dtdy, const int nchannels, float *result, float *dresultds, float *dresultdt, OSLUStringHash *errormessage) override
bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) override
Definition services.cpp:193
static ustring u_raster
Definition services.h:269
static ustring u_empty
Definition services.h:322
static ustring u_curve_thickness
Definition services.h:297
int pointcloud_search(OSL::ShaderGlobals *sg, OSLUStringHash filename, const OSL::Vec3 &center, const float radius, const int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) override
static ustring u_ndc
Definition services.h:270
static ustring u_particle_index
Definition services.h:281
static ustring u_point_position
Definition services.h:302
static ustring u_point_radius
Definition services.h:303
static ustring u_curve_tangent_normal
Definition services.h:299
~OSLRenderServices() override
Definition services.cpp:135
int supports(string_view feature) const override
Definition services.cpp:142
static ustring u_image_resolution
Definition services.h:328
static ustring u_path_diffuse_depth
Definition services.h:308
static bool get_camera_attribute(ShaderGlobals *globals, OSLUStringHash name, TypeDesc type, bool derivatives, void *val)
Definition services.cpp:899
static ustring u_normal_map_normal
Definition services.h:305
static ustring u_index
Definition services.h:265
bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) override
Definition services.cpp:155
static ustring u_curve_length
Definition services.h:298
static ustring u_aperture_aspect_ratio
Definition services.h:329
static ustring u_hit
Definition services.h:314
static ustring u_material_index
Definition services.h:279
static ustring u_path_ray_depth
Definition services.h:307
static ustring u_point_random
Definition services.h:304
static ustring u_is_smooth
Definition services.h:295
static ustring u_object_location
Definition services.h:271
static ustring u_curve_random
Definition services.h:300
static ustring u_particle_rotation
Definition services.h:286
static ustring u_focal_distance
Definition services.h:332
static ustring u_particle_velocity
Definition services.h:288
static ustring u_particle_angular_velocity
Definition services.h:289
static ustring u_N
Definition services.h:316
int pointcloud_get(OSL::ShaderGlobals *sg, OSLUStringHash filename, size_t *indices, const int count, OSLUStringHash attr_name, const TypeDesc attr_type, void *out_data) override
static ustring u_path_glossy_depth
Definition services.h:309
static ustring u_hitdist
Definition services.h:315
static bool get_object_standard_attribute(ShaderGlobals *globals, OSLUStringHash name, const TypeDesc type, bool derivatives, void *val)
Definition services.cpp:630
static ustring u_geom_dupli_uv
Definition services.h:278
static ustring u_aperture_size
Definition services.h:330
static ustring u_I
Definition services.h:319
static ustring u_geom_undisplaced
Definition services.h:294
OSLTextureHandleMap textures
Definition services.h:338
static ustring u_geom_numpolyvertices
Definition services.h:290
static ustring u_v
Definition services.h:321
static ustring u_world
Definition services.h:266
static ustring u_object_random
Definition services.h:280
static ustring u_path_ray_length
Definition services.h:306
static ustring u_path_portal_depth
Definition services.h:312
static ustring u_screen
Definition services.h:268
static ustring u_object_is_light
Definition services.h:275
static ustring u_particle_random
Definition services.h:282
static ustring u_camera
Definition services.h:267
static ustring u_particle_age
Definition services.h:283
static ustring u_P
Definition services.h:318
bool pointcloud_write(OSL::ShaderGlobals *sg, OSLUStringHash filename, const OSL::Vec3 &pos, const int nattribs, const OSLUStringRep *names, const TypeDesc *types, const void **data) override
bool environment(OSLUStringHash filename, TextureHandle *texture_handle, TexturePerthread *texture_thread_info, OSL::TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &R, const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, const int nchannels, float *result, float *dresultds, float *dresultdt, OSLUStringHash *errormessage) override
bool get_array_attribute(OSL::ShaderGlobals *sg, bool derivatives, OSLUStringHash object, const TypeDesc type, OSLUStringHash name, const int index, void *val) override
Definition services.cpp:401
static ustring u_object_index
Definition services.h:274
bool get_attribute(OSL::ShaderGlobals *sg, bool derivatives, OSLUStringHash object, const TypeDesc type, OSLUStringHash name, void *val) override
Definition services.cpp:929
static ustring u_is_point
Definition services.h:301
static ustring u_path_transparent_depth
Definition services.h:310
bool get_userdata(bool derivatives, OSLUStringHash name, const TypeDesc type, OSL::ShaderGlobals *sg, void *val) override
Definition services.cpp:974
bool trace(TraceOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &P, const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, const OSL::Vec3 &R, const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) override
static ustring u_particle_lifetime
Definition services.h:284
static ustring u_is_curve
Definition services.h:296
static ustring u_object_color
Definition services.h:272
static ustring u_distance
Definition services.h:264
static ustring u_aperture_position
Definition services.h:331
static ustring u_Ng
Definition services.h:317
static ustring u_trace
Definition services.h:313
static ustring u_geom_trianglevertices
Definition services.h:291
bool texture3d(OSLUStringHash filename, TextureHandle *texture_handle, TexturePerthread *texture_thread_info, OSL::TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &P, const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, const OSL::Vec3 &dPdz, const int nchannels, float *result, float *dresultds, float *dresultdt, float *dresultdr, OSLUStringHash *errormessage) override
static ustring u_geom_polyvertices
Definition services.h:292
bool getmessage(OSL::ShaderGlobals *sg, OSLUStringHash source, OSLUStringHash name, const TypeDesc type, void *val, bool derivatives) override
static ustring u_particle_size
Definition services.h:287
OSL::TextureSystem::TextureHandle * get_texture_handle(OSL::ustring filename, OSL::ShadingContext *context, const OSL::TextureOpt *options) override
Definition services.cpp:989
static ustring u_geom_dupli_generated
Definition services.h:277
OSLRenderServices(OSL::TextureSystem *texture_system, const int device_type)
Definition services.cpp:130
bool good(OSL::TextureSystem::TextureHandle *texture_handle) override
static ustring u_geom_name
Definition services.h:293
ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, const int id, const float x, float y)
ccl_device_forceinline float3 dPdx(const ccl_private ShaderData *sd)
ccl_device_forceinline float3 dPdy(const ccl_private ShaderData *sd)
ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform a)
CCL_NAMESPACE_BEGIN struct Options options
#define kernel_data
#define PRIM_NONE
#define OBJECT_NONE
#define ccl_device_inline
#define ccl_device_template_spec
#define CCL_NAMESPACE_END
@ DEVICE_CPU
@ DEVICE_OPTIX
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float differential_make_compact(const float dD)
ccl_device_forceinline differential3 differential_from_compact(const float3 D, const float dD)
#define str(s)
ccl_device_inline void triangle_vertices(KernelGlobals kg, const int prim, float3 P[3])
ccl_device_inline float3 triangle_smooth_normal_unnormalized(KernelGlobals kg, const ccl_private ShaderData *sd, const float3 Ng, const int prim, const float u, float v)
uint pos
ccl_device_inline float hash_uint2_to_float(const uint kx, const uint ky)
Definition hash.h:197
ccl_device_intersect bool scene_intersect(KernelGlobals kg, const ccl_private Ray *ray, const uint visibility, ccl_private Intersection *isect)
CCL_NAMESPACE_BEGIN ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, const float2 rand)
ccl_device_inline float3 camera_world_to_ndc(KernelGlobals kg, ccl_private ShaderData *sd, float3 P)
const ccl_global KernelWorkTile * tile
ccl_device Transform primitive_attribute_matrix(KernelGlobals kg, const AttributeDescriptor desc)
ccl_device_inline float3 object_dupli_uv(KernelGlobals kg, const int object)
ccl_device_inline int object_particle_id(KernelGlobals kg, const int object)
ccl_device int shader_pass_id(KernelGlobals kg, const ccl_private ShaderData *sd)
ccl_device_inline Transform object_get_inverse_transform(KernelGlobals kg, const ccl_private ShaderData *sd)
ccl_device float4 particle_rotation(KernelGlobals kg, const int particle)
ccl_device float3 particle_location(KernelGlobals kg, const int particle)
ccl_device float particle_lifetime(KernelGlobals kg, const int particle)
ccl_device float particle_age(KernelGlobals kg, const int particle)
ccl_device_inline uint particle_index(KernelGlobals kg, const int particle)
ccl_device_inline float3 object_color(KernelGlobals kg, const int object)
ccl_device_inline Transform object_get_transform(KernelGlobals kg, const ccl_private ShaderData *sd)
ccl_device float3 particle_velocity(KernelGlobals kg, const int particle)
ccl_device_inline float object_alpha(KernelGlobals kg, const int object)
ccl_device float3 particle_angular_velocity(KernelGlobals kg, const int particle)
ccl_device_inline float3 object_dupli_generated(KernelGlobals kg, const int object)
ccl_device_inline float object_pass_id(KernelGlobals kg, const int object)
ccl_device float particle_size(KernelGlobals kg, const int particle)
ccl_device_inline void object_position_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private T *P)
ccl_device_inline float3 object_location(KernelGlobals kg, const ccl_private ShaderData *sd)
ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg, const int object, const float time, ccl_private Transform *itfm)
ccl_device_inline float object_random_number(KernelGlobals kg, const int object)
#define OSL_TEXTURE_HANDLE_TYPE_SVM
#define OSL_TEXTURE_HANDLE_TYPE_IES
#define OSL_TEXTURE_HANDLE_TYPE_AO_OR_BEVEL
@ NODE_AO_INSIDE
@ NODE_AO_GLOBAL_RADIUS
@ NODE_AO_ONLY_LOCAL
@ NODE_ATTR_FLOAT
@ NODE_ATTR_FLOAT3
@ NODE_ATTR_RGBA
@ NODE_ATTR_FLOAT2
@ NODE_ATTR_FLOAT4
@ NODE_ATTR_MATRIX
@ PRIMITIVE_LAMP
@ PRIMITIVE_MOTION
@ PRIMITIVE_CURVE
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_POINT
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_NORMAL_UNDISPLACED
@ PATH_RAY_SHADOW
@ PATH_RAY_SHADOW_OPAQUE
@ PATH_RAY_EMISSION
@ PATH_RAY_ALL_VISIBILITY
@ PATH_RAY_CAMERA
@ SHADER_SMOOTH_NORMAL
@ SD_OBJECT_TRANSFORM_APPLIED
@ BVH_LAYOUT_NONE
@ CAMERA_ORTHOGRAPHIC
ccl_device_inline float kernel_ies_interp(KernelGlobals kg, const int slot, const float h_angle, const float v_angle)
#define LOG_INFO
Definition log.h:106
static ulong state[N]
#define N
#define T
#define R
ccl_device_inline void motion_triangle_vertices(KernelGlobals kg, const int object, const uint3 tri_vindex, const int numsteps, const int numverts, const int step, const float t, float3 verts[3])
float average(point a)
Definition node_math.h:144
OSL::ustringhash OSLUStringHash
Definition osl/compat.h:11
OSL::ustringrep OSLUStringRep
Definition osl/compat.h:15
static OSL::ustring to_ustring(OSLUStringHash h)
Definition osl/compat.h:18
static constexpr TypeDesc TypeFloatArray4(TypeDesc::FLOAT, TypeDesc::SCALAR, TypeDesc::NOSEMANTICS, 4)
CCL_NAMESPACE_BEGIN ccl_device_forceinline dual< T > primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
Definition primitive.h:32
const char * name
const int status
#define make_float2
#define make_float4
ccl_device_template_spec bool set_attribute(const dual1 v, TypeDesc type, bool derivatives, void *val)
Definition services.cpp:412
bool get_object_attribute_impl(const ThreadKernelGlobalsCPU *kg, ShaderData *sd, const AttributeDescriptor &desc, const TypeDesc &type, bool derivatives, void *val)
Definition services.cpp:584
static bool get_object_attribute(const ThreadKernelGlobalsCPU *kg, ShaderData *sd, const AttributeDescriptor &desc, const TypeDesc &type, bool derivatives, void *val)
Definition services.cpp:604
static bool set_attribute_float3_3(const float3 P[3], TypeDesc type, bool derivatives, void *val)
Definition services.cpp:551
#define READ_PATH_STATE(elem)
static bool set_attribute_matrix(const Transform &tfm, const TypeDesc type, void *val)
Definition services.cpp:573
static CCL_NAMESPACE_BEGIN void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
Definition services.cpp:48
ccl_device_inline void set_data_float3(const dual3 data, bool derivatives, ccl_private void *val)
ccl_device bool attribute_bump_map_normal(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private dual3 &f)
ccl_device_inline void set_data_float4(const dual4 data, bool derivatives, ccl_private void *val)
ccl_device_inline void set_data_float(const dual1 data, bool derivatives, ccl_private void *val)
ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const ccl_private Ray *ccl_restrict ray, const ccl_private Intersection *ccl_restrict isect)
Definition shader_data.h:39
#define FLT_MAX
Definition stdcycles.h:14
static bool find_attribute(const std::string &attributes, const char *search_attribute)
NodeAttributeType type
ColorSpaceProcessor * processor
Definition services.h:65
OSL::TextureSystem::TextureHandle * oiio_handle
Definition services.h:64
vector< int4 > svm_slots
Definition services.h:63
float tmax
float tmin
float dD
float3 P
float time
float dP
RaySelfPrimitives self
float3 D
ccl_private ShaderData * sd
const ThreadKernelGlobalsCPU * kg
ccl_private OSLTraceData * tracedata
const struct IntegratorStateCPU * path_state
const struct IntegratorShadowStateCPU * shadow_path_state
packed_float3 N
i
Definition text_draw.cc:230
@ INTERPOLATION_NONE
Definition texture.h:23
@ TEX_IMAGE_MISSING_G
Definition texture.h:15
@ TEX_IMAGE_MISSING_A
Definition texture.h:17
@ TEX_IMAGE_MISSING_R
Definition texture.h:14
@ TEX_IMAGE_MISSING_B
Definition texture.h:16
dual< float4 > dual4
Definition types_dual.h:59
dual< float3 > dual3
Definition types_dual.h:58
dual< float2 > dual2
Definition types_dual.h:57
dual< float > dual1
Definition types_dual.h:56