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/geom/geom_triangle_intersect.h')
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h171
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,