1 /*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 /* Object Primitive
16 *
17 * All mesh and curve primitives are part of an object. The same mesh and curves
18 * may be instanced multiple times by different objects.
19 *
20 * If the mesh is not instanced multiple times, the object will not be explicitly
21 * stored as a primitive in the BVH, rather the bare triangles are curved are
22 * directly primitives in the BVH with world space locations applied, and the object
23 * ID is looked up afterwards. */
24
25 CCL_NAMESPACE_BEGIN
26
27 /* Object attributes, for now a fixed size and contents */
28
29 enum ObjectTransform {
30 OBJECT_TRANSFORM = 0,
31 OBJECT_INVERSE_TRANSFORM = 1,
32 };
33
34 enum ObjectVectorTransform { OBJECT_PASS_MOTION_PRE = 0, OBJECT_PASS_MOTION_POST = 1 };
35
36 /* Object to world space transformation */
37
object_fetch_transform(KernelGlobals * kg,int object,enum ObjectTransform type)38 ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg,
39 int object,
40 enum ObjectTransform type)
41 {
42 if (type == OBJECT_INVERSE_TRANSFORM) {
43 return kernel_tex_fetch(__objects, object).itfm;
44 }
45 else {
46 return kernel_tex_fetch(__objects, object).tfm;
47 }
48 }
49
50 /* Lamp to world space transformation */
51
lamp_fetch_transform(KernelGlobals * kg,int lamp,bool inverse)52 ccl_device_inline Transform lamp_fetch_transform(KernelGlobals *kg, int lamp, bool inverse)
53 {
54 if (inverse) {
55 return kernel_tex_fetch(__lights, lamp).itfm;
56 }
57 else {
58 return kernel_tex_fetch(__lights, lamp).tfm;
59 }
60 }
61
62 /* Object to world space transformation for motion vectors */
63
object_fetch_motion_pass_transform(KernelGlobals * kg,int object,enum ObjectVectorTransform type)64 ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals *kg,
65 int object,
66 enum ObjectVectorTransform type)
67 {
68 int offset = object * OBJECT_MOTION_PASS_SIZE + (int)type;
69 return kernel_tex_fetch(__object_motion_pass, offset);
70 }
71
72 /* Motion blurred object transformations */
73
74 #ifdef __OBJECT_MOTION__
object_fetch_transform_motion(KernelGlobals * kg,int object,float time)75 ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg,
76 int object,
77 float time)
78 {
79 const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset;
80 const ccl_global DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset);
81 const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1;
82
83 Transform tfm;
84 transform_motion_array_interpolate(&tfm, motion, num_steps, time);
85
86 return tfm;
87 }
88
object_fetch_transform_motion_test(KernelGlobals * kg,int object,float time,Transform * itfm)89 ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg,
90 int object,
91 float time,
92 Transform *itfm)
93 {
94 int object_flag = kernel_tex_fetch(__object_flag, object);
95 if (object_flag & SD_OBJECT_MOTION) {
96 /* if we do motion blur */
97 Transform tfm = object_fetch_transform_motion(kg, object, time);
98
99 if (itfm)
100 *itfm = transform_quick_inverse(tfm);
101
102 return tfm;
103 }
104 else {
105 Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
106 if (itfm)
107 *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
108
109 return tfm;
110 }
111 }
112 #endif
113
114 /* Transform position from object to world space */
115
object_position_transform(KernelGlobals * kg,const ShaderData * sd,float3 * P)116 ccl_device_inline void object_position_transform(KernelGlobals *kg,
117 const ShaderData *sd,
118 float3 *P)
119 {
120 #ifdef __OBJECT_MOTION__
121 *P = transform_point_auto(&sd->ob_tfm, *P);
122 #else
123 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
124 *P = transform_point(&tfm, *P);
125 #endif
126 }
127
128 /* Transform position from world to object space */
129
object_inverse_position_transform(KernelGlobals * kg,const ShaderData * sd,float3 * P)130 ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg,
131 const ShaderData *sd,
132 float3 *P)
133 {
134 #ifdef __OBJECT_MOTION__
135 *P = transform_point_auto(&sd->ob_itfm, *P);
136 #else
137 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
138 *P = transform_point(&tfm, *P);
139 #endif
140 }
141
142 /* Transform normal from world to object space */
143
object_inverse_normal_transform(KernelGlobals * kg,const ShaderData * sd,float3 * N)144 ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg,
145 const ShaderData *sd,
146 float3 *N)
147 {
148 #ifdef __OBJECT_MOTION__
149 if ((sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP)) {
150 *N = normalize(transform_direction_transposed_auto(&sd->ob_tfm, *N));
151 }
152 #else
153 if (sd->object != OBJECT_NONE) {
154 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
155 *N = normalize(transform_direction_transposed(&tfm, *N));
156 }
157 else if (sd->type == PRIMITIVE_LAMP) {
158 Transform tfm = lamp_fetch_transform(kg, sd->lamp, false);
159 *N = normalize(transform_direction_transposed(&tfm, *N));
160 }
161 #endif
162 }
163
164 /* Transform normal from object to world space */
165
object_normal_transform(KernelGlobals * kg,const ShaderData * sd,float3 * N)166 ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
167 {
168 #ifdef __OBJECT_MOTION__
169 *N = normalize(transform_direction_transposed_auto(&sd->ob_itfm, *N));
170 #else
171 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
172 *N = normalize(transform_direction_transposed(&tfm, *N));
173 #endif
174 }
175
176 /* Transform direction vector from object to world space */
177
object_dir_transform(KernelGlobals * kg,const ShaderData * sd,float3 * D)178 ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
179 {
180 #ifdef __OBJECT_MOTION__
181 *D = transform_direction_auto(&sd->ob_tfm, *D);
182 #else
183 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
184 *D = transform_direction(&tfm, *D);
185 #endif
186 }
187
188 /* Transform direction vector from world to object space */
189
object_inverse_dir_transform(KernelGlobals * kg,const ShaderData * sd,float3 * D)190 ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg,
191 const ShaderData *sd,
192 float3 *D)
193 {
194 #ifdef __OBJECT_MOTION__
195 *D = transform_direction_auto(&sd->ob_itfm, *D);
196 #else
197 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
198 *D = transform_direction(&tfm, *D);
199 #endif
200 }
201
202 /* Object center position */
203
object_location(KernelGlobals * kg,const ShaderData * sd)204 ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd)
205 {
206 if (sd->object == OBJECT_NONE)
207 return make_float3(0.0f, 0.0f, 0.0f);
208
209 #ifdef __OBJECT_MOTION__
210 return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
211 #else
212 Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
213 return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
214 #endif
215 }
216
217 /* Total surface area of object */
218
object_surface_area(KernelGlobals * kg,int object)219 ccl_device_inline float object_surface_area(KernelGlobals *kg, int object)
220 {
221 return kernel_tex_fetch(__objects, object).surface_area;
222 }
223
224 /* Color of the object */
225
object_color(KernelGlobals * kg,int object)226 ccl_device_inline float3 object_color(KernelGlobals *kg, int object)
227 {
228 if (object == OBJECT_NONE)
229 return make_float3(0.0f, 0.0f, 0.0f);
230
231 const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
232 return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]);
233 }
234
235 /* Pass ID number of object */
236
object_pass_id(KernelGlobals * kg,int object)237 ccl_device_inline float object_pass_id(KernelGlobals *kg, int object)
238 {
239 if (object == OBJECT_NONE)
240 return 0.0f;
241
242 return kernel_tex_fetch(__objects, object).pass_id;
243 }
244
245 /* Per lamp random number for shader variation */
246
lamp_random_number(KernelGlobals * kg,int lamp)247 ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp)
248 {
249 if (lamp == LAMP_NONE)
250 return 0.0f;
251
252 return kernel_tex_fetch(__lights, lamp).random;
253 }
254
255 /* Per object random number for shader variation */
256
object_random_number(KernelGlobals * kg,int object)257 ccl_device_inline float object_random_number(KernelGlobals *kg, int object)
258 {
259 if (object == OBJECT_NONE)
260 return 0.0f;
261
262 return kernel_tex_fetch(__objects, object).random_number;
263 }
264
265 /* Particle ID from which this object was generated */
266
object_particle_id(KernelGlobals * kg,int object)267 ccl_device_inline int object_particle_id(KernelGlobals *kg, int object)
268 {
269 if (object == OBJECT_NONE)
270 return 0;
271
272 return kernel_tex_fetch(__objects, object).particle_index;
273 }
274
275 /* Generated texture coordinate on surface from where object was instanced */
276
object_dupli_generated(KernelGlobals * kg,int object)277 ccl_device_inline float3 object_dupli_generated(KernelGlobals *kg, int object)
278 {
279 if (object == OBJECT_NONE)
280 return make_float3(0.0f, 0.0f, 0.0f);
281
282 const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
283 return make_float3(
284 kobject->dupli_generated[0], kobject->dupli_generated[1], kobject->dupli_generated[2]);
285 }
286
287 /* UV texture coordinate on surface from where object was instanced */
288
object_dupli_uv(KernelGlobals * kg,int object)289 ccl_device_inline float3 object_dupli_uv(KernelGlobals *kg, int object)
290 {
291 if (object == OBJECT_NONE)
292 return make_float3(0.0f, 0.0f, 0.0f);
293
294 const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
295 return make_float3(kobject->dupli_uv[0], kobject->dupli_uv[1], 0.0f);
296 }
297
298 /* Information about mesh for motion blurred triangles and curves */
299
object_motion_info(KernelGlobals * kg,int object,int * numsteps,int * numverts,int * numkeys)300 ccl_device_inline void object_motion_info(
301 KernelGlobals *kg, int object, int *numsteps, int *numverts, int *numkeys)
302 {
303 if (numkeys) {
304 *numkeys = kernel_tex_fetch(__objects, object).numkeys;
305 }
306
307 if (numsteps)
308 *numsteps = kernel_tex_fetch(__objects, object).numsteps;
309 if (numverts)
310 *numverts = kernel_tex_fetch(__objects, object).numverts;
311 }
312
313 /* Offset to an objects patch map */
314
object_patch_map_offset(KernelGlobals * kg,int object)315 ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
316 {
317 if (object == OBJECT_NONE)
318 return 0;
319
320 return kernel_tex_fetch(__objects, object).patch_map_offset;
321 }
322
323 /* Volume step size */
324
object_volume_density(KernelGlobals * kg,int object)325 ccl_device_inline float object_volume_density(KernelGlobals *kg, int object)
326 {
327 if (object == OBJECT_NONE) {
328 return 1.0f;
329 }
330
331 return kernel_tex_fetch(__objects, object).surface_area;
332 }
333
object_volume_step_size(KernelGlobals * kg,int object)334 ccl_device_inline float object_volume_step_size(KernelGlobals *kg, int object)
335 {
336 if (object == OBJECT_NONE) {
337 return kernel_data.background.volume_step_size;
338 }
339
340 return kernel_tex_fetch(__object_volume_step, object);
341 }
342
343 /* Pass ID for shader */
344
shader_pass_id(KernelGlobals * kg,const ShaderData * sd)345 ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
346 {
347 return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id;
348 }
349
350 /* Cryptomatte ID */
351
object_cryptomatte_id(KernelGlobals * kg,int object)352 ccl_device_inline float object_cryptomatte_id(KernelGlobals *kg, int object)
353 {
354 if (object == OBJECT_NONE)
355 return 0.0f;
356
357 return kernel_tex_fetch(__objects, object).cryptomatte_object;
358 }
359
object_cryptomatte_asset_id(KernelGlobals * kg,int object)360 ccl_device_inline float object_cryptomatte_asset_id(KernelGlobals *kg, int object)
361 {
362 if (object == OBJECT_NONE)
363 return 0;
364
365 return kernel_tex_fetch(__objects, object).cryptomatte_asset;
366 }
367
368 /* Particle data from which object was instanced */
369
particle_index(KernelGlobals * kg,int particle)370 ccl_device_inline uint particle_index(KernelGlobals *kg, int particle)
371 {
372 return kernel_tex_fetch(__particles, particle).index;
373 }
374
particle_age(KernelGlobals * kg,int particle)375 ccl_device float particle_age(KernelGlobals *kg, int particle)
376 {
377 return kernel_tex_fetch(__particles, particle).age;
378 }
379
particle_lifetime(KernelGlobals * kg,int particle)380 ccl_device float particle_lifetime(KernelGlobals *kg, int particle)
381 {
382 return kernel_tex_fetch(__particles, particle).lifetime;
383 }
384
particle_size(KernelGlobals * kg,int particle)385 ccl_device float particle_size(KernelGlobals *kg, int particle)
386 {
387 return kernel_tex_fetch(__particles, particle).size;
388 }
389
particle_rotation(KernelGlobals * kg,int particle)390 ccl_device float4 particle_rotation(KernelGlobals *kg, int particle)
391 {
392 return kernel_tex_fetch(__particles, particle).rotation;
393 }
394
particle_location(KernelGlobals * kg,int particle)395 ccl_device float3 particle_location(KernelGlobals *kg, int particle)
396 {
397 return float4_to_float3(kernel_tex_fetch(__particles, particle).location);
398 }
399
particle_velocity(KernelGlobals * kg,int particle)400 ccl_device float3 particle_velocity(KernelGlobals *kg, int particle)
401 {
402 return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity);
403 }
404
particle_angular_velocity(KernelGlobals * kg,int particle)405 ccl_device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
406 {
407 return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity);
408 }
409
410 /* Object intersection in BVH */
411
bvh_clamp_direction(float3 dir)412 ccl_device_inline float3 bvh_clamp_direction(float3 dir)
413 {
414 const float ooeps = 8.271806E-25f;
415 return make_float3((fabsf(dir.x) > ooeps) ? dir.x : copysignf(ooeps, dir.x),
416 (fabsf(dir.y) > ooeps) ? dir.y : copysignf(ooeps, dir.y),
417 (fabsf(dir.z) > ooeps) ? dir.z : copysignf(ooeps, dir.z));
418 }
419
bvh_inverse_direction(float3 dir)420 ccl_device_inline float3 bvh_inverse_direction(float3 dir)
421 {
422 return rcp(dir);
423 }
424
425 /* Transform ray into object space to enter static object in BVH */
426
bvh_instance_push(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float t)427 ccl_device_inline float bvh_instance_push(
428 KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
429 {
430 Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
431
432 *P = transform_point(&tfm, ray->P);
433
434 float len;
435 *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
436 *idir = bvh_inverse_direction(*dir);
437
438 if (t != FLT_MAX) {
439 t *= len;
440 }
441
442 return t;
443 }
444
445 /* Transorm ray to exit static object in BVH */
446
bvh_instance_pop(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float t)447 ccl_device_inline float bvh_instance_pop(
448 KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
449 {
450 if (t != FLT_MAX) {
451 Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
452 t /= len(transform_direction(&tfm, ray->D));
453 }
454
455 *P = ray->P;
456 *dir = bvh_clamp_direction(ray->D);
457 *idir = bvh_inverse_direction(*dir);
458
459 return t;
460 }
461
462 /* Same as above, but returns scale factor to apply to multiple intersection distances */
463
bvh_instance_pop_factor(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float * t_fac)464 ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg,
465 int object,
466 const Ray *ray,
467 float3 *P,
468 float3 *dir,
469 float3 *idir,
470 float *t_fac)
471 {
472 Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
473 *t_fac = 1.0f / len(transform_direction(&tfm, ray->D));
474
475 *P = ray->P;
476 *dir = bvh_clamp_direction(ray->D);
477 *idir = bvh_inverse_direction(*dir);
478 }
479
480 #ifdef __OBJECT_MOTION__
481 /* Transform ray into object space to enter motion blurred object in BVH */
482
bvh_instance_motion_push(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float t,Transform * itfm)483 ccl_device_inline float bvh_instance_motion_push(KernelGlobals *kg,
484 int object,
485 const Ray *ray,
486 float3 *P,
487 float3 *dir,
488 float3 *idir,
489 float t,
490 Transform *itfm)
491 {
492 object_fetch_transform_motion_test(kg, object, ray->time, itfm);
493
494 *P = transform_point(itfm, ray->P);
495
496 float len;
497 *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
498 *idir = bvh_inverse_direction(*dir);
499
500 if (t != FLT_MAX) {
501 t *= len;
502 }
503
504 return t;
505 }
506
507 /* Transorm ray to exit motion blurred object in BVH */
508
bvh_instance_motion_pop(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float t,Transform * itfm)509 ccl_device_inline float bvh_instance_motion_pop(KernelGlobals *kg,
510 int object,
511 const Ray *ray,
512 float3 *P,
513 float3 *dir,
514 float3 *idir,
515 float t,
516 Transform *itfm)
517 {
518 if (t != FLT_MAX) {
519 t /= len(transform_direction(itfm, ray->D));
520 }
521
522 *P = ray->P;
523 *dir = bvh_clamp_direction(ray->D);
524 *idir = bvh_inverse_direction(*dir);
525
526 return t;
527 }
528
529 /* Same as above, but returns scale factor to apply to multiple intersection distances */
530
bvh_instance_motion_pop_factor(KernelGlobals * kg,int object,const Ray * ray,float3 * P,float3 * dir,float3 * idir,float * t_fac,Transform * itfm)531 ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg,
532 int object,
533 const Ray *ray,
534 float3 *P,
535 float3 *dir,
536 float3 *idir,
537 float *t_fac,
538 Transform *itfm)
539 {
540 *t_fac = 1.0f / len(transform_direction(itfm, ray->D));
541 *P = ray->P;
542 *dir = bvh_clamp_direction(ray->D);
543 *idir = bvh_inverse_direction(*dir);
544 }
545
546 #endif
547
548 /* TODO(sergey): This is only for until we've got OpenCL 2.0
549 * on all devices we consider supported. It'll be replaced with
550 * generic address space.
551 */
552
553 #ifdef __KERNEL_OPENCL__
object_position_transform_addrspace(KernelGlobals * kg,const ShaderData * sd,ccl_addr_space float3 * P)554 ccl_device_inline void object_position_transform_addrspace(KernelGlobals *kg,
555 const ShaderData *sd,
556 ccl_addr_space float3 *P)
557 {
558 float3 private_P = *P;
559 object_position_transform(kg, sd, &private_P);
560 *P = private_P;
561 }
562
object_dir_transform_addrspace(KernelGlobals * kg,const ShaderData * sd,ccl_addr_space float3 * D)563 ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg,
564 const ShaderData *sd,
565 ccl_addr_space float3 *D)
566 {
567 float3 private_D = *D;
568 object_dir_transform(kg, sd, &private_D);
569 *D = private_D;
570 }
571
object_normal_transform_addrspace(KernelGlobals * kg,const ShaderData * sd,ccl_addr_space float3 * N)572 ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg,
573 const ShaderData *sd,
574 ccl_addr_space float3 *N)
575 {
576 float3 private_N = *N;
577 object_normal_transform(kg, sd, &private_N);
578 *N = private_N;
579 }
580 #endif
581
582 #ifndef __KERNEL_OPENCL__
583 # define object_position_transform_auto object_position_transform
584 # define object_dir_transform_auto object_dir_transform
585 # define object_normal_transform_auto object_normal_transform
586 #else
587 # define object_position_transform_auto object_position_transform_addrspace
588 # define object_dir_transform_auto object_dir_transform_addrspace
589 # define object_normal_transform_auto object_normal_transform_addrspace
590 #endif
591
592 CCL_NAMESPACE_END
593