Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/bvh/bvh_util.h
| Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | #ifdef __INTERSECTION_REFINE__ | ||||
| return res; | return res; | ||||
| #else | #else | ||||
| const float epsilon_f = 1e-4f; | const float epsilon_f = 1e-4f; | ||||
| return P + epsilon_f * Ng; | return P + epsilon_f * Ng; | ||||
| #endif | #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__)) | #if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__)) | ||||
| /* ToDo: Move to another file? */ | /* ToDo: Move to another file? */ | ||||
| ccl_device int intersections_compare(const void *a, const void *b) | ccl_device int intersections_compare(const void *a, const void *b) | ||||
| { | { | ||||
| const Intersection *isect_a = (const Intersection *)a; | const Intersection *isect_a = (const Intersection *)a; | ||||
| const Intersection *isect_b = (const Intersection *)b; | const Intersection *isect_b = (const Intersection *)b; | ||||
| if (isect_a->t < isect_b->t) | if (isect_a->t < isect_b->t) | ||||
| Show All 26 Lines | do { | ||||
| --num_hits; | --num_hits; | ||||
| } while (swapped); | } while (swapped); | ||||
| # else | # else | ||||
| qsort(hits, num_hits, sizeof(Intersection), intersections_compare); | qsort(hits, num_hits, sizeof(Intersection), intersections_compare); | ||||
| # endif | # endif | ||||
| } | } | ||||
| #endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */ | #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, | ccl_device_forceinline int intersection_get_shader_flags(const KernelGlobals *ccl_restrict kg, | ||||
| const Intersection *isect) | const Intersection *ccl_restrict isect) | ||||
| { | { | ||||
| const int prim = kernel_tex_fetch(__prim_index, isect->prim); | const int prim = kernel_tex_fetch(__prim_index, isect->prim); | ||||
| int shader = 0; | int shader = 0; | ||||
| #ifdef __HAIR__ | #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 | #endif | ||||
| { | { | ||||
| shader = kernel_tex_fetch(__tri_shader, prim); | shader = kernel_tex_fetch(__tri_shader, prim); | ||||
| } | } | ||||
| #ifdef __HAIR__ | #ifdef __HAIR__ | ||||
| else { | else { | ||||
| float4 str = kernel_tex_fetch(__curves, prim); | float4 str = kernel_tex_fetch(__curves, prim); | ||||
| shader = __float_as_int(str.z); | shader = __float_as_int(str.z); | ||||
| } | } | ||||
| #endif | #endif | ||||
| return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; | return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags; | ||||
| } | } | ||||
| ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict kg, | ccl_device_forceinline int intersection_get_shader_from_isect_prim( | ||||
| const Intersection *isect) | 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; | int shader = 0; | ||||
| #ifdef __HAIR__ | #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 | #endif | ||||
| { | { | ||||
| shader = kernel_tex_fetch(__tri_shader, prim); | shader = kernel_tex_fetch(__tri_shader, prim); | ||||
| } | } | ||||
| #ifdef __HAIR__ | #ifdef __HAIR__ | ||||
| else { | else { | ||||
| float4 str = kernel_tex_fetch(__curves, prim); | float4 str = kernel_tex_fetch(__curves, prim); | ||||
| shader = __float_as_int(str.z); | shader = __float_as_int(str.z); | ||||
| } | } | ||||
| #endif | #endif | ||||
| return shader & SHADER_MASK; | 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) | const Intersection *ccl_restrict isect) | ||||
| { | { | ||||
| if (isect->object != OBJECT_NONE) { | if (isect->object != OBJECT_NONE) { | ||||
| return isect->object; | return isect->object; | ||||
| } | } | ||||
| return kernel_tex_fetch(__prim_object, isect->prim); | 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 | CCL_NAMESPACE_END | ||||