Blender  V2.93
bvh_local.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-2013, 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 finding local intersections
27  * around the shading point, for subsurface scattering and bevel. We disable
28  * various features for performance, and for instanced objects avoid traversing
29  * other parts of the scene.
30  *
31  * BVH_MOTION: motion blur rendering
32  */
33 
34 #ifndef __KERNEL_GPU__
36 #else
38 #endif
39  bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
40  const Ray *ray,
41  LocalIntersection *local_isect,
42  int local_object,
43  uint *lcg_state,
44  int max_hits)
45 {
46  /* todo:
47  * - test if pushing distance on the stack helps (for non shadow rays)
48  * - separate version for shadow rays
49  * - likely and unlikely for if() statements
50  * - test restrict attribute for pointers
51  */
52 
53  /* traversal stack in CUDA thread-local memory */
56 
57  /* traversal variables in registers */
58  int stack_ptr = 0;
59  int node_addr = kernel_tex_fetch(__object_node, local_object);
60 
61  /* ray parameters in registers */
62  float3 P = ray->P;
63  float3 dir = bvh_clamp_direction(ray->D);
64  float3 idir = bvh_inverse_direction(dir);
65  int object = OBJECT_NONE;
66  float isect_t = ray->t;
67 
68  if (local_isect != NULL) {
69  local_isect->num_hits = 0;
70  }
71  kernel_assert((local_isect == NULL) == (max_hits == 0));
72 
73  const int object_flag = kernel_tex_fetch(__object_flag, local_object);
74  if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
75 #if BVH_FEATURE(BVH_MOTION)
76  Transform ob_itfm;
77  isect_t = bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
78 #else
79  isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
80 #endif
81  object = local_object;
82  }
83 
84  /* traversal loop */
85  do {
86  do {
87  /* traverse internal nodes */
88  while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
89  int node_addr_child1, traverse_mask;
90  float dist[2];
91  float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
92 
93  traverse_mask = NODE_INTERSECT(kg,
94  P,
96  dir,
97 #endif
98  idir,
99  isect_t,
100  node_addr,
102  dist);
103 
104  node_addr = __float_as_int(cnodes.z);
105  node_addr_child1 = __float_as_int(cnodes.w);
106 
107  if (traverse_mask == 3) {
108  /* Both children were intersected, push the farther one. */
109  bool is_closest_child1 = (dist[1] < dist[0]);
110  if (is_closest_child1) {
111  int tmp = node_addr;
112  node_addr = node_addr_child1;
113  node_addr_child1 = tmp;
114  }
115 
116  ++stack_ptr;
117  kernel_assert(stack_ptr < BVH_STACK_SIZE);
118  traversal_stack[stack_ptr] = node_addr_child1;
119  }
120  else {
121  /* One child was intersected. */
122  if (traverse_mask == 2) {
123  node_addr = node_addr_child1;
124  }
125  else if (traverse_mask == 0) {
126  /* Neither child was intersected. */
127  node_addr = traversal_stack[stack_ptr];
128  --stack_ptr;
129  }
130  }
131  }
132 
133  /* if node is leaf, fetch triangle list */
134  if (node_addr < 0) {
135  float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
136  int prim_addr = __float_as_int(leaf.x);
137 
138  const int prim_addr2 = __float_as_int(leaf.y);
139  const uint type = __float_as_int(leaf.w);
140 
141  /* pop */
142  node_addr = traversal_stack[stack_ptr];
143  --stack_ptr;
144 
145  /* primitive intersection */
146  switch (type & PRIMITIVE_ALL) {
147  case PRIMITIVE_TRIANGLE: {
148  /* intersect ray against primitive */
149  for (; prim_addr < prim_addr2; prim_addr++) {
150  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
151  if (triangle_intersect_local(kg,
152  local_isect,
153  P,
154  dir,
155  object,
156  local_object,
157  prim_addr,
158  isect_t,
159  lcg_state,
160  max_hits)) {
161  return true;
162  }
163  }
164  break;
165  }
166 #if BVH_FEATURE(BVH_MOTION)
168  /* intersect ray against primitive */
169  for (; prim_addr < prim_addr2; prim_addr++) {
170  kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
171  if (motion_triangle_intersect_local(kg,
172  local_isect,
173  P,
174  dir,
175  ray->time,
176  object,
177  local_object,
178  prim_addr,
179  isect_t,
180  lcg_state,
181  max_hits)) {
182  return true;
183  }
184  }
185  break;
186  }
187 #endif
188  default: {
189  break;
190  }
191  }
192  }
193  } while (node_addr != ENTRYPOINT_SENTINEL);
194  } while (node_addr != ENTRYPOINT_SENTINEL);
195 
196  return false;
197 }
198 
200  const Ray *ray,
201  LocalIntersection *local_isect,
202  int local_object,
203  uint *lcg_state,
204  int max_hits)
205 {
206  return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
207 }
208 
209 #undef BVH_FUNCTION_NAME
210 #undef BVH_FUNCTION_FEATURES
211 #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
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, LocalIntersection *local_isect, int local_object, uint *lcg_state, int max_hits)
Definition: bvh_local.h:199
#define NODE_INTERSECT
Definition: bvh_local.h:23
#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
Definition: bvh/bvh.h:80
BLI_Stack * traversal_stack
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
#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
@ PATH_RAY_ALL_VISIBILITY
Definition: kernel_types.h:295
#define OBJECT_NONE
Definition: kernel_types.h:59
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel_types.h:908
static float P(float k)
Definition: math_interp.c:41
ccl_device_inline int __float_as_int(float f)
Definition: util_math.h:202