diff options
Diffstat (limited to 'intern/cycles/kernel/bvh')
-rw-r--r-- | intern/cycles/kernel/bvh/bvh.h | 32 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_embree.h | 21 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_local.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_nodes.h | 10 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_shadow_all.h | 105 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_traversal.h | 26 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_types.h | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_util.h | 110 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_volume.h | 13 | ||||
-rw-r--r-- | intern/cycles/kernel/bvh/bvh_volume_all.h | 14 |
10 files changed, 146 insertions, 198 deletions
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index acf29cf1baf..539e9fd05fb 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -25,6 +25,8 @@ * the code has been extended and modified to support more primitives and work * with CPU/CUDA/OpenCL. */ +#pragma once + #ifdef __EMBREE__ # include "kernel/bvh/bvh_embree.h" #endif @@ -152,13 +154,11 @@ ccl_device_inline bool scene_intersect_valid(const Ray *ray) return isfinite_safe(ray->P.x) && isfinite_safe(ray->D.x) && len_squared(ray->D) != 0.0f; } -ccl_device_intersect bool scene_intersect(KernelGlobals *kg, +ccl_device_intersect bool scene_intersect(const KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { - PROFILING_INIT(kg, PROFILING_INTERSECT); - #ifdef __KERNEL_OPTIX__ uint p0 = 0; uint p1 = 0; @@ -238,15 +238,13 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg, } #ifdef __BVH_LOCAL__ -ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, +ccl_device_intersect bool scene_intersect_local(const KernelGlobals *kg, const Ray *ray, LocalIntersection *local_isect, int local_object, uint *lcg_state, int max_hits) { - PROFILING_INIT(kg, PROFILING_INTERSECT_LOCAL); - # ifdef __KERNEL_OPTIX__ uint p0 = ((uint64_t)lcg_state) & 0xFFFFFFFF; uint p1 = (((uint64_t)lcg_state) >> 32) & 0xFFFFFFFF; @@ -313,8 +311,8 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, float3 dir = ray->D; float3 idir = ray->D; Transform ob_itfm; - rtc_ray.tfar = bvh_instance_motion_push( - kg, local_object, ray, &P, &dir, &idir, ray->t, &ob_itfm); + rtc_ray.tfar = ray->t * + bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, &ob_itfm); /* bvh_instance_motion_push() returns the inverse transform but * it's not needed here. */ (void)ob_itfm; @@ -353,15 +351,13 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, #endif #ifdef __SHADOW_RECORD_ALL__ -ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, +ccl_device_intersect bool scene_intersect_shadow_all(const KernelGlobals *kg, const Ray *ray, Intersection *isect, uint visibility, uint max_hits, uint *num_hits) { - PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW_ALL); - # ifdef __KERNEL_OPTIX__ uint p0 = ((uint64_t)isect) & 0xFFFFFFFF; uint p1 = (((uint64_t)isect) >> 32) & 0xFFFFFFFF; @@ -401,17 +397,13 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL); ctx.isect_s = isect; ctx.max_hits = max_hits; - ctx.num_hits = 0; IntersectContext rtc_ctx(&ctx); RTCRay rtc_ray; kernel_embree_setup_ray(*ray, rtc_ray, visibility); rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray); - if (ctx.num_hits > max_hits) { - return true; - } *num_hits = ctx.num_hits; - return rtc_ray.tfar == -INFINITY; + return ctx.opaque_hit; } # endif /* __EMBREE__ */ @@ -439,13 +431,11 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, #endif /* __SHADOW_RECORD_ALL__ */ #ifdef __VOLUME__ -ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg, +ccl_device_intersect bool scene_intersect_volume(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility) { - PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME); - # ifdef __KERNEL_OPTIX__ uint p0 = 0; uint p1 = 0; @@ -498,14 +488,12 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg, #endif /* __VOLUME__ */ #ifdef __VOLUME_RECORD_ALL__ -ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg, +ccl_device_intersect uint scene_intersect_volume_all(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint max_hits, const uint visibility) { - PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME_ALL); - if (!scene_intersect_valid(ray)) { return false; } diff --git a/intern/cycles/kernel/bvh/bvh_embree.h b/intern/cycles/kernel/bvh/bvh_embree.h index 4605c3ea51d..092d770dcac 100644 --- a/intern/cycles/kernel/bvh/bvh_embree.h +++ b/intern/cycles/kernel/bvh/bvh_embree.h @@ -14,14 +14,13 @@ * limitations under the License. */ +#pragma once + #include <embree3/rtcore_ray.h> #include <embree3/rtcore_scene.h> -// clang-format off -#include "kernel/kernel_compat_cpu.h" -#include "kernel/split/kernel_split_data_types.h" -#include "kernel/kernel_globals.h" -// clang-format on +#include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" #include "util/util_vector.h" @@ -36,25 +35,29 @@ struct CCLIntersectContext { RAY_VOLUME_ALL = 4, } RayType; - KernelGlobals *kg; + const KernelGlobals *kg; RayType type; /* for shadow rays */ Intersection *isect_s; int max_hits; int num_hits; + float max_t; + bool opaque_hit; /* for SSS Rays: */ LocalIntersection *local_isect; int local_object_id; uint *lcg_state; - CCLIntersectContext(KernelGlobals *kg_, RayType type_) + CCLIntersectContext(const KernelGlobals *kg_, RayType type_) { kg = kg_; type = type_; max_hits = 1; num_hits = 0; + max_t = FLT_MAX; + opaque_hit = false; isect_s = NULL; local_isect = NULL; local_object_id = -1; @@ -98,7 +101,7 @@ ccl_device_inline void kernel_embree_setup_rayhit(const Ray &ray, rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID; } -ccl_device_inline void kernel_embree_convert_hit(KernelGlobals *kg, +ccl_device_inline void kernel_embree_convert_hit(const KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect) @@ -123,7 +126,7 @@ ccl_device_inline void kernel_embree_convert_hit(KernelGlobals *kg, isect->type = kernel_tex_fetch(__prim_type, isect->prim); } -ccl_device_inline void kernel_embree_convert_sss_hit(KernelGlobals *kg, +ccl_device_inline void kernel_embree_convert_sss_hit(const KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect, diff --git a/intern/cycles/kernel/bvh/bvh_local.h b/intern/cycles/kernel/bvh/bvh_local.h index 4006c9c1632..90b9f410b29 100644 --- a/intern/cycles/kernel/bvh/bvh_local.h +++ b/intern/cycles/kernel/bvh/bvh_local.h @@ -36,7 +36,7 @@ ccl_device #else ccl_device_inline #endif - bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + bool BVH_FUNCTION_FULL_NAME(BVH)(const KernelGlobals *kg, const Ray *ray, LocalIntersection *local_isect, int local_object, @@ -74,9 +74,9 @@ ccl_device_inline if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { #if BVH_FEATURE(BVH_MOTION) Transform ob_itfm; - isect_t = bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, isect_t, &ob_itfm); + isect_t *= bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, &ob_itfm); #else - isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t); + isect_t *= bvh_instance_push(kg, local_object, ray, &P, &dir, &idir); #endif object = local_object; } @@ -196,7 +196,7 @@ ccl_device_inline return false; } -ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, +ccl_device_inline bool BVH_FUNCTION_NAME(const KernelGlobals *kg, const Ray *ray, LocalIntersection *local_isect, int local_object, diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h index 5367bdb633c..15cd0f22213 100644 --- a/intern/cycles/kernel/bvh/bvh_nodes.h +++ b/intern/cycles/kernel/bvh/bvh_nodes.h @@ -16,7 +16,7 @@ // TODO(sergey): Look into avoid use of full Transform and use 3x3 matrix and // 3-vector which might be faster. -ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *kg, +ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(const KernelGlobals *kg, int node_addr, int child) { @@ -28,7 +28,7 @@ ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *k return space; } -ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg, +ccl_device_forceinline int bvh_aligned_node_intersect(const KernelGlobals *kg, const float3 P, const float3 idir, const float t, @@ -76,7 +76,7 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg, #endif } -ccl_device_forceinline bool bvh_unaligned_node_intersect_child(KernelGlobals *kg, +ccl_device_forceinline bool bvh_unaligned_node_intersect_child(const KernelGlobals *kg, const float3 P, const float3 dir, const float t, @@ -102,7 +102,7 @@ ccl_device_forceinline bool bvh_unaligned_node_intersect_child(KernelGlobals *kg return tnear <= tfar; } -ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg, +ccl_device_forceinline int bvh_unaligned_node_intersect(const KernelGlobals *kg, const float3 P, const float3 dir, const float3 idir, @@ -134,7 +134,7 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg, return mask; } -ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg, +ccl_device_forceinline int bvh_node_intersect(const KernelGlobals *kg, const float3 P, const float3 dir, const float3 idir, diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index 2e94b1d7c37..0ae36fccf9b 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -36,7 +36,7 @@ ccl_device #else ccl_device_inline #endif - bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + bool BVH_FUNCTION_FULL_NAME(BVH)(const KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint visibility, @@ -68,10 +68,10 @@ ccl_device_inline Transform ob_itfm; #endif - int num_hits_in_instance = 0; + float t_world_to_instance = 1.0f; *num_hits = 0; - isect_array->t = tmax; + Intersection *isect = isect_array; /* traversal loop */ do { @@ -147,13 +147,14 @@ ccl_device_inline switch (p_type) { case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr); + hit = triangle_intersect( + kg, isect, P, dir, isect_t, visibility, object, prim_addr); break; } #if BVH_FEATURE(BVH_MOTION) case PRIMITIVE_MOTION_TRIANGLE: { hit = motion_triangle_intersect( - kg, isect_array, P, dir, ray->time, visibility, object, prim_addr); + kg, isect, P, dir, isect_t, ray->time, visibility, object, prim_addr); break; } #endif @@ -163,8 +164,16 @@ ccl_device_inline case PRIMITIVE_CURVE_RIBBON: case PRIMITIVE_MOTION_CURVE_RIBBON: { const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr); - hit = curve_intersect( - kg, isect_array, P, dir, visibility, object, prim_addr, ray->time, curve_type); + hit = curve_intersect(kg, + isect, + P, + dir, + isect_t, + visibility, + object, + prim_addr, + ray->time, + curve_type); break; } #endif @@ -176,27 +185,49 @@ ccl_device_inline /* shadow ray early termination */ if (hit) { + /* Convert intersection distance to world space. */ + isect->t /= t_world_to_instance; + /* detect if this surface has a shader with transparent shadows */ /* todo: optimize so primitive visibility flag indicates if * the primitive has a transparent shadow shader? */ - const int flags = intersection_get_shader_flags(kg, isect_array); + const int flags = intersection_get_shader_flags(kg, isect); - /* if no transparent shadows, all light is blocked */ - if (!(flags & SD_HAS_TRANSPARENT_SHADOW)) { - return true; - } - /* if maximum number of hits reached, block all light */ - else if (*num_hits == max_hits) { + if (!(flags & SD_HAS_TRANSPARENT_SHADOW) || max_hits == 0) { + /* If no transparent shadows, all light is blocked and we can + * stop immediately. */ return true; } - /* move on to next entry in intersections array */ - isect_array++; + /* Increase the number of hits, possibly beyond max_hits, we will + * simply not record those and only keep the max_hits closest. */ (*num_hits)++; - num_hits_in_instance++; - isect_array->t = isect_t; + if (*num_hits >= max_hits) { + /* If maximum number of hits reached, find the intersection with + * the largest distance to potentially replace when another hit + * is found. */ + const int num_recorded_hits = min(max_hits, *num_hits); + float max_recorded_t = isect_array[0].t; + int max_recorded_hit = 0; + + for (int i = 1; i < num_recorded_hits; i++) { + if (isect_array[i].t > max_recorded_t) { + max_recorded_t = isect_array[i].t; + max_recorded_hit = i; + } + } + + isect = isect_array + max_recorded_hit; + + /* Limit the ray distance and stop counting hits beyond this. */ + isect_t = max_recorded_t * t_world_to_instance; + } + else { + /* Still have space for intersection, use next hit. */ + isect = isect + 1; + } } prim_addr++; @@ -207,13 +238,14 @@ ccl_device_inline object = kernel_tex_fetch(__prim_object, -prim_addr - 1); #if BVH_FEATURE(BVH_MOTION) - isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm); + t_world_to_instance = bvh_instance_motion_push( + kg, object, ray, &P, &dir, &idir, &ob_itfm); #else - isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); + t_world_to_instance = bvh_instance_push(kg, object, ray, &P, &dir, &idir); #endif - num_hits_in_instance = 0; - isect_array->t = isect_t; + /* Convert intersection to object space. */ + isect_t *= t_world_to_instance; ++stack_ptr; kernel_assert(stack_ptr < BVH_STACK_SIZE); @@ -228,32 +260,19 @@ ccl_device_inline kernel_assert(object != OBJECT_NONE); /* Instance pop. */ - if (num_hits_in_instance) { - float t_fac; - #if BVH_FEATURE(BVH_MOTION) - bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm); + bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm); #else - bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac); + bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); #endif - /* scale isect->t to adjust for instancing */ - for (int i = 0; i < num_hits_in_instance; i++) { - (isect_array - i - 1)->t *= t_fac; - } - } - else { -#if BVH_FEATURE(BVH_MOTION) - bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm); -#else - bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX); -#endif - } - - isect_t = tmax; - isect_array->t = isect_t; + /* Restore world space ray length. If max number of hits exceeded this + * distance is reduced to recorded only the closest hits. If not use + * the original ray length. */ + isect_t = (max_hits && *num_hits > max_hits) ? isect->t : tmax; object = OBJECT_NONE; + t_world_to_instance = 1.0f; node_addr = traversal_stack[stack_ptr]; --stack_ptr; } @@ -262,7 +281,7 @@ ccl_device_inline return false; } -ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, +ccl_device_inline bool BVH_FUNCTION_NAME(const KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint visibility, diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h index 89250a8d60a..a26d8c514f3 100644 --- a/intern/cycles/kernel/bvh/bvh_traversal.h +++ b/intern/cycles/kernel/bvh/bvh_traversal.h @@ -31,7 +31,7 @@ * BVH_MOTION: motion blur rendering */ -ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, +ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility) @@ -136,7 +136,8 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, case PRIMITIVE_TRIANGLE: { for (; prim_addr < prim_addr2; prim_addr++) { kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); - if (triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr)) { + if (triangle_intersect( + kg, isect, P, dir, isect->t, visibility, object, prim_addr)) { /* shadow ray early termination */ if (visibility & PATH_RAY_SHADOW_OPAQUE) return true; @@ -149,7 +150,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, for (; prim_addr < prim_addr2; prim_addr++) { kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type); if (motion_triangle_intersect( - kg, isect, P, dir, ray->time, visibility, object, prim_addr)) { + kg, isect, P, dir, isect->t, ray->time, visibility, object, prim_addr)) { /* shadow ray early termination */ if (visibility & PATH_RAY_SHADOW_OPAQUE) return true; @@ -166,8 +167,16 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, for (; prim_addr < prim_addr2; prim_addr++) { const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr); kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL)); - const bool hit = curve_intersect( - kg, isect, P, dir, visibility, object, prim_addr, ray->time, curve_type); + const bool hit = curve_intersect(kg, + isect, + P, + dir, + isect->t, + visibility, + object, + prim_addr, + ray->time, + curve_type); if (hit) { /* shadow ray early termination */ if (visibility & PATH_RAY_SHADOW_OPAQUE) @@ -184,10 +193,9 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, object = kernel_tex_fetch(__prim_object, -prim_addr - 1); #if BVH_FEATURE(BVH_MOTION) - isect->t = bvh_instance_motion_push( - kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm); + isect->t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); #else - isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); + isect->t *= bvh_instance_push(kg, object, ray, &P, &dir, &idir); #endif ++stack_ptr; @@ -218,7 +226,7 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, return (isect->prim != PRIM_NONE); } -ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, +ccl_device_inline bool BVH_FUNCTION_NAME(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility) diff --git a/intern/cycles/kernel/bvh/bvh_types.h b/intern/cycles/kernel/bvh/bvh_types.h index 98e6ec25d15..6039e707fc3 100644 --- a/intern/cycles/kernel/bvh/bvh_types.h +++ b/intern/cycles/kernel/bvh/bvh_types.h @@ -14,8 +14,7 @@ * limitations under the License. */ -#ifndef __BVH_TYPES__ -#define __BVH_TYPES__ +#pragma once CCL_NAMESPACE_BEGIN @@ -43,5 +42,3 @@ CCL_NAMESPACE_BEGIN #define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0) CCL_NAMESPACE_END - -#endif /* __BVH_TYPES__ */ diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h index b1faebce957..21384457b16 100644 --- a/intern/cycles/kernel/bvh/bvh_util.h +++ b/intern/cycles/kernel/bvh/bvh_util.h @@ -71,86 +71,6 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng) #endif } -/* This function should be used to compute a modified ray start position for - * rays leaving from a surface. The algorithm slightly distorts flat surface - * of a triangle. Surface is lifted by amount h along normal n in the incident - * point. */ - -ccl_device_inline float3 smooth_surface_offset(KernelGlobals *kg, ShaderData *sd, float3 Ng) -{ - float3 V[3], N[3]; - triangle_vertices_and_normals(kg, sd->prim, V, N); - - const float u = sd->u, v = sd->v; - const float w = 1 - u - v; - float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */ - float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */ - - object_normal_transform(kg, sd, &n); /* Normal x scale, world space */ - - /* Parabolic approximation */ - float a = dot(N[2] - N[0], V[0] - V[2]); - float b = dot(N[2] - N[1], V[1] - V[2]); - float c = dot(N[1] - N[0], V[1] - V[0]); - float h = a * u * (u - 1) + (a + b + c) * u * v + b * v * (v - 1); - - /* Check flipped normals */ - if (dot(n, Ng) > 0) { - /* Local linear envelope */ - float h0 = max(max(dot(V[1] - V[0], N[0]), dot(V[2] - V[0], N[0])), 0.0f); - float h1 = max(max(dot(V[0] - V[1], N[1]), dot(V[2] - V[1], N[1])), 0.0f); - float h2 = max(max(dot(V[0] - V[2], N[2]), dot(V[1] - V[2], N[2])), 0.0f); - h0 = max(dot(V[0] - P, N[0]) + h0, 0.0f); - h1 = max(dot(V[1] - P, N[1]) + h1, 0.0f); - h2 = max(dot(V[2] - P, N[2]) + h2, 0.0f); - h = max(min(min(h0, h1), h2), h * 0.5f); - } - else { - float h0 = max(max(dot(V[0] - V[1], N[0]), dot(V[0] - V[2], N[0])), 0.0f); - float h1 = max(max(dot(V[1] - V[0], N[1]), dot(V[1] - V[2], N[1])), 0.0f); - float h2 = max(max(dot(V[2] - V[0], N[2]), dot(V[2] - V[1], N[2])), 0.0f); - h0 = max(dot(P - V[0], N[0]) + h0, 0.0f); - h1 = max(dot(P - V[1], N[1]) + h1, 0.0f); - h2 = max(dot(P - V[2], N[2]) + h2, 0.0f); - h = min(-min(min(h0, h1), h2), h * 0.5f); - } - - return n * h; -} - -/* Ray offset to avoid shadow terminator artifact. */ - -ccl_device_inline float3 ray_offset_shadow(KernelGlobals *kg, ShaderData *sd, float3 L) -{ - float NL = dot(sd->N, L); - bool transmit = (NL < 0.0f); - float3 Ng = (transmit ? -sd->Ng : sd->Ng); - float3 P = ray_offset(sd->P, Ng); - - if ((sd->type & PRIMITIVE_ALL_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) { - const float offset_cutoff = - kernel_tex_fetch(__objects, sd->object).shadow_terminator_geometry_offset; - /* Do ray offset (heavy stuff) only for close to be terminated triangles: - * offset_cutoff = 0.1f means that 10-20% of rays will be affected. Also - * make a smooth transition near the threshold. */ - if (offset_cutoff > 0.0f) { - float NgL = dot(Ng, L); - float offset_amount = 0.0f; - if (NL < offset_cutoff) { - offset_amount = clamp(2.0f - (NgL + NL) / offset_cutoff, 0.0f, 1.0f); - } - else { - offset_amount = clamp(1.0f - NgL / offset_cutoff, 0.0f, 1.0f); - } - if (offset_amount > 0.0f) { - P += smooth_surface_offset(kg, sd, Ng) * offset_amount; - } - } - } - - return P; -} - #if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__)) /* ToDo: Move to another file? */ ccl_device int intersections_compare(const void *a, const void *b) @@ -193,10 +113,10 @@ ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits) } #endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */ -/* Utility to quickly get a shader flags from an intersection. */ +/* Utility to quickly get flags from an intersection. */ -ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals *ccl_restrict kg, - const Intersection *isect) +ccl_device_forceinline int intersection_get_shader_flags(const KernelGlobals *ccl_restrict kg, + const Intersection *ccl_restrict isect) { const int prim = kernel_tex_fetch(__prim_index, isect->prim); int shader = 0; @@ -217,14 +137,14 @@ ccl_device_forceinline int intersection_get_shader_flags(KernelGlobals *ccl_rest return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; } -ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict kg, - const Intersection *isect) +ccl_device_forceinline int intersection_get_shader_from_isect_prim( + const KernelGlobals *ccl_restrict kg, const int isect_prim) { - const int prim = kernel_tex_fetch(__prim_index, isect->prim); + const int prim = kernel_tex_fetch(__prim_index, isect_prim); int shader = 0; #ifdef __HAIR__ - if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) + if (kernel_tex_fetch(__prim_type, isect_prim) & PRIMITIVE_ALL_TRIANGLE) #endif { shader = kernel_tex_fetch(__tri_shader, prim); @@ -239,7 +159,13 @@ ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict k return shader & SHADER_MASK; } -ccl_device_forceinline int intersection_get_object(KernelGlobals *ccl_restrict kg, +ccl_device_forceinline int intersection_get_shader(const KernelGlobals *ccl_restrict kg, + const Intersection *ccl_restrict isect) +{ + return intersection_get_shader_from_isect_prim(kg, isect->prim); +} + +ccl_device_forceinline int intersection_get_object(const KernelGlobals *ccl_restrict kg, const Intersection *ccl_restrict isect) { if (isect->object != OBJECT_NONE) { @@ -249,4 +175,12 @@ ccl_device_forceinline int intersection_get_object(KernelGlobals *ccl_restrict k return kernel_tex_fetch(__prim_object, isect->prim); } +ccl_device_forceinline int intersection_get_object_flags(const KernelGlobals *ccl_restrict kg, + const Intersection *ccl_restrict isect) +{ + const int object = intersection_get_object(kg, isect); + + return kernel_tex_fetch(__object_flag, object); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h index 1f2ea47269b..0411d9c522d 100644 --- a/intern/cycles/kernel/bvh/bvh_volume.h +++ b/intern/cycles/kernel/bvh/bvh_volume.h @@ -35,7 +35,7 @@ ccl_device #else ccl_device_inline #endif - bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + bool BVH_FUNCTION_FULL_NAME(BVH)(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility) @@ -147,7 +147,7 @@ ccl_device_inline if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } - triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr); + triangle_intersect(kg, isect, P, dir, isect->t, visibility, object, prim_addr); } break; } @@ -165,7 +165,7 @@ ccl_device_inline continue; } motion_triangle_intersect( - kg, isect, P, dir, ray->time, visibility, object, prim_addr); + kg, isect, P, dir, isect->t, ray->time, visibility, object, prim_addr); } break; } @@ -181,10 +181,9 @@ ccl_device_inline int object_flag = kernel_tex_fetch(__object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME) { #if BVH_FEATURE(BVH_MOTION) - isect->t = bvh_instance_motion_push( - kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm); + isect->t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); #else - isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t); + isect->t *= bvh_instance_push(kg, object, ray, &P, &dir, &idir); #endif ++stack_ptr; @@ -222,7 +221,7 @@ ccl_device_inline return (isect->prim != PRIM_NONE); } -ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, +ccl_device_inline bool BVH_FUNCTION_NAME(const KernelGlobals *kg, const Ray *ray, Intersection *isect, const uint visibility) diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h index a8664cc4331..4874270f15d 100644 --- a/intern/cycles/kernel/bvh/bvh_volume_all.h +++ b/intern/cycles/kernel/bvh/bvh_volume_all.h @@ -35,7 +35,7 @@ ccl_device #else ccl_device_inline #endif - uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, + uint BVH_FUNCTION_FULL_NAME(BVH)(const KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint max_hits, @@ -150,7 +150,8 @@ ccl_device_inline if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { continue; } - hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr); + hit = triangle_intersect( + kg, isect_array, P, dir, isect_t, visibility, object, prim_addr); if (hit) { /* Move on to next entry in intersections array. */ isect_array++; @@ -190,7 +191,7 @@ ccl_device_inline continue; } hit = motion_triangle_intersect( - kg, isect_array, P, dir, ray->time, visibility, object, prim_addr); + kg, isect_array, P, dir, isect_t, ray->time, visibility, object, prim_addr); if (hit) { /* Move on to next entry in intersections array. */ isect_array++; @@ -228,10 +229,9 @@ ccl_device_inline int object_flag = kernel_tex_fetch(__object_flag, object); if (object_flag & SD_OBJECT_HAS_VOLUME) { #if BVH_FEATURE(BVH_MOTION) - isect_t = bvh_instance_motion_push( - kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm); + isect_t *= bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &ob_itfm); #else - isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t); + isect_t *= bvh_instance_push(kg, object, ray, &P, &dir, &idir); #endif num_hits_in_instance = 0; @@ -289,7 +289,7 @@ ccl_device_inline return num_hits; } -ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg, +ccl_device_inline uint BVH_FUNCTION_NAME(const KernelGlobals *kg, const Ray *ray, Intersection *isect_array, const uint max_hits, |