Blender V5.0
device/hiprt/common.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifdef __HIPRT__
6
7struct RayPayload {
9 RaySelfPrimitives self;
10 uint visibility;
11 int prim_type;
12 float ray_time;
13};
14
15/* Some ray types might use the same intersection function for regular and shadow intersections,
16 * but have different filter functions for them. To make this code simpler subclass from
17 * RayPayload.
18 *
19 * NOTE: This assumes that reinterpret_cast from void pointer to RayPayload works correctly. */
20struct ShadowPayload : RayPayload {
21 int in_state;
22 uint max_transparent_hits;
23 uint num_transparent_hits;
24 uint *r_num_recorded_hits;
25 float *r_throughput;
26};
27
28struct LocalPayload {
30 RaySelfPrimitives self;
31 float ray_time;
32 int local_object;
33 uint max_hits;
34 uint *lcg_state;
35 LocalIntersection *local_isect;
36};
37
38# define SET_HIPRT_RAY(RAY_RT, RAY) \
39 RAY_RT.direction = RAY->D; \
40 RAY_RT.origin = RAY->P; \
41 RAY_RT.maxT = RAY->tmax; \
42 RAY_RT.minT = RAY->tmin;
43
44# define GET_TRAVERSAL_STACK() \
45 Stack stack(kg->global_stack_buffer, kg->shared_stack); \
46 Instance_Stack instance_stack;
47
48# define GET_TRAVERSAL_ANY_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
49 hiprtSceneTraversalAnyHitCustomStack<Stack, Instance_Stack> traversal( \
50 (hiprtScene)kernel_data.device_bvh, \
51 ray_hip, \
52 stack, \
53 instance_stack, \
54 visibility, \
55 hiprtTraversalHintDefault, \
56 &payload, \
57 kernel_params.FUNCTION_TABLE, \
58 RAY_TYPE, \
59 RAY_TIME);
60
61# define GET_TRAVERSAL_CLOSEST_HIT(FUNCTION_TABLE, RAY_TYPE, RAY_TIME) \
62 hiprtSceneTraversalClosestCustomStack<Stack, Instance_Stack> traversal( \
63 (hiprtScene)kernel_data.device_bvh, \
64 ray_hip, \
65 stack, \
66 instance_stack, \
67 visibility, \
68 hiprtTraversalHintDefault, \
69 &payload, \
70 kernel_params.FUNCTION_TABLE, \
71 RAY_TYPE, \
72 RAY_TIME);
73
74ccl_device_inline void set_intersect_point(KernelGlobals kg,
75 const hiprtHit &hit,
77{
78 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
79 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
80
81 isect->type = kernel_data_fetch(objects, object_id).primitive_type;
82
83 isect->t = hit.t;
84 isect->prim = hit.primID + prim_offset;
85 isect->object = object_id;
86 isect->u = hit.uv.x;
87 isect->v = hit.uv.y;
88}
89
90/* --------------------------------------------------------------------
91 * Custom intersection functions.
92 */
93
94ccl_device_inline bool curve_custom_intersect(const hiprtRay &ray,
95 RayPayload *payload,
96 hiprtHit &hit)
97
98{
99 /* Could also cast shadow payload to get the elements needed to do the intersection no need to
100 * write a separate function for shadow intersection. */
101
102 KernelGlobals kg = payload->kg;
103
104 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
105
106 /* `data_offset.x`: where the data (prim id, type )for the geometry of the current object begins
107 * the prim_id that is in hiprtHit hit is local to the particular geometry so we add the above
108 * `ofstream` to map prim id in hiprtHit to the one compatible to what next stage expects
109 * `data_offset.y`: the offset that has to be added to a local primitive to get the global
110 * `primitive id = kernel_data_fetch(object_prim_offset, object_id);` */
111 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
112
113 const int prim_offset = data_offset.y;
114
115 const int2 prim_info = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x);
116 const int curve_index = prim_info.x;
117 const int key_value = prim_info.y;
118
119# ifdef __SHADOW_LINKING__
120 if (intersection_skip_shadow_link(kg, payload->self, object_id)) {
121 return false; /* Ignore hit - continue traversal. */
122 }
123# endif
124
125 if (intersection_skip_self_shadow(payload->self, object_id, curve_index + prim_offset)) {
126 return false;
127 }
128
129 const float ray_time = payload->ray_time;
130
131 if ((key_value & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
132 const int time_offset = kernel_data_fetch(prim_time_offset, object_id);
133 const float2 prims_time = kernel_data_fetch(prims_time, hit.primID + time_offset);
134 if (ray_time < prims_time.x || ray_time > prims_time.y) {
135 return false;
136 }
137 }
138
139 Intersection isect;
140 const bool b_hit = curve_intersect(kg,
141 &isect,
142 ray.origin,
143 ray.direction,
144 ray.minT,
145 ray.maxT,
146 object_id,
147 curve_index + prim_offset,
148 ray_time,
149 key_value);
150 if (b_hit) {
151 hit.uv.x = isect.u;
152 hit.uv.y = isect.v;
153 hit.t = isect.t;
154 hit.primID = isect.prim;
155 payload->prim_type = isect.type; /* packed_curve_type */
156 }
157
158 return b_hit;
159}
160
161ccl_device_inline bool motion_triangle_custom_intersect(const hiprtRay &ray,
162 RayPayload *payload,
163 hiprtHit &hit)
164{
165 KernelGlobals kg = payload->kg;
166 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
167 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
168 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
169
170 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
171 const int prim_id_global = prim_id_local + prim_offset;
172
173 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
174 return false;
175 }
176
177 Intersection isect;
178 const bool b_hit = motion_triangle_intersect(kg,
179 &isect,
180 ray.origin,
181 ray.direction,
182 ray.minT,
183 ray.maxT,
184 payload->ray_time,
185 payload->visibility,
186 object_id,
187 prim_id_global,
188 hit.instanceID);
189
190 if (b_hit) {
191 hit.uv.x = isect.u;
192 hit.uv.y = isect.v;
193 hit.t = isect.t;
194 hit.primID = isect.prim;
195 payload->prim_type = isect.type;
196 }
197
198 return b_hit;
199}
200
201ccl_device_inline bool motion_triangle_custom_local_intersect(const hiprtRay &ray,
202 LocalPayload *payload,
203 hiprtHit &hit)
204{
205# ifdef __OBJECT_MOTION__
206 KernelGlobals kg = payload->kg;
207
208 const int object_id = payload->local_object;
209 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
210 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
211
212 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
213 const int prim_id_global = prim_id_local + prim_offset;
214
215 if (intersection_skip_self_local(payload->self, prim_id_global)) {
216 return false;
217 }
218
219 return motion_triangle_intersect_local(kg,
220 payload->local_isect,
221 ray.origin,
222 ray.direction,
223 payload->ray_time,
224 object_id,
225 prim_id_global,
226 ray.minT,
227 ray.maxT,
228 payload->lcg_state,
229 payload->max_hits);
230
231# else
232 return false;
233# endif
234}
235
236ccl_device_inline bool motion_triangle_custom_volume_intersect(const hiprtRay &ray,
237 RayPayload *payload,
238 hiprtHit &hit)
239{
240# ifdef __OBJECT_MOTION__
241 KernelGlobals kg = payload->kg;
242
243 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
244 const int object_flag = kernel_data_fetch(object_flag, object_id);
245
246 if (!(object_flag & SD_OBJECT_HAS_VOLUME)) {
247 return false;
248 }
249
250 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
251 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
252
253 const int prim_id_local = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x).x;
254 const int prim_id_global = prim_id_local + prim_offset;
255
256 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
257 return false;
258 }
259
260 Intersection isect;
261 const bool b_hit = motion_triangle_intersect(kg,
262 &isect,
263 ray.origin,
264 ray.direction,
265 ray.minT,
266 ray.maxT,
267 payload->ray_time,
268 payload->visibility,
269 object_id,
270 prim_id_global,
271 prim_id_local);
272
273 if (b_hit) {
274 hit.uv.x = isect.u;
275 hit.uv.y = isect.v;
276 hit.t = isect.t;
277 hit.primID = isect.prim;
278 payload->prim_type = isect.type;
279 }
280
281 return b_hit;
282# else
283 return false;
284# endif
285}
286
287ccl_device_inline bool point_custom_intersect(const hiprtRay &ray,
288 RayPayload *payload,
289 hiprtHit &hit)
290{
291# if defined(__POINTCLOUD__)
292 KernelGlobals kg = payload->kg;
293
294 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
295 const int2 data_offset = kernel_data_fetch(custom_prim_info_offset, object_id);
296 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
297
298 const int2 prim_info = kernel_data_fetch(custom_prim_info, hit.primID + data_offset.x);
299 const int prim_id_local = prim_info.x;
300 const int prim_id_global = prim_id_local + prim_offset;
301
302 const int primitive_type = prim_info.y;
303
304# ifdef __SHADOW_LINKING__
305 if (intersection_skip_shadow_link(kg, payload->self, object_id)) {
306 return false; /* Ignore hit - continue traversal */
307 }
308# endif
309
310 if (intersection_skip_self_shadow(payload->self, object_id, prim_id_global)) {
311 return false;
312 }
313
314 const float ray_time = payload->ray_time;
315
316 if ((primitive_type & PRIMITIVE_MOTION_POINT) && kernel_data.bvh.use_bvh_steps) {
317 const int time_offset = kernel_data_fetch(prim_time_offset, object_id);
318 const float2 prims_time = kernel_data_fetch(prims_time, hit.primID + time_offset);
319 if (ray_time < prims_time.x || ray_time > prims_time.y) {
320 return false;
321 }
322 }
323
324 Intersection isect;
325 const bool b_hit = point_intersect(kg,
326 &isect,
327 ray.origin,
328 ray.direction,
329 ray.minT,
330 ray.maxT,
331 object_id,
332 prim_id_global,
333 ray_time,
334 primitive_type);
335
336 if (b_hit) {
337 hit.uv.x = isect.u;
338 hit.uv.y = isect.v;
339 hit.t = isect.t;
340 hit.primID = isect.prim;
341 payload->prim_type = isect.type;
342 }
343
344 return b_hit;
345# else
346 return false;
347# endif
348}
349
350/* --------------------------------------------------------------------
351 * Intersection filters.
352 */
353
354ccl_device_inline bool closest_intersection_filter(const hiprtRay &ray,
355 RayPayload *payload,
356 const hiprtHit &hit)
357{
358 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
359 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
360 const int prim = hit.primID + prim_offset;
361
362# ifdef __SHADOW_LINKING__
363 if (intersection_skip_shadow_link(payload->kg, payload->self, object_id)) {
364 return true; /* Ignore hit - continue traversal. */
365 }
366# endif
367
368 if (intersection_skip_self_shadow(payload->self, object_id, prim)) {
369 return true; /* Ignore hit - continue traversal. */
370 }
371
372 return false;
373}
374
375ccl_device_inline bool shadow_intersection_filter(const hiprtRay &ray,
376 ShadowPayload *payload,
377 const hiprtHit &hit)
378
379{
380 KernelGlobals kg = payload->kg;
381
382 uint num_transparent_hits = payload->num_transparent_hits;
383 const uint max_transparent_hits = payload->max_transparent_hits;
384 const int state = payload->in_state;
385 const RaySelfPrimitives &self = payload->self;
386
387 const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
388 const int prim_offset = kernel_data_fetch(object_prim_offset, object);
389 const int prim = hit.primID + prim_offset;
390
391 const float ray_tmax = hit.t;
392
393# ifdef __SHADOW_LINKING__
394 if (intersection_skip_shadow_link(kg, self, object)) {
395 return true; /* Ignore hit - continue traversal */
396 }
397# endif
398
399# ifdef __VISIBILITY_FLAG__
400 if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
401 return true; /* No hit - continue traversal. */
402 }
403# endif
404
405 if (intersection_skip_self_shadow(self, object, prim)) {
406 return true; /* No hit -continue traversal. */
407 }
408
409 if (intersection_skip_shadow_already_recoded(state, object, prim, *payload->r_num_recorded_hits))
410 {
411 return true;
412 }
413
414 const float u = hit.uv.x;
415 const float v = hit.uv.y;
416 const int primitive_type = kernel_data_fetch(objects, object).primitive_type;
417
418# ifndef __TRANSPARENT_SHADOWS__
419 return false;
420# else
421 const int flags = intersection_get_shader_flags(kg, prim, primitive_type);
422 if (!(flags & SD_HAS_TRANSPARENT_SHADOW)) {
423 return false;
424 }
425
426 num_transparent_hits += !(flags & SD_HAS_ONLY_VOLUME);
427 if (num_transparent_hits > max_transparent_hits) {
428 return false;
429 }
430
431 uint record_index = *payload->r_num_recorded_hits;
432
433 payload->num_transparent_hits = num_transparent_hits;
434 *(payload->r_num_recorded_hits) += 1;
435
436 const uint max_record_hits = INTEGRATOR_SHADOW_ISECT_SIZE;
437 if (record_index >= max_record_hits) {
438 float max_recorded_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
439 uint max_recorded_hit = 0;
440
441 for (int i = 1; i < max_record_hits; i++) {
442 const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
443 if (isect_t > max_recorded_t) {
444 max_recorded_t = isect_t;
445 max_recorded_hit = i;
446 }
447 }
448
449 if (ray_tmax >= max_recorded_t) {
450 return true;
451 }
452
453 record_index = max_recorded_hit;
454 }
455
456 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, u) = u;
457 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, v) = v;
458 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, t) = ray_tmax;
459 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, prim) = prim;
460 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, object) = object;
461 INTEGRATOR_STATE_ARRAY_WRITE(state, shadow_isect, record_index, type) = primitive_type;
462
463 return true;
464# endif /* __TRANSPARENT_SHADOWS__ */
465}
466
467ccl_device_inline bool shadow_intersection_filter_curves(const hiprtRay &ray,
468 ShadowPayload *payload,
469 const hiprtHit &hit)
470
471{
472 KernelGlobals kg = payload->kg;
473
474 uint num_transparent_hits = payload->num_transparent_hits;
475 const uint num_recorded_hits = *(payload->r_num_recorded_hits);
476 const uint max_transparent_hits = payload->max_transparent_hits;
477 const RaySelfPrimitives &self = payload->self;
478
479 const int object = kernel_data_fetch(user_instance_id, hit.instanceID);
480 const int prim = hit.primID;
481
482 const float ray_tmax = hit.t;
483
484# ifdef __SHADOW_LINKING__
485 /* It doesn't seem like this is necessary. */
486 if (intersection_skip_shadow_link(kg, self, object)) {
487 return true; /* Ignore hit - continue traversal. */
488 }
489# endif
490
491# ifdef __VISIBILITY_FLAG__
492 if ((kernel_data_fetch(objects, object).visibility & payload->visibility) == 0) {
493 return true; /* No hit - continue traversal. */
494 }
495# endif
496
497 if (intersection_skip_self_shadow(self, object, prim)) {
498 return true; /* No hit -continue traversal. */
499 }
500
501 /* FIXME: transparent curves are not recorded, this check doesn't work. */
502 if (intersection_skip_shadow_already_recoded(payload->in_state, object, prim, num_recorded_hits))
503 {
504 return true;
505 }
506
507 const float u = hit.uv.x;
508 const float v = hit.uv.y;
509
510 if (u == 0.0f || u == 1.0f) {
511 return true; /* Continue traversal. */
512 }
513
514 const int primitive_type = payload->prim_type;
515
516# ifndef __TRANSPARENT_SHADOWS__
517 return false;
518# else
519 const int flags = intersection_get_shader_flags(kg, prim, primitive_type);
520 if (!(flags & SD_HAS_TRANSPARENT_SHADOW)) {
521 return false;
522 }
523
524 num_transparent_hits += !(flags & SD_HAS_ONLY_VOLUME);
525 if (num_transparent_hits > max_transparent_hits) {
526 return false;
527 }
528
529 float throughput = *payload->r_throughput;
530 throughput *= intersection_curve_shadow_transparency(kg, object, prim, primitive_type, u);
531 *payload->r_throughput = throughput;
532 payload->num_transparent_hits = num_transparent_hits;
533
534 if (throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
535 return false;
536 }
537
538 return true;
539# endif /* __TRANSPARENT_SHADOWS__ */
540}
541
542ccl_device_inline bool local_intersection_filter(const hiprtRay &ray,
543 LocalPayload *payload,
544 const hiprtHit &hit)
545{
546# ifdef __BVH_LOCAL__
547 KernelGlobals kg = payload->kg;
548
549 const int object_id = payload->local_object;
550 const uint max_hits = payload->max_hits;
551
552 /* Triangle primitive uses hardware intersection, other primitives do custom intersection
553 * which does reservoir sampling for intersections. For the custom primitives only check
554 * whether we can stop traversal early on. The rest of the checks here only do for the
555 * regular triangles. */
556 const int primitive_type = kernel_data_fetch(objects, object_id).primitive_type;
557 if (primitive_type != PRIMITIVE_TRIANGLE) {
558 if (max_hits == 0) {
559 return false;
560 }
561 return true;
562 }
563
564 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
565 const int prim = hit.primID + prim_offset;
566# ifndef __RAY_OFFSET__
567 if (intersection_skip_self_local(payload->self, prim)) {
568 return true; /* Continue search. */
569 }
570# endif
571
572 if (max_hits == 0) {
573 return false; /* Stop search. */
574 }
575
576 const int hit_index = local_intersect_get_record_index(
577 payload->local_isect, hit.t, payload->lcg_state, max_hits);
578 if (hit_index == -1) {
579 return true; /* Continue search. */
580 }
581
582 Intersection *isect = &payload->local_isect->hits[hit_index];
583 isect->t = hit.t;
584 isect->u = hit.uv.x;
585 isect->v = hit.uv.y;
586 isect->prim = prim;
587 isect->object = object_id;
588 isect->type = primitive_type;
589
590 payload->local_isect->Ng[hit_index] = hit.normal;
591
592 return true;
593# else
594 return false;
595# endif
596}
597
598ccl_device_inline bool volume_intersection_filter(const hiprtRay &ray,
599 RayPayload *payload,
600 const hiprtHit &hit)
601{
602 const int object_id = kernel_data_fetch(user_instance_id, hit.instanceID);
603 const int prim_offset = kernel_data_fetch(object_prim_offset, object_id);
604 const int prim = hit.primID + prim_offset;
605 const int object_flag = kernel_data_fetch(object_flag, object_id);
606
607 if (intersection_skip_self(payload->self, object_id, prim)) {
608 return true;
609 }
610 if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
611 return true;
612 }
613 return false;
614}
615
616HIPRT_DEVICE bool intersectFunc(const uint geom_type,
617 const uint ray_type,
618 const hiprtFuncTableHeader &tableHeader,
619 const hiprtRay &ray,
620 void *payload,
621 hiprtHit &hit)
622{
623 const uint index = tableHeader.numGeomTypes * ray_type + geom_type;
624 switch (index) {
627 return curve_custom_intersect(ray, (RayPayload *)payload, hit);
630 return motion_triangle_custom_intersect(ray, (RayPayload *)payload, hit);
632 return motion_triangle_custom_local_intersect(ray, (LocalPayload *)payload, hit);
634 return motion_triangle_custom_volume_intersect(ray, (RayPayload *)payload, hit);
637 return point_custom_intersect(ray, (RayPayload *)payload, hit);
638 default:
639 break;
640 }
641 return false;
642}
643
644HIPRT_DEVICE bool filterFunc(const uint geom_type,
645 const uint ray_type,
646 const hiprtFuncTableHeader &tableHeader,
647 const hiprtRay &ray,
648 void *payload,
649 const hiprtHit &hit)
650{
651 const uint index = tableHeader.numGeomTypes * ray_type + geom_type;
652 switch (index) {
654 return closest_intersection_filter(ray, (RayPayload *)payload, hit);
656 return shadow_intersection_filter_curves(ray, (ShadowPayload *)payload, hit);
660 return shadow_intersection_filter(ray, (ShadowPayload *)payload, hit);
663 return local_intersection_filter(ray, (LocalPayload *)payload, hit);
666 return volume_intersection_filter(ray, (RayPayload *)payload, hit);
667 default:
668 break;
669 }
670 return false;
671}
672
673#endif
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, const int prim, const int type)
ccl_device_forceinline bool intersection_skip_shadow_already_recoded(IntegratorShadowState state, const int object, const int prim, const int num_hits)
ccl_device_inline bool intersection_skip_shadow_link(KernelGlobals kg, const ccl_ray_data RaySelfPrimitives &self, const int isect_object)
ccl_device_inline bool intersection_skip_self_shadow(const ccl_ray_data RaySelfPrimitives &self, const int object, const int prim)
ccl_device_inline bool intersection_skip_self(const ccl_ray_data RaySelfPrimitives &self, const int object, const int prim)
#define CURVE_SHADOW_TRANSPARENCY_CUTOFF
ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, const int object, const int prim, const int type, const float u)
ccl_device_inline bool intersection_skip_self_local(const ccl_ray_data RaySelfPrimitives &self, const int prim)
#define kernel_data
#define kernel_data_fetch(name, index)
#define INTEGRATOR_SHADOW_ISECT_SIZE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
@ Motion_Triangle_Filter_Volume
@ Motion_Triangle_Filter_Local
@ Triangle_Filter_Closest
@ Curve_Filter_Shadow
@ Motion_Triangle_Filter_Shadow
@ Point_Filter_Shadow
@ Triangle_Filter_Local
@ Triangle_Filter_Volume
@ Triangle_Filter_Shadow
@ Motion_Triangle_Intersect_Shadow
@ Curve_Intersect_Function
@ Motion_Triangle_Intersect_Function
@ Point_Intersect_Shadow
@ Curve_Intersect_Shadow
@ Point_Intersect_Function
@ Motion_Triangle_Intersect_Volume
@ Motion_Triangle_Intersect_Local
@ SD_HAS_TRANSPARENT_SHADOW
@ SD_HAS_ONLY_VOLUME
@ PRIMITIVE_MOTION
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_MOTION_POINT
@ SD_OBJECT_HAS_VOLUME
static ulong state[N]
ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, const float3 P, const float3 dir, const float tmin, const float tmax, const float time, const uint visibility, const int object, const int prim, const int prim_addr)
#define INTEGRATOR_STATE_ARRAY_WRITE(state, nested_struct, array_index, member)
Definition state.h:240
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition state.h:238
float y
i
Definition text_draw.cc:230