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:
authorWilliam Leeson <leesonw>2022-01-13 19:12:03 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-01-26 19:51:05 +0300
commita9bb4607660a2f68a78732fd7f5d5280d8075dcb (patch)
treec0234ee456c92c2b121dc461b13337e8f3f3afd0 /intern/cycles/kernel/geom
parent974981a63704e654e620336a3417f8e6fd259cd3 (diff)
Cycles: compute triangle location from barycentric instead of re-intersecting
This is a bit more efficient than what we did before. Ref D12954
Diffstat (limited to 'intern/cycles/kernel/geom')
-rw-r--r--intern/cycles/kernel/geom/motion_triangle_intersect.h112
-rw-r--r--intern/cycles/kernel/geom/motion_triangle_shader.h10
-rw-r--r--intern/cycles/kernel/geom/shader_data.h2
-rw-r--r--intern/cycles/kernel/geom/triangle_intersect.h114
4 files changed, 23 insertions, 215 deletions
diff --git a/intern/cycles/kernel/geom/motion_triangle_intersect.h b/intern/cycles/kernel/geom/motion_triangle_intersect.h
index cb6d210d90f..a11cb88385b 100644
--- a/intern/cycles/kernel/geom/motion_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/motion_triangle_intersect.h
@@ -29,46 +29,19 @@
CCL_NAMESPACE_BEGIN
-/* Refine triangle intersection to more precise hit point. For rays that travel
- * far the precision is often not so good, this reintersects the primitive from
- * a closer distance.
+/**
+ * Use the barycentric coordinates to get the intersection location
*/
-
-ccl_device_inline float3 motion_triangle_refine(KernelGlobals kg,
- ccl_private ShaderData *sd,
- float3 P,
- float3 D,
- float t,
- const int isect_object,
- const int isect_prim,
- float3 verts[3])
+ccl_device_inline float3 motion_triangle_point_from_uv(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ const int isect_object,
+ const int isect_prim,
+ const float u,
+ const float v,
+ float3 verts[3])
{
-#ifdef __INTERSECTION_REFINE__
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- if (UNLIKELY(t == 0.0f)) {
- return P;
- }
- const Transform tfm = object_get_inverse_transform(kg, sd);
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D * t);
- D = normalize_len(D, &t);
- }
-
- P = P + D * t;
-
- /* Compute refined intersection distance. */
- const float3 e1 = verts[0] - verts[2];
- const float3 e2 = verts[1] - verts[2];
- const float3 s1 = cross(D, e2);
-
- const float invdivisor = 1.0f / dot(s1, e1);
- const float3 d = P - verts[2];
- const float3 s2 = cross(d, e1);
- float rt = dot(e2, s2) * invdivisor;
-
- /* Compute refined position. */
- P = P + D * rt;
+ float w = 1.0f - u - v;
+ float3 P = u * verts[0] + v * verts[1] + w * verts[2];
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
const Transform tfm = object_get_transform(kg, sd);
@@ -76,71 +49,8 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals kg,
}
return P;
-#else
- return P + D * t;
-#endif
}
-/* Same as above, except that t is assumed to be in object space
- * for instancing.
- */
-
-#ifdef __BVH_LOCAL__
-# if defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))
-ccl_device_noinline
-# else
-ccl_device_inline
-# endif
- float3
- motion_triangle_refine_local(KernelGlobals kg,
- ccl_private ShaderData *sd,
- float3 P,
- float3 D,
- float t,
- const int isect_object,
- const int isect_prim,
- float3 verts[3])
-{
-# if defined(__KERNEL_GPU_RAYTRACING__)
- /* t is always in world space with OptiX and MetalRT. */
- return motion_triangle_refine(kg, sd, P, D, t, isect_object, isect_prim, verts);
-# else
-# ifdef __INTERSECTION_REFINE__
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- const Transform tfm = object_get_inverse_transform(kg, sd);
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
-
- P = P + D * t;
-
- /* compute refined intersection distance */
- const float3 e1 = verts[0] - verts[2];
- const float3 e2 = verts[1] - verts[2];
- const float3 s1 = cross(D, e2);
-
- const float invdivisor = 1.0f / dot(s1, e1);
- const float3 d = P - verts[2];
- const float3 s2 = cross(d, e1);
- float rt = dot(e2, s2) * invdivisor;
-
- P = P + D * rt;
-
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- const Transform tfm = object_get_transform(kg, sd);
- P = transform_point(&tfm, P);
- }
-
- return P;
-# else /* __INTERSECTION_REFINE__ */
- return P + D * t;
-# endif /* __INTERSECTION_REFINE__ */
-# endif
-}
-#endif /* __BVH_LOCAL__ */
-
/* Ray intersection. We simply compute the vertex positions at the given ray
* time and do a ray intersection with the resulting triangle.
*/
diff --git a/intern/cycles/kernel/geom/motion_triangle_shader.h b/intern/cycles/kernel/geom/motion_triangle_shader.h
index fc7c181882e..15730c83969 100644
--- a/intern/cycles/kernel/geom/motion_triangle_shader.h
+++ b/intern/cycles/kernel/geom/motion_triangle_shader.h
@@ -68,15 +68,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
/* Compute refined position. */
-#ifdef __BVH_LOCAL__
- if (is_local) {
- sd->P = motion_triangle_refine_local(kg, sd, P, D, ray_t, isect_object, isect_prim, verts);
- }
- else
-#endif /* __BVH_LOCAL__*/
- {
- sd->P = motion_triangle_refine(kg, sd, P, D, ray_t, isect_object, isect_prim, verts);
- }
+ sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts);
/* Compute face normal. */
float3 Ng;
if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
diff --git a/intern/cycles/kernel/geom/shader_data.h b/intern/cycles/kernel/geom/shader_data.h
index f5055d8b285..2027190fdd2 100644
--- a/intern/cycles/kernel/geom/shader_data.h
+++ b/intern/cycles/kernel/geom/shader_data.h
@@ -89,7 +89,7 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg,
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* vectors */
- sd->P = triangle_refine(kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim);
+ sd->P = triangle_point_from_uv(kg, sd, isect->object, isect->prim, isect->u, isect->v);
sd->Ng = Ng;
sd->N = Ng;
diff --git a/intern/cycles/kernel/geom/triangle_intersect.h b/intern/cycles/kernel/geom/triangle_intersect.h
index 0169b40bc34..8458cf020a0 100644
--- a/intern/cycles/kernel/geom/triangle_intersect.h
+++ b/intern/cycles/kernel/geom/triangle_intersect.h
@@ -142,116 +142,23 @@ ccl_device_inline bool triangle_intersect_local(KernelGlobals kg,
}
#endif /* __BVH_LOCAL__ */
-/* Refine triangle intersection to more precise hit point. For rays that travel
- * far the precision is often not so good, this reintersects the primitive from
- * a closer distance. */
-
-/* Reintersections uses the paper:
- *
- * Tomas Moeller
- * Fast, minimum storage ray/triangle intersection
- * http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf
+/**
+ * Use the barycentric coordinates to get the intersection location
*/
-
-ccl_device_inline float3 triangle_refine(KernelGlobals kg,
- ccl_private ShaderData *sd,
- float3 P,
- float3 D,
- float t,
- const int isect_object,
- const int isect_prim)
+ccl_device_inline float3 triangle_point_from_uv(KernelGlobals kg,
+ ccl_private ShaderData *sd,
+ const int isect_object,
+ const int isect_prim,
+ const float u,
+ const float v)
{
-#ifdef __INTERSECTION_REFINE__
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- if (UNLIKELY(t == 0.0f)) {
- return P;
- }
- const Transform tfm = object_get_inverse_transform(kg, sd);
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D * t);
- D = normalize_len(D, &t);
- }
-
- P = P + D * t;
-
const uint tri_vindex = kernel_tex_fetch(__tri_vindex, isect_prim).w;
const packed_float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0),
tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1),
tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2);
- 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 det = dot(edge1, pvec);
- if (det != 0.0f) {
- /* If determinant is zero it means ray lies in the plane of
- * the triangle. It is possible in theory due to watertight
- * nature of triangle intersection. For such cases we simply
- * don't refine intersection hoping it'll go all fine.
- */
- float rt = dot(edge2, qvec) / det;
- P = P + D * rt;
- }
-
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- const Transform tfm = object_get_transform(kg, sd);
- P = transform_point(&tfm, P);
- }
-
- return P;
-#else
- return P + D * t;
-#endif
-}
-
-/* Same as above, except that t is assumed to be in object space for
- * instancing.
- */
-ccl_device_inline float3 triangle_refine_local(KernelGlobals kg,
- ccl_private ShaderData *sd,
- float3 P,
- float3 D,
- float t,
- const int isect_object,
- const int isect_prim)
-{
-#if defined(__KERNEL_GPU_RAYTRACING__)
- /* t is always in world space with OptiX and MetalRT. */
- return triangle_refine(kg, sd, P, D, t, isect_object, isect_prim);
-#else
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- const Transform tfm = object_get_inverse_transform(kg, sd);
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
+ float w = 1.0f - u - v;
- P = P + D * t;
-
-# ifdef __INTERSECTION_REFINE__
- const uint tri_vindex = kernel_tex_fetch(__tri_vindex, isect_prim).w;
- const packed_float3 tri_a = kernel_tex_fetch(__tri_verts, tri_vindex + 0),
- tri_b = kernel_tex_fetch(__tri_verts, tri_vindex + 1),
- tri_c = kernel_tex_fetch(__tri_verts, tri_vindex + 2);
- 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 det = dot(edge1, pvec);
- if (det != 0.0f) {
- /* If determinant is zero it means ray lies in the plane of
- * the triangle. It is possible in theory due to watertight
- * nature of triangle intersection. For such cases we simply
- * don't refine intersection hoping it'll go all fine.
- */
- float rt = dot(edge2, qvec) / det;
- P = P + D * rt;
- }
-# endif /* __INTERSECTION_REFINE__ */
+ float3 P = u * tri_a + v * tri_b + w * tri_c;
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
const Transform tfm = object_get_transform(kg, sd);
@@ -259,7 +166,6 @@ ccl_device_inline float3 triangle_refine_local(KernelGlobals kg,
}
return P;
-#endif
}
CCL_NAMESPACE_END