Blender  V2.93
bvh_volume_all.h
Go to the documentation of this file.
1 /*
2  * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
3  * and code copyright 2009-2012 Intel Corporation
4  *
5  * Modifications Copyright 2011-2014, Blender Foundation.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #if BVH_FEATURE(BVH_HAIR)
21 # define NODE_INTERSECT bvh_node_intersect
22 #else
23 # define NODE_INTERSECT bvh_aligned_node_intersect
24 #endif
25 
26 /* This is a template BVH traversal function for volumes, where
27  * various features can be enabled/disabled. This way we can compile optimized
28  * versions for each case without new features slowing things down.
29  *
30  * BVH_MOTION: motion blur rendering
31  */
32 
33 #ifndef __KERNEL_GPU__
35 #else
37 #endif
38  uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
39  const Ray *ray,
40  Intersection *isect_array,
41  const uint max_hits,
42  const uint visibility)
43 {
44  /* todo:
45  * - test if pushing distance on the stack helps (for non shadow rays)
46  * - separate version for shadow rays
47  * - likely and unlikely for if() statements
48  * - test restrict attribute for pointers
49  */
50 
51  /* traversal stack in CUDA thread-local memory */
54 
55  /* traversal variables in registers */
56  int stack_ptr = 0;
57  int node_addr = kernel_data.bvh.root;
58 
59  /* ray parameters in registers */
60  const float tmax = ray->t;
61  float3 P = ray->P;
62  float3 dir = bvh_clamp_direction(ray->D);
63  float3 idir = bvh_inverse_direction(dir);
64  int object = OBJECT_NONE;
65  float isect_t = tmax;
66 
67 #if BVH_FEATURE(BVH_MOTION)
68  Transform ob_itfm;
69 #endif
70 
71  int num_hits_in_instance = 0;
72 
73  uint num_hits = 0;
74  isect_array->t = tmax;
75 
76  /* traversal loop */
77  do {
78  do {
79  /* traverse internal nodes */
80  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
81  int node_addr_child1, traverse_mask;
82  float dist[2];
83  float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
84 
85  traverse_mask = NODE_INTERSECT(kg,
86  P,
88  dir,
89 #endif
90  idir,
91  isect_t,
92  node_addr,
93  visibility,
94  dist);
95 
96  node_addr = __float_as_int(cnodes.z);
97  node_addr_child1 = __float_as_int(cnodes.w);
98 
99  if (traverse_mask == 3) {
100  /* Both children were intersected, push the farther one. */
101  bool is_closest_child1 = (dist[1] < dist[0]);
102  if (is_closest_child1) {
103  int tmp = node_addr;
104  node_addr = node_addr_child1;
105  node_addr_child1 = tmp;
106  }
107 
108  ++stack_ptr;
109  kernel_assert(stack_ptr < BVH_STACK_SIZE);
110  traversal_stack[stack_ptr] = node_addr_child1;
111  }
112  else {
113  /* One child was intersected. */
114  if (traverse_mask == 2) {
115  node_addr = node_addr_child1;
116  }
117  else if (traverse_mask == 0) {
118  /* Neither child was intersected. */
119  node_addr = traversal_stack[stack_ptr];
120  --stack_ptr;
121  }
122  }
123  }
124 
125  /* if node is leaf, fetch triangle list */
126  if (node_addr < 0) {
127  float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
128  int prim_addr = __float_as_int(leaf.x);
129 
130  if (prim_addr >= 0) {
131  const int prim_addr2 = __float_as_int(leaf.y);
132  const uint type = __float_as_int(leaf.w);
133  bool hit;
134 
135  /* pop */
136  node_addr = traversal_stack[stack_ptr];
137  --stack_ptr;
138 
139  /* primitive intersection */
140  switch (type & PRIMITIVE_ALL) {
141  case PRIMITIVE_TRIANGLE: {
142  /* intersect ray against primitive */
143  for (; prim_addr < prim_addr2; prim_addr++) {
144  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
145  /* only primitives from volume object */
146  uint tri_object = (object == OBJECT_NONE) ?
147  kernel_tex_fetch(__prim_object, prim_addr) :
148  object;
149  int object_flag = kernel_tex_fetch(__object_flag, tri_object);
150  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
151  continue;
152  }
153  hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
154  if (hit) {
155  /* Move on to next entry in intersections array. */
156  isect_array++;
157  num_hits++;
158  num_hits_in_instance++;
159  isect_array->t = isect_t;
160  if (num_hits == max_hits) {
161  if (object != OBJECT_NONE) {
162 #if BVH_FEATURE(BVH_MOTION)
163  float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
164 #else
166  kg, object, OBJECT_INVERSE_TRANSFORM);
167  float t_fac = 1.0f / len(transform_direction(&itfm, dir));
168 #endif
169  for (int i = 0; i < num_hits_in_instance; i++) {
170  (isect_array - i - 1)->t *= t_fac;
171  }
172  }
173  return num_hits;
174  }
175  }
176  }
177  break;
178  }
179 #if BVH_FEATURE(BVH_MOTION)
181  /* intersect ray against primitive */
182  for (; prim_addr < prim_addr2; prim_addr++) {
183  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
184  /* only primitives from volume object */
185  uint tri_object = (object == OBJECT_NONE) ?
186  kernel_tex_fetch(__prim_object, prim_addr) :
187  object;
188  int object_flag = kernel_tex_fetch(__object_flag, tri_object);
189  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
190  continue;
191  }
193  kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
194  if (hit) {
195  /* Move on to next entry in intersections array. */
196  isect_array++;
197  num_hits++;
198  num_hits_in_instance++;
199  isect_array->t = isect_t;
200  if (num_hits == max_hits) {
201  if (object != OBJECT_NONE) {
202 # if BVH_FEATURE(BVH_MOTION)
203  float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
204 # else
206  kg, object, OBJECT_INVERSE_TRANSFORM);
207  float t_fac = 1.0f / len(transform_direction(&itfm, dir));
208 # endif
209  for (int i = 0; i < num_hits_in_instance; i++) {
210  (isect_array - i - 1)->t *= t_fac;
211  }
212  }
213  return num_hits;
214  }
215  }
216  }
217  break;
218  }
219 #endif /* BVH_MOTION */
220  default: {
221  break;
222  }
223  }
224  }
225  else {
226  /* instance push */
227  object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
228  int object_flag = kernel_tex_fetch(__object_flag, object);
229  if (object_flag & SD_OBJECT_HAS_VOLUME) {
230 #if BVH_FEATURE(BVH_MOTION)
231  isect_t = bvh_instance_motion_push(
232  kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
233 #else
234  isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
235 #endif
236 
237  num_hits_in_instance = 0;
238  isect_array->t = isect_t;
239 
240  ++stack_ptr;
241  kernel_assert(stack_ptr < BVH_STACK_SIZE);
243 
244  node_addr = kernel_tex_fetch(__object_node, object);
245  }
246  else {
247  /* pop */
248  object = OBJECT_NONE;
249  node_addr = traversal_stack[stack_ptr];
250  --stack_ptr;
251  }
252  }
253  }
254  } while (node_addr != ENTRYPOINT_SENTINEL);
255 
256  if (stack_ptr >= 0) {
257  kernel_assert(object != OBJECT_NONE);
258 
259  /* Instance pop. */
260  if (num_hits_in_instance) {
261  float t_fac;
262 #if BVH_FEATURE(BVH_MOTION)
263  bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
264 #else
265  bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
266 #endif
267  /* Scale isect->t to adjust for instancing. */
268  for (int i = 0; i < num_hits_in_instance; i++) {
269  (isect_array - i - 1)->t *= t_fac;
270  }
271  }
272  else {
273 #if BVH_FEATURE(BVH_MOTION)
274  bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
275 #else
276  bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
277 #endif
278  }
279 
280  isect_t = tmax;
281  isect_array->t = isect_t;
282 
283  object = OBJECT_NONE;
284  node_addr = traversal_stack[stack_ptr];
285  --stack_ptr;
286  }
287  } while (node_addr != ENTRYPOINT_SENTINEL);
288 
289  return num_hits;
290 }
291 
293  const Ray *ray,
294  Intersection *isect_array,
295  const uint max_hits,
296  const uint visibility)
297 {
298  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect_array, max_hits, visibility);
299 }
300 
301 #undef BVH_FUNCTION_NAME
302 #undef BVH_FUNCTION_FEATURES
303 #undef NODE_INTERSECT
unsigned int uint
Definition: BLI_sys_types.h:83
_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
#define BVH_STACK_SIZE
Definition: bvh_types.h:33
#define BVH_FEATURE(f)
Definition: bvh_types.h:43
#define ENTRYPOINT_SENTINEL
Definition: bvh_types.h:30
#define BVH_HAIR
Definition: bvh_types.h:37
#define BVH_FUNCTION_FULL_NAME(prefix)
Definition: bvh_types.h:41
ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint max_hits, const uint visibility)
#define NODE_INTERSECT
Definition: bvh/bvh.h:80
BLI_Stack * traversal_stack
ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 dir, float time, uint visibility, int object, int prim_addr)
ccl_device_inline float3 bvh_clamp_direction(float3 dir)
Definition: geom_object.h:405
@ OBJECT_INVERSE_TRANSFORM
Definition: geom_object.h:31
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
Definition: geom_object.h:413
ccl_device_inline float bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
Definition: geom_object.h:420
ccl_device_inline float bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
Definition: geom_object.h:440
ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t_fac)
Definition: geom_object.h:457
ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
Definition: geom_object.h:38
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 dir, uint visibility, int object, int prim_addr)
#define kernel_data
#define kernel_assert(cond)
#define kernel_tex_fetch(tex, index)
#define ccl_device
#define ccl_device_inline
@ PRIMITIVE_ALL
Definition: kernel_types.h:702
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel_types.h:687
@ PRIMITIVE_TRIANGLE
Definition: kernel_types.h:686
#define OBJECT_NONE
Definition: kernel_types.h:59
@ SD_OBJECT_HAS_VOLUME
Definition: kernel_types.h:912
static float P(float k)
Definition: math_interp.c:41
ccl_device_inline int __float_as_int(float f)
Definition: util_math.h:202
ccl_device_inline float3 transform_direction(const Transform *t, const float3 a)
uint len