Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/bvh/bvh.h')
-rw-r--r--intern/cycles/kernel/bvh/bvh.h424
1 files changed, 424 insertions, 0 deletions
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
new file mode 100644
index 00000000000..59881738195
--- /dev/null
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -0,0 +1,424 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* BVH
+ *
+ * Bounding volume hierarchy for ray tracing. We compile different variations
+ * of the same BVH traversal function for faster rendering when some types of
+ * primitives are not needed, using #includes to work around the lack of
+ * C++ templates in OpenCL.
+ *
+ * Originally based on "Understanding the Efficiency of Ray Traversal on GPUs",
+ * the code has been extended and modified to support more primitives and work
+ * with CPU/CUDA/OpenCL. */
+
+CCL_NAMESPACE_BEGIN
+
+/* Don't inline intersect functions on GPU, this is faster */
+#ifdef __KERNEL_GPU__
+# define ccl_device_intersect ccl_device_noinline
+#else
+# define ccl_device_intersect ccl_device_inline
+#endif
+
+/* bottom-most stack entry, indicating the end of traversal */
+#define ENTRYPOINT_SENTINEL 0x76543210
+
+/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
+#define BVH_STACK_SIZE 192
+#define BVH_QSTACK_SIZE 384
+
+/* BVH intersection function variations */
+
+#define BVH_INSTANCING 1
+#define BVH_MOTION 2
+#define BVH_HAIR 4
+#define BVH_HAIR_MINIMUM_WIDTH 8
+
+#define BVH_NAME_JOIN(x,y) x ## _ ## y
+#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
+#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
+
+#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+
+/* Debugging heleprs */
+#ifdef __KERNEL_DEBUG__
+# define BVH_DEBUG_INIT() \
+ do { \
+ isect->num_traversal_steps = 0; \
+ isect->num_traversed_instances = 0; \
+ } while(0)
+# define BVH_DEBUG_NEXT_STEP() \
+ do { \
+ ++isect->num_traversal_steps; \
+ } while(0)
+# define BVH_DEBUG_NEXT_INSTANCE() \
+ do { \
+ ++isect->num_traversed_instances; \
+ } while(0)
+#else /* __KERNEL_DEBUG__ */
+# define BVH_DEBUG_INIT()
+# define BVH_DEBUG_NEXT_STEP()
+# define BVH_DEBUG_NEXT_INSTANCE()
+#endif /* __KERNEL_DEBUG__ */
+
+
+/* Common QBVH functions. */
+#ifdef __QBVH__
+# include "qbvh_nodes.h"
+#endif
+
+/* Regular BVH traversal */
+
+#include "bvh_nodes.h"
+
+#define BVH_FUNCTION_NAME bvh_intersect
+#define BVH_FUNCTION_FEATURES 0
+#include "bvh_traversal.h"
+
+#if defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING
+# include "bvh_traversal.h"
+#endif
+
+#if defined(__HAIR__)
+# define BVH_FUNCTION_NAME bvh_intersect_hair
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
+# include "bvh_traversal.h"
+#endif
+
+#if defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+# include "bvh_traversal.h"
+#endif
+
+#if defined(__HAIR__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_hair_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
+# include "bvh_traversal.h"
+#endif
+
+/* Subsurface scattering BVH traversal */
+
+#if defined(__SUBSURFACE__)
+# define BVH_FUNCTION_NAME bvh_intersect_subsurface
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_subsurface.h"
+#endif
+
+#if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
+# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
+# include "bvh_subsurface.h"
+#endif
+
+/* Volume BVH traversal */
+
+#if defined(__VOLUME__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume.h"
+#endif
+
+#if defined(__VOLUME__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume.h"
+#endif
+
+/* Record all intersections - Shadow BVH traversal */
+
+#if defined(__SHADOW_RECORD_ALL__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all
+# define BVH_FUNCTION_FEATURES 0
+# include "bvh_shadow_all.h"
+#endif
+
+#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING
+# include "bvh_shadow_all.h"
+#endif
+
+#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_shadow_all.h"
+#endif
+
+#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+# include "bvh_shadow_all.h"
+#endif
+
+#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
+# include "bvh_shadow_all.h"
+#endif
+
+/* Record all intersections - Volume BVH traversal */
+
+#if defined(__VOLUME_RECORD_ALL__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_all
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_volume_all.h"
+#endif
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume_all.h"
+#endif
+
+#if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume_all.h"
+#endif
+
+#undef BVH_FEATURE
+#undef BVH_NAME_JOIN
+#undef BVH_NAME_EVAL
+#undef BVH_FUNCTION_FULL_NAME
+
+ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
+ const Ray *ray,
+ const uint visibility,
+ Intersection *isect,
+ uint *lcg_state,
+ float difl,
+ float extmax)
+{
+#ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+# ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_hair_motion(kg, ray, isect, visibility, lcg_state, difl, extmax);
+# endif /* __HAIR__ */
+
+ return bvh_intersect_motion(kg, ray, isect, visibility);
+ }
+#endif /* __OBJECT_MOTION__ */
+
+#ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_hair(kg, ray, isect, visibility, lcg_state, difl, extmax);
+#endif /* __HAIR__ */
+
+#ifdef __KERNEL_CPU__
+
+# ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_instancing(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+
+ return bvh_intersect(kg, ray, isect, visibility);
+#else /* __KERNEL_CPU__ */
+
+# ifdef __INSTANCING__
+ return bvh_intersect_instancing(kg, ray, isect, visibility);
+# else
+ return bvh_intersect(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+
+#endif /* __KERNEL_CPU__ */
+}
+
+#ifdef __SUBSURFACE__
+ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
+ const Ray *ray,
+ SubsurfaceIntersection *ss_isect,
+ int subsurface_object,
+ uint *lcg_state,
+ int max_hits)
+{
+#ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+ return bvh_intersect_subsurface_motion(kg,
+ ray,
+ ss_isect,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+ }
+#endif /* __OBJECT_MOTION__ */
+ return bvh_intersect_subsurface(kg,
+ ray,
+ ss_isect,
+ subsurface_object,
+ lcg_state,
+ max_hits);
+}
+#endif
+
+#ifdef __SHADOW_RECORD_ALL__
+ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
+{
+# ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+# ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits);
+# endif /* __HAIR__ */
+
+ return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits);
+ }
+# endif /* __OBJECT_MOTION__ */
+
+# ifdef __HAIR__
+ if(kernel_data.bvh.have_curves)
+ return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
+# endif /* __HAIR__ */
+
+# ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
+# endif /* __INSTANCING__ */
+
+ return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
+}
+#endif /* __SHADOW_RECORD_ALL__ */
+
+#ifdef __VOLUME__
+ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility)
+{
+# ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+ return bvh_intersect_volume_motion(kg, ray, isect, visibility);
+ }
+# endif /* __OBJECT_MOTION__ */
+# ifdef __KERNEL_CPU__
+# ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+ return bvh_intersect_volume(kg, ray, isect, visibility);
+# else /* __KERNEL_CPU__ */
+# ifdef __INSTANCING__
+ return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
+# else
+ return bvh_intersect_volume(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+# endif /* __KERNEL_CPU__ */
+}
+#endif /* __VOLUME__ */
+
+#ifdef __VOLUME_RECORD_ALL__
+ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint max_hits,
+ const uint visibility)
+{
+# ifdef __OBJECT_MOTION__
+ if(kernel_data.bvh.have_motion) {
+ return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits, visibility);
+ }
+# endif /* __OBJECT_MOTION__ */
+# ifdef __INSTANCING__
+ if(kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits, visibility);
+# endif /* __INSTANCING__ */
+ return bvh_intersect_volume_all(kg, ray, isect, max_hits, visibility);
+}
+#endif /* __VOLUME_RECORD_ALL__ */
+
+
+/* Ray offset to avoid self intersection.
+ *
+ * This function should be used to compute a modified ray start position for
+ * rays leaving from a surface. */
+
+ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
+{
+#ifdef __INTERSECTION_REFINE__
+ const float epsilon_f = 1e-5f;
+ /* ideally this should match epsilon_f, but instancing and motion blur
+ * precision makes it problematic */
+ const float epsilon_test = 1.0f;
+ const int epsilon_i = 32;
+
+ float3 res;
+
+ /* x component */
+ if(fabsf(P.x) < epsilon_test) {
+ res.x = P.x + Ng.x*epsilon_f;
+ }
+ else {
+ uint ix = __float_as_uint(P.x);
+ ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i;
+ res.x = __uint_as_float(ix);
+ }
+
+ /* y component */
+ if(fabsf(P.y) < epsilon_test) {
+ res.y = P.y + Ng.y*epsilon_f;
+ }
+ else {
+ uint iy = __float_as_uint(P.y);
+ iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i;
+ res.y = __uint_as_float(iy);
+ }
+
+ /* z component */
+ if(fabsf(P.z) < epsilon_test) {
+ res.z = P.z + Ng.z*epsilon_f;
+ }
+ else {
+ uint iz = __float_as_uint(P.z);
+ iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i;
+ res.z = __uint_as_float(iz);
+ }
+
+ return res;
+#else
+ const float epsilon_f = 1e-4f;
+ return P + epsilon_f*Ng;
+#endif
+}
+
+#if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
+/* ToDo: Move to another file? */
+ccl_device int intersections_compare(const void *a, const void *b)
+{
+ const Intersection *isect_a = (const Intersection*)a;
+ const Intersection *isect_b = (const Intersection*)b;
+
+ if(isect_a->t < isect_b->t)
+ return -1;
+ else if(isect_a->t > isect_b->t)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
+CCL_NAMESPACE_END
+