Blender  V2.93
bvh_volume.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  bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
39  const Ray *ray,
40  Intersection *isect,
41  const uint visibility)
42 {
43  /* todo:
44  * - test if pushing distance on the stack helps (for non shadow rays)
45  * - separate version for shadow rays
46  * - likely and unlikely for if() statements
47  * - test restrict attribute for pointers
48  */
49 
50  /* traversal stack in CUDA thread-local memory */
53 
54  /* traversal variables in registers */
55  int stack_ptr = 0;
56  int node_addr = kernel_data.bvh.root;
57 
58  /* ray parameters in registers */
59  float3 P = ray->P;
60  float3 dir = bvh_clamp_direction(ray->D);
61  float3 idir = bvh_inverse_direction(dir);
62  int object = OBJECT_NONE;
63 
64 #if BVH_FEATURE(BVH_MOTION)
65  Transform ob_itfm;
66 #endif
67 
68  isect->t = ray->t;
69  isect->u = 0.0f;
70  isect->v = 0.0f;
71  isect->prim = PRIM_NONE;
72  isect->object = OBJECT_NONE;
73 
74  /* traversal loop */
75  do {
76  do {
77  /* traverse internal nodes */
78  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
79  int node_addr_child1, traverse_mask;
80  float dist[2];
81  float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
82 
83  traverse_mask = NODE_INTERSECT(kg,
84  P,
86  dir,
87 #endif
88  idir,
89  isect->t,
90  node_addr,
91  visibility,
92  dist);
93 
94  node_addr = __float_as_int(cnodes.z);
95  node_addr_child1 = __float_as_int(cnodes.w);
96 
97  if (traverse_mask == 3) {
98  /* Both children were intersected, push the farther one. */
99  bool is_closest_child1 = (dist[1] < dist[0]);
100  if (is_closest_child1) {
101  int tmp = node_addr;
102  node_addr = node_addr_child1;
103  node_addr_child1 = tmp;
104  }
105 
106  ++stack_ptr;
107  kernel_assert(stack_ptr < BVH_STACK_SIZE);
108  traversal_stack[stack_ptr] = node_addr_child1;
109  }
110  else {
111  /* One child was intersected. */
112  if (traverse_mask == 2) {
113  node_addr = node_addr_child1;
114  }
115  else if (traverse_mask == 0) {
116  /* Neither child was intersected. */
117  node_addr = traversal_stack[stack_ptr];
118  --stack_ptr;
119  }
120  }
121  }
122 
123  /* if node is leaf, fetch triangle list */
124  if (node_addr < 0) {
125  float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
126  int prim_addr = __float_as_int(leaf.x);
127 
128  if (prim_addr >= 0) {
129  const int prim_addr2 = __float_as_int(leaf.y);
130  const uint type = __float_as_int(leaf.w);
131 
132  /* pop */
133  node_addr = traversal_stack[stack_ptr];
134  --stack_ptr;
135 
136  /* primitive intersection */
137  switch (type & PRIMITIVE_ALL) {
138  case PRIMITIVE_TRIANGLE: {
139  /* intersect ray against primitive */
140  for (; prim_addr < prim_addr2; prim_addr++) {
141  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
142  /* only primitives from volume object */
143  uint tri_object = (object == OBJECT_NONE) ?
144  kernel_tex_fetch(__prim_object, prim_addr) :
145  object;
146  int object_flag = kernel_tex_fetch(__object_flag, tri_object);
147  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
148  continue;
149  }
150  triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
151  }
152  break;
153  }
154 #if BVH_FEATURE(BVH_MOTION)
156  /* intersect ray against primitive */
157  for (; prim_addr < prim_addr2; prim_addr++) {
158  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
159  /* only primitives from volume object */
160  uint tri_object = (object == OBJECT_NONE) ?
161  kernel_tex_fetch(__prim_object, prim_addr) :
162  object;
163  int object_flag = kernel_tex_fetch(__object_flag, tri_object);
164  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
165  continue;
166  }
168  kg, isect, P, dir, ray->time, visibility, object, prim_addr);
169  }
170  break;
171  }
172 #endif
173  default: {
174  break;
175  }
176  }
177  }
178  else {
179  /* instance push */
180  object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
181  int object_flag = kernel_tex_fetch(__object_flag, object);
182  if (object_flag & SD_OBJECT_HAS_VOLUME) {
183 #if BVH_FEATURE(BVH_MOTION)
184  isect->t = bvh_instance_motion_push(
185  kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
186 #else
187  isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
188 #endif
189 
190  ++stack_ptr;
191  kernel_assert(stack_ptr < BVH_STACK_SIZE);
193 
194  node_addr = kernel_tex_fetch(__object_node, object);
195  }
196  else {
197  /* pop */
198  object = OBJECT_NONE;
199  node_addr = traversal_stack[stack_ptr];
200  --stack_ptr;
201  }
202  }
203  }
204  } while (node_addr != ENTRYPOINT_SENTINEL);
205 
206  if (stack_ptr >= 0) {
207  kernel_assert(object != OBJECT_NONE);
208 
209  /* instance pop */
210 #if BVH_FEATURE(BVH_MOTION)
211  isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
212 #else
213  isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
214 #endif
215 
216  object = OBJECT_NONE;
217  node_addr = traversal_stack[stack_ptr];
218  --stack_ptr;
219  }
220  } while (node_addr != ENTRYPOINT_SENTINEL);
221 
222  return (isect->prim != PRIM_NONE);
223 }
224 
226  const Ray *ray,
227  Intersection *isect,
228  const uint visibility)
229 {
230  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect, visibility);
231 }
232 
233 #undef BVH_FUNCTION_NAME
234 #undef BVH_FUNCTION_FEATURES
235 #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
#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
#define NODE_INTERSECT
Definition: bvh_volume.h:23
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility)
Definition: bvh_volume.h:225
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
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_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 PRIM_NONE
Definition: kernel_types.h:60
#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