Blender  V3.3
shadow_all.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
3  * and code copyright 2009-2012 Intel Corporation
4  *
5  * Modifications Copyright 2011-2022 Blender Foundation. */
6 
7 #if BVH_FEATURE(BVH_HAIR)
8 # define NODE_INTERSECT bvh_node_intersect
9 #else
10 # define NODE_INTERSECT bvh_aligned_node_intersect
11 #endif
12 
13 /* This is a template BVH traversal function, where various features can be
14  * enabled/disabled. This way we can compile optimized versions for each case
15  * without new features slowing things down.
16  *
17  * BVH_HAIR: hair curve rendering
18  * BVH_POINTCLOUD: point cloud rendering
19  * BVH_MOTION: motion blur rendering
20  */
21 
22 #ifndef __KERNEL_GPU__
24 #else
26 #endif
28  ccl_private const Ray *ray,
30  const uint visibility,
31  const uint max_hits,
32  ccl_private uint *r_num_recorded_hits,
33  ccl_private float *r_throughput)
34 {
35  /* todo:
36  * - likely and unlikely for if() statements
37  * - test restrict attribute for pointers
38  */
39 
40  /* traversal stack in CUDA thread-local memory */
43 
44  /* traversal variables in registers */
45  int stack_ptr = 0;
46  int node_addr = kernel_data.bvh.root;
47 
48  /* ray parameters in registers */
49  float3 P = ray->P;
50  float3 dir = bvh_clamp_direction(ray->D);
51  float3 idir = bvh_inverse_direction(dir);
52  float tmin = ray->tmin;
53  int object = OBJECT_NONE;
54  uint num_hits = 0;
55 
56  /* Max distance in world space. May be dynamically reduced when max number of
57  * recorded hits is exceeded and we no longer need to find hits beyond the max
58  * distance found. */
59  const float tmax = ray->tmax;
60  float tmax_hits = tmax;
61 
62  *r_num_recorded_hits = 0;
63  *r_throughput = 1.0f;
64 
65  /* traversal loop */
66  do {
67  do {
68  /* traverse internal nodes */
69  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
70  int node_addr_child1, traverse_mask;
71  float dist[2];
72  float4 cnodes = kernel_data_fetch(bvh_nodes, node_addr + 0);
73 
74  traverse_mask = NODE_INTERSECT(kg,
75  P,
77  dir,
78 #endif
79  idir,
80  tmin,
81  tmax,
82  node_addr,
83  visibility,
84  dist);
85 
86  node_addr = __float_as_int(cnodes.z);
87  node_addr_child1 = __float_as_int(cnodes.w);
88 
89  if (traverse_mask == 3) {
90  /* Both children were intersected, push the farther one. */
91  bool is_closest_child1 = (dist[1] < dist[0]);
92  if (is_closest_child1) {
93  int tmp = node_addr;
94  node_addr = node_addr_child1;
95  node_addr_child1 = tmp;
96  }
97 
98  ++stack_ptr;
99  kernel_assert(stack_ptr < BVH_STACK_SIZE);
100  traversal_stack[stack_ptr] = node_addr_child1;
101  }
102  else {
103  /* One child was intersected. */
104  if (traverse_mask == 2) {
105  node_addr = node_addr_child1;
106  }
107  else if (traverse_mask == 0) {
108  /* Neither child was intersected. */
109  node_addr = traversal_stack[stack_ptr];
110  --stack_ptr;
111  }
112  }
113  }
114 
115  /* if node is leaf, fetch triangle list */
116  if (node_addr < 0) {
117  float4 leaf = kernel_data_fetch(bvh_leaf_nodes, (-node_addr - 1));
118  int prim_addr = __float_as_int(leaf.x);
119 
120  if (prim_addr >= 0) {
121  const int prim_addr2 = __float_as_int(leaf.y);
122  const uint type = __float_as_int(leaf.w);
123 
124  /* pop */
125  node_addr = traversal_stack[stack_ptr];
126  --stack_ptr;
127 
128  /* primitive intersection */
129  for (; prim_addr < prim_addr2; prim_addr++) {
130  kernel_assert((kernel_data_fetch(prim_type, prim_addr) & PRIMITIVE_ALL) ==
131  (type & PRIMITIVE_ALL));
132  bool hit;
133 
134  /* todo: specialized intersect functions which don't fill in
135  * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
136  * might give a few % performance improvement */
138 
139  const int prim_object = (object == OBJECT_NONE) ?
140  kernel_data_fetch(prim_object, prim_addr) :
141  object;
142  const int prim = kernel_data_fetch(prim_index, prim_addr);
143  if (intersection_skip_self_shadow(ray->self, prim_object, prim)) {
144  continue;
145  }
146 
147  switch (type & PRIMITIVE_ALL) {
148  case PRIMITIVE_TRIANGLE: {
149  hit = triangle_intersect(
150  kg, &isect, P, dir, tmin, tmax, visibility, prim_object, prim, prim_addr);
151  break;
152  }
153 #if BVH_FEATURE(BVH_MOTION)
155  hit = motion_triangle_intersect(kg,
156  &isect,
157  P,
158  dir,
159  tmin,
160  tmax,
161  ray->time,
162  visibility,
163  prim_object,
164  prim,
165  prim_addr);
166  break;
167  }
168 #endif
169 #if BVH_FEATURE(BVH_HAIR)
174  if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
175  const float2 prim_time = kernel_data_fetch(prim_time, prim_addr);
176  if (ray->time < prim_time.x || ray->time > prim_time.y) {
177  hit = false;
178  break;
179  }
180  }
181 
182  const int curve_type = kernel_data_fetch(prim_type, prim_addr);
183  hit = curve_intersect(
184  kg, &isect, P, dir, tmin, tmax, prim_object, prim, ray->time, curve_type);
185 
186  break;
187  }
188 #endif
189 #if BVH_FEATURE(BVH_POINTCLOUD)
190  case PRIMITIVE_POINT:
191  case PRIMITIVE_MOTION_POINT: {
192  if ((type & PRIMITIVE_MOTION) && kernel_data.bvh.use_bvh_steps) {
193  const float2 prim_time = kernel_data_fetch(prim_time, prim_addr);
194  if (ray->time < prim_time.x || ray->time > prim_time.y) {
195  hit = false;
196  break;
197  }
198  }
199 
200  const int point_type = kernel_data_fetch(prim_type, prim_addr);
201  hit = point_intersect(
202  kg, &isect, P, dir, tmin, tmax, prim_object, prim, ray->time, point_type);
203  break;
204  }
205 #endif /* BVH_FEATURE(BVH_POINTCLOUD) */
206  default: {
207  hit = false;
208  break;
209  }
210  }
211 
212  /* shadow ray early termination */
213  if (hit) {
214  /* detect if this surface has a shader with transparent shadows */
215  /* todo: optimize so primitive visibility flag indicates if
216  * the primitive has a transparent shadow shader? */
217  const int flags = intersection_get_shader_flags(kg, isect.prim, isect.type);
218 
219  if (!(flags & SD_HAS_TRANSPARENT_SHADOW) || num_hits >= max_hits) {
220  /* If no transparent shadows, all light is blocked and we can
221  * stop immediately. */
222  return true;
223  }
224 
225  num_hits++;
226 
227  bool record_intersection = true;
228 
229  /* Always use baked shadow transparency for curves. */
230  if (isect.type & PRIMITIVE_CURVE) {
232  kg, isect.object, isect.prim, isect.type, isect.u);
233 
234  if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
235  return true;
236  }
237  else {
238  record_intersection = false;
239  }
240  }
241 
242  if (record_intersection) {
243  /* Test if we need to record this transparent intersection. */
244  const uint max_record_hits = min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
245  if (*r_num_recorded_hits < max_record_hits || isect.t < tmax_hits) {
246  /* If maximum number of hits was reached, replace the intersection with the
247  * highest distance. We want to find the N closest intersections. */
248  const uint num_recorded_hits = min(*r_num_recorded_hits, max_record_hits);
249  uint isect_index = num_recorded_hits;
250  if (num_recorded_hits + 1 >= max_record_hits) {
251  float max_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, t);
252  uint max_recorded_hit = 0;
253 
254  for (uint i = 1; i < num_recorded_hits; ++i) {
255  const float isect_t = INTEGRATOR_STATE_ARRAY(state, shadow_isect, i, t);
256  if (isect_t > max_t) {
257  max_recorded_hit = i;
258  max_t = isect_t;
259  }
260  }
261 
262  if (num_recorded_hits >= max_record_hits) {
263  isect_index = max_recorded_hit;
264  }
265 
266  /* Limit the ray distance and stop counting hits beyond this. */
267  tmax_hits = max(isect.t, max_t);
268  }
269 
270  integrator_state_write_shadow_isect(state, &isect, isect_index);
271  }
272 
273  /* Always increase the number of recorded hits, even beyond the maximum,
274  * so that we can detect this and trace another ray if needed. */
275  ++(*r_num_recorded_hits);
276  }
277  }
278  }
279  }
280  else {
281  /* instance push */
282  object = kernel_data_fetch(prim_object, -prim_addr - 1);
283 
284 #if BVH_FEATURE(BVH_MOTION)
285  bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir);
286 #else
287  bvh_instance_push(kg, object, ray, &P, &dir, &idir);
288 #endif
289 
290  ++stack_ptr;
291  kernel_assert(stack_ptr < BVH_STACK_SIZE);
293 
294  node_addr = kernel_data_fetch(object_node, object);
295  }
296  }
297  } while (node_addr != ENTRYPOINT_SENTINEL);
298 
299  if (stack_ptr >= 0) {
300  kernel_assert(object != OBJECT_NONE);
301 
302  /* Instance pop. */
303  bvh_instance_pop(ray, &P, &dir, &idir);
304 
305  object = OBJECT_NONE;
306  node_addr = traversal_stack[stack_ptr];
307  --stack_ptr;
308  }
309  } while (node_addr != ENTRYPOINT_SENTINEL);
310 
311  return false;
312 }
313 
315  ccl_private const Ray *ray,
317  const uint visibility,
318  const uint max_hits,
319  ccl_private uint *num_recorded_hits,
320  ccl_private float *throughput)
321 {
322  return BVH_FUNCTION_FULL_NAME(BVH)(
323  kg, ray, state, visibility, max_hits, num_recorded_hits, throughput);
324 }
325 
326 #undef BVH_FUNCTION_NAME
327 #undef BVH_FUNCTION_FEATURES
328 #undef NODE_INTERSECT
unsigned int uint
Definition: BLI_sys_types.h:67
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
float float4[4]
Definition: bvh/bvh.h:63
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_optional_struct_init
Definition: cuda/compat.h:53
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals kg, const int prim, const int type)
#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_shadow(ccl_private const RaySelfPrimitives &self, const int object, const int prim)
BLI_Stack * traversal_stack
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define BVH_STACK_SIZE
#define BVH_FEATURE(f)
#define ENTRYPOINT_SENTINEL
#define BVH_HAIR
#define BVH_FUNCTION_FULL_NAME(prefix)
const int state
ccl_device_inline void bvh_instance_push(KernelGlobals kg, int object, ccl_private const Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
ccl_device_inline float3 bvh_clamp_direction(float3 dir)
ccl_device_inline void bvh_instance_pop(ccl_private const Ray *ray, ccl_private float3 *P, ccl_private float3 *dir, ccl_private float3 *idir)
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
@ SD_HAS_TRANSPARENT_SHADOW
Definition: kernel/types.h:766
@ PRIMITIVE_MOTION_CURVE_RIBBON
Definition: kernel/types.h:561
@ PRIMITIVE_ALL
Definition: kernel/types.h:566
@ PRIMITIVE_MOTION
Definition: kernel/types.h:558
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel/types.h:559
@ PRIMITIVE_CURVE_RIBBON
Definition: kernel/types.h:553
@ PRIMITIVE_MOTION_CURVE_THICK
Definition: kernel/types.h:560
@ PRIMITIVE_CURVE
Definition: kernel/types.h:564
@ PRIMITIVE_CURVE_THICK
Definition: kernel/types.h:552
@ PRIMITIVE_TRIANGLE
Definition: kernel/types.h:551
@ PRIMITIVE_MOTION_POINT
Definition: kernel/types.h:562
@ PRIMITIVE_POINT
Definition: kernel/types.h:554
#define INTEGRATOR_SHADOW_ISECT_SIZE
Definition: kernel/types.h:53
#define OBJECT_NONE
Definition: kernel/types.h:40
static float P(float k)
Definition: math_interp.c:25
ccl_device_inline bool motion_triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, float3 P, float3 dir, float tmin, float tmax, float time, uint visibility, int object, int prim, int prim_addr)
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals kg, ccl_private const Ray *ray, IntegratorShadowState state, const uint visibility, const uint max_hits, ccl_private uint *num_recorded_hits, ccl_private float *throughput)
Definition: shadow_all.h:314
#define NODE_INTERSECT
Definition: shadow_all.h:10
#define min(a, b)
Definition: sort.c:35
IntegratorShadowStateCPU *ccl_restrict IntegratorShadowState
Definition: state.h:149
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition: state.h:157
ccl_device_forceinline void integrator_state_write_shadow_isect(IntegratorShadowState state, ccl_private const Intersection *ccl_restrict isect, const int index)
Definition: state_util.h:116
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float max
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, float3 P, float3 dir, float tmin, float tmax, uint visibility, int object, int prim, int prim_addr)
ccl_device_inline int __float_as_int(float f)
Definition: util/math.h:243