7cecee793c1263595732e9df678744eabe9eff9f
[blender-staging.git] / intern / cycles / kernel / bvh / bvh.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* BVH
18  *
19  * Bounding volume hierarchy for ray tracing. We compile different variations
20  * of the same BVH traversal function for faster rendering when some types of
21  * primitives are not needed, using #includes to work around the lack of
22  * C++ templates in OpenCL.
23  *
24  * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs",
25  * the code has been extended and modified to support more primitives and work
26  * with CPU/CUDA/OpenCL. */
27
28 CCL_NAMESPACE_BEGIN
29
30 #include "bvh_types.h"
31
32 /* Common QBVH functions. */
33 #ifdef __QBVH__
34 #  include "qbvh_nodes.h"
35 #endif
36
37 /* Regular BVH traversal */
38
39 #include "bvh_nodes.h"
40
41 #define BVH_FUNCTION_NAME bvh_intersect
42 #define BVH_FUNCTION_FEATURES 0
43 #include "bvh_traversal.h"
44
45 #if defined(__INSTANCING__)
46 #  define BVH_FUNCTION_NAME bvh_intersect_instancing
47 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING
48 #  include "bvh_traversal.h"
49 #endif
50
51 #if defined(__HAIR__)
52 #  define BVH_FUNCTION_NAME bvh_intersect_hair
53 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
54 #  include "bvh_traversal.h"
55 #endif
56
57 #if defined(__OBJECT_MOTION__)
58 #  define BVH_FUNCTION_NAME bvh_intersect_motion
59 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
60 #  include "bvh_traversal.h"
61 #endif
62
63 #if defined(__HAIR__) && defined(__OBJECT_MOTION__)
64 #  define BVH_FUNCTION_NAME bvh_intersect_hair_motion
65 #  define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
66 #  include "bvh_traversal.h"
67 #endif
68
69 /* Subsurface scattering BVH traversal */
70
71 #if defined(__SUBSURFACE__)
72 #  define BVH_FUNCTION_NAME bvh_intersect_subsurface
73 #  define BVH_FUNCTION_FEATURES BVH_HAIR
74 #  include "bvh_subsurface.h"
75
76 #  if defined(__OBJECT_MOTION__)
77 #    define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
78 #    define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
79 #    include "bvh_subsurface.h"
80 #  endif
81 #endif  /* __SUBSURFACE__ */
82
83 /* Volume BVH traversal */
84
85 #if defined(__VOLUME__)
86 #  define BVH_FUNCTION_NAME bvh_intersect_volume
87 #  define BVH_FUNCTION_FEATURES BVH_HAIR
88 #  include "bvh_volume.h"
89
90 #  if defined(__INSTANCING__)
91 #    define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
92 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
93 #    include "bvh_volume.h"
94 #  endif
95
96 #  if defined(__OBJECT_MOTION__)
97 #    define BVH_FUNCTION_NAME bvh_intersect_volume_motion
98 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
99 #    include "bvh_volume.h"
100 #  endif
101 #endif  /* __VOLUME__ */
102
103 /* Record all intersections - Shadow BVH traversal */
104
105 #if defined(__SHADOW_RECORD_ALL__)
106 #  define BVH_FUNCTION_NAME bvh_intersect_shadow_all
107 #  define BVH_FUNCTION_FEATURES 0
108 #  include "bvh_shadow_all.h"
109
110 #  if defined(__INSTANCING__)
111 #    define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
112 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING
113 #    include "bvh_shadow_all.h"
114 #  endif
115
116 #  if defined(__HAIR__)
117 #    define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
118 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
119 #    include "bvh_shadow_all.h"
120 #  endif
121
122 #  if defined(__OBJECT_MOTION__)
123 #    define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
124 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
125 #    include "bvh_shadow_all.h"
126 #  endif
127
128 #  if defined(__HAIR__) && defined(__OBJECT_MOTION__)
129 #    define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
130 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
131 #    include "bvh_shadow_all.h"
132 #  endif
133 #endif  /* __SHADOW_RECORD_ALL__ */
134
135 /* Record all intersections - Volume BVH traversal  */
136
137 #if defined(__VOLUME_RECORD_ALL__)
138 #  define BVH_FUNCTION_NAME bvh_intersect_volume_all
139 #  define BVH_FUNCTION_FEATURES BVH_HAIR
140 #  include "bvh_volume_all.h"
141
142 #  if defined(__INSTANCING__)
143 #    define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
144 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
145 #    include "bvh_volume_all.h"
146 #  endif
147
148 #  if defined(__OBJECT_MOTION__)
149 #    define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
150 #    define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
151 #    include "bvh_volume_all.h"
152 #  endif
153 #endif  /* __VOLUME_RECORD_ALL__ */
154
155 #undef BVH_FEATURE
156 #undef BVH_NAME_JOIN
157 #undef BVH_NAME_EVAL
158 #undef BVH_FUNCTION_FULL_NAME
159
160 ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
161                                           const Ray *ray,
162                                           const uint visibility,
163                                           Intersection *isect,
164                                           uint *lcg_state,
165                                           float difl,
166                                           float extmax)
167 {
168 #ifdef __OBJECT_MOTION__
169         if(kernel_data.bvh.have_motion) {
170 #  ifdef __HAIR__
171                 if(kernel_data.bvh.have_curves)
172                         return bvh_intersect_hair_motion(kg, ray, isect, visibility, lcg_state, difl, extmax);
173 #  endif /* __HAIR__ */
174
175                 return bvh_intersect_motion(kg, ray, isect, visibility);
176         }
177 #endif /* __OBJECT_MOTION__ */
178
179 #ifdef __HAIR__
180         if(kernel_data.bvh.have_curves)
181                 return bvh_intersect_hair(kg, ray, isect, visibility, lcg_state, difl, extmax);
182 #endif /* __HAIR__ */
183
184 #ifdef __KERNEL_CPU__
185
186 #  ifdef __INSTANCING__
187         if(kernel_data.bvh.have_instancing)
188                 return bvh_intersect_instancing(kg, ray, isect, visibility);
189 #  endif /* __INSTANCING__ */
190
191         return bvh_intersect(kg, ray, isect, visibility);
192 #else /* __KERNEL_CPU__ */
193
194 #  ifdef __INSTANCING__
195         return bvh_intersect_instancing(kg, ray, isect, visibility);
196 #  else
197         return bvh_intersect(kg, ray, isect, visibility);
198 #  endif /* __INSTANCING__ */
199
200 #endif /* __KERNEL_CPU__ */
201 }
202
203 #ifdef __SUBSURFACE__
204 ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
205                                                      const Ray *ray,
206                                                      SubsurfaceIntersection *ss_isect,
207                                                      int subsurface_object,
208                                                      uint *lcg_state,
209                                                      int max_hits)
210 {
211 #ifdef __OBJECT_MOTION__
212         if(kernel_data.bvh.have_motion) {
213                 return bvh_intersect_subsurface_motion(kg,
214                                                        ray,
215                                                        ss_isect,
216                                                        subsurface_object,
217                                                        lcg_state,
218                                                        max_hits);
219         }
220 #endif /* __OBJECT_MOTION__ */
221         return bvh_intersect_subsurface(kg,
222                                         ray,
223                                         ss_isect,
224                                         subsurface_object,
225                                         lcg_state,
226                                         max_hits);
227 }
228 #endif
229
230 #ifdef __SHADOW_RECORD_ALL__
231 ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
232 {
233 #  ifdef __OBJECT_MOTION__
234         if(kernel_data.bvh.have_motion) {
235 #    ifdef __HAIR__
236                 if(kernel_data.bvh.have_curves)
237                         return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits);
238 #    endif /* __HAIR__ */
239
240                 return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits);
241         }
242 #  endif /* __OBJECT_MOTION__ */
243
244 #  ifdef __HAIR__
245         if(kernel_data.bvh.have_curves)
246                 return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
247 #  endif /* __HAIR__ */
248
249 #  ifdef __INSTANCING__
250         if(kernel_data.bvh.have_instancing)
251                 return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
252 #  endif /* __INSTANCING__ */
253
254         return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
255 }
256 #endif  /* __SHADOW_RECORD_ALL__ */
257
258 #ifdef __VOLUME__
259 ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
260                                                  const Ray *ray,
261                                                  Intersection *isect,
262                                                  const uint visibility)
263 {
264 #  ifdef __OBJECT_MOTION__
265         if(kernel_data.bvh.have_motion) {
266                 return bvh_intersect_volume_motion(kg, ray, isect, visibility);
267         }
268 #  endif /* __OBJECT_MOTION__ */
269 #  ifdef __KERNEL_CPU__
270 #    ifdef __INSTANCING__
271         if(kernel_data.bvh.have_instancing)
272                 return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
273 #    endif /* __INSTANCING__ */
274         return bvh_intersect_volume(kg, ray, isect, visibility);
275 #  else /* __KERNEL_CPU__ */
276 #    ifdef __INSTANCING__
277         return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
278 #    else
279         return bvh_intersect_volume(kg, ray, isect, visibility);
280 #    endif /* __INSTANCING__ */
281 #  endif /* __KERNEL_CPU__ */
282 }
283 #endif  /* __VOLUME__ */
284
285 #ifdef __VOLUME_RECORD_ALL__
286 ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
287                                                      const Ray *ray,
288                                                      Intersection *isect,
289                                                      const uint max_hits,
290                                                      const uint visibility)
291 {
292 #  ifdef __OBJECT_MOTION__
293         if(kernel_data.bvh.have_motion) {
294                 return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits, visibility);
295         }
296 #  endif /* __OBJECT_MOTION__ */
297 #  ifdef __INSTANCING__
298         if(kernel_data.bvh.have_instancing)
299                 return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits, visibility);
300 #  endif /* __INSTANCING__ */
301         return bvh_intersect_volume_all(kg, ray, isect, max_hits, visibility);
302 }
303 #endif  /* __VOLUME_RECORD_ALL__ */
304
305
306 /* Ray offset to avoid self intersection.
307  *
308  * This function should be used to compute a modified ray start position for
309  * rays leaving from a surface. */
310
311 ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
312 {
313 #ifdef __INTERSECTION_REFINE__
314         const float epsilon_f = 1e-5f;
315         /* ideally this should match epsilon_f, but instancing and motion blur
316          * precision makes it problematic */
317         const float epsilon_test = 1.0f;
318         const int epsilon_i = 32;
319
320         float3 res;
321
322         /* x component */
323         if(fabsf(P.x) < epsilon_test) {
324                 res.x = P.x + Ng.x*epsilon_f;
325         }
326         else {
327                 uint ix = __float_as_uint(P.x);
328                 ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i;
329                 res.x = __uint_as_float(ix);
330         }
331
332         /* y component */
333         if(fabsf(P.y) < epsilon_test) {
334                 res.y = P.y + Ng.y*epsilon_f;
335         }
336         else {
337                 uint iy = __float_as_uint(P.y);
338                 iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i;
339                 res.y = __uint_as_float(iy);
340         }
341
342         /* z component */
343         if(fabsf(P.z) < epsilon_test) {
344                 res.z = P.z + Ng.z*epsilon_f;
345         }
346         else {
347                 uint iz = __float_as_uint(P.z);
348                 iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i;
349                 res.z = __uint_as_float(iz);
350         }
351
352         return res;
353 #else
354         const float epsilon_f = 1e-4f;
355         return P + epsilon_f*Ng;
356 #endif
357 }
358
359 #if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
360 /* ToDo: Move to another file? */
361 ccl_device int intersections_compare(const void *a, const void *b)
362 {
363         const Intersection *isect_a = (const Intersection*)a;
364         const Intersection *isect_b = (const Intersection*)b;
365
366         if(isect_a->t < isect_b->t)
367                 return -1;
368         else if(isect_a->t > isect_b->t)
369                 return 1;
370         else
371                 return 0;
372 }
373 #endif
374
375 CCL_NAMESPACE_END
376