diff options
Diffstat (limited to 'intern/cycles/kernel/geom/geom_triangle_intersect.h')
-rw-r--r-- | intern/cycles/kernel/geom/geom_triangle_intersect.h | 171 |
1 files changed, 84 insertions, 87 deletions
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 06917dc16d8..d6e4abc8267 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -14,7 +14,7 @@ * limitations under the License. */ -/* Triangle/Ray intersections . +/* Triangle/Ray intersections. * * For BVH ray intersection we use a precomputed triangle storage to accelerate * intersection at the cost of more memory usage. @@ -50,7 +50,7 @@ typedef struct IsectPrecalc { } IsectPrecalc; /* Workaround for CUDA toolkit 6.5.16. */ -#if defined(__KERNEL_CPU__) || !defined(__KERNEL_CUDA_EXPERIMENTAL__) || __CUDA_ARCH__ < 500 +#if defined(__KERNEL_CPU__) || !defined(__KERNEL_EXPERIMENTAL__) || __CUDA_ARCH__ < 500 # if (defined(i386) || defined(_M_IX86)) ccl_device_noinline # else @@ -60,7 +60,7 @@ ccl_device_inline ccl_device_noinline #endif void triangle_intersect_precalc(float3 dir, - IsectPrecalc *isect_precalc) + IsectPrecalc *isect_precalc) { /* Calculate dimension where the ray direction is maximal. */ int kz = util_max_axis(make_float3(fabsf(dir.x), @@ -77,10 +77,10 @@ void triangle_intersect_precalc(float3 dir, } /* Calculate the shear constants. */ - float inf_dir_z = 1.0f / IDX(dir, kz); - isect_precalc->Sx = IDX(dir, kx) * inf_dir_z; - isect_precalc->Sy = IDX(dir, ky) * inf_dir_z; - isect_precalc->Sz = inf_dir_z; + float inv_dir_z = 1.0f / IDX(dir, kz); + isect_precalc->Sx = IDX(dir, kx) * inv_dir_z; + isect_precalc->Sy = IDX(dir, ky) * inv_dir_z; + isect_precalc->Sz = inv_dir_z; /* Store the dimensions. */ isect_precalc->kx = kx; @@ -98,7 +98,6 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const IsectPrecalc *isect_precalc, Intersection *isect, float3 P, - float3 dir, uint visibility, int object, int triAddr) @@ -111,14 +110,22 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, const float Sz = isect_precalc->Sz; /* Calculate vertices relative to ray origin. */ - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2)); - - const float3 A = tri[0] - P; - const float3 B = tri[1] - P; - const float3 C = tri[2] - P; + float4 tri_a, tri_b, tri_c; + if (kernel_data.bvh.use_tri_storage) { + tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0); + tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1); + tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); + } + else { + const int prim = kernel_tex_fetch(__prim_index, triAddr); + const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)); + tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)); + tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)); + } + const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); + const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); + const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); @@ -154,15 +161,10 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, * the hit distance. */ const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; - - /* Perform "near clipping". */ - const float abs_T = xor_signmast(T, sign_mask); - if(abs_T < 0.0f) { - return false; - } - /* Perform "far clipping". */ - const float abs_det = xor_signmast(det, sign_mask); - if(abs_T > isect->t * abs_det) { + const float sign_T = xor_signmast(T, sign_mask); + if((sign_T < 0.0f) || + (sign_T > isect->t * xor_signmast(det, sign_mask))) + { return false; } @@ -174,37 +176,12 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, { /* Normalize U, V, W, and T. */ const float inv_det = 1.0f / det; - const float t = T * inv_det; - -#ifdef __INTERSECTION_REFINE__ - /* TODO(sergey): When intersection refine is enabled ray is being - * pushed by quite small epsilon from the surface, which causes - * numerical issues of watertight Woop intersection check with - * huge triangles. - * - * Here we're working this around by checking distance in Pleucker - * coordinates if intersection is suspiciously close to the point - * in order to eliminate self-shadowing. - * - * Ideally we need to solve this in Woop intersection code but - * it's quite tricky. - */ - if(UNLIKELY(abs_det > 100000.0f && t < 1e-3f)) { - const float3 Ng = cross(A - B, C - A); - const float pleucker_den = dot(Ng, dir); - const float pleucker_T = dot(A, Ng); - if(UNLIKELY(pleucker_T * pleucker_den < 0.0f)) { - return false; - } - } -#endif - isect->prim = triAddr; isect->object = object; isect->type = PRIMITIVE_TRIANGLE; isect->u = U * inv_det; isect->v = V * inv_det; - isect->t = t; + isect->t = T * inv_det; return true; } return false; @@ -221,7 +198,6 @@ ccl_device_inline void triangle_intersect_subsurface( const IsectPrecalc *isect_precalc, Intersection *isect_array, float3 P, - float3 dir, int object, int triAddr, float tmax, @@ -237,14 +213,22 @@ ccl_device_inline void triangle_intersect_subsurface( const float Sz = isect_precalc->Sz; /* Calculate vertices relative to ray origin. */ - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2)); - - const float3 A = tri[0] - P; - const float3 B = tri[1] - P; - const float3 C = tri[2] - P; + float4 tri_a, tri_b, tri_c; + if (kernel_data.bvh.use_tri_storage) { + tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0); + tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1); + tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); + } + else { + const int prim = kernel_tex_fetch(__prim_index, triAddr); + const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)); + tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)); + tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)); + } + const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z); + const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z); + const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z); const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz); const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz); @@ -279,13 +263,10 @@ ccl_device_inline void triangle_intersect_subsurface( /* Calculate scaled z−coordinates of vertices and use them to calculate * the hit distance. */ - const float Az = Sz * A_kz; - const float Bz = Sz * B_kz; - const float Cz = Sz * C_kz; - const float T = U * Az + V * Bz + W * Cz; - - if ((xor_signmast(T, sign_mask) < 0.0f) || - (xor_signmast(T, sign_mask) > tmax * xor_signmast(det, sign_mask))) + const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; + const float sign_T = xor_signmast(T, sign_mask); + if((sign_T < 0.0f) || + (sign_T > tmax * xor_signmast(det, sign_mask))) { return; } @@ -345,7 +326,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, return P; } #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif @@ -357,14 +338,22 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, P = P + D*t; - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2)); - - float3 edge1 = tri[0] - tri[2]; - float3 edge2 = tri[1] - tri[2]; - float3 tvec = P - tri[2]; + float4 tri_a, tri_b, tri_c; + if (kernel_data.bvh.use_tri_storage) { + tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0); + tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1); + tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2); + } + else { + const int prim = kernel_tex_fetch(__prim_index, isect->prim); + const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)); + tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)); + tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)); + } + float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z); + float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z); + float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z); float3 qvec = cross(tvec, edge1); float3 pvec = cross(D, edge2); float rt = dot(edge2, qvec) / dot(edge1, pvec); @@ -373,7 +362,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg, if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif @@ -402,7 +391,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, #ifdef __INTERSECTION_REFINE__ if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_itfm; + Transform tfm = ccl_fetch(sd, ob_itfm); #else Transform tfm = object_fetch_transform(kg, isect->object, @@ -416,14 +405,22 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, P = P + D*t; - float3 tri[3]; - tri[0] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0)); - tri[1] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1)); - tri[2] = float4_to_float3(kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2)); - - float3 edge1 = tri[0] - tri[2]; - float3 edge2 = tri[1] - tri[2]; - float3 tvec = P - tri[2]; + float4 tri_a, tri_b, tri_c; + if (kernel_data.bvh.use_tri_storage) { + tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0); + tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1); + tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2); + } + else { + const int prim = kernel_tex_fetch(__prim_index, isect->prim); + const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); + tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)); + tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)); + tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)); + } + float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z); + float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z); + float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z); float3 qvec = cross(tvec, edge1); float3 pvec = cross(D, edge2); float rt = dot(edge2, qvec) / dot(edge1, pvec); @@ -432,7 +429,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, if(isect->object != OBJECT_NONE) { #ifdef __OBJECT_MOTION__ - Transform tfm = sd->ob_tfm; + Transform tfm = ccl_fetch(sd, ob_tfm); #else Transform tfm = object_fetch_transform(kg, isect->object, |