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