Fix T74939: Random Walk subsurface appearance in OptiX does not match other engines
authorPatrick Mours <pmours@nvidia.com>
Wed, 25 Mar 2020 17:30:39 +0000 (18:30 +0100)
committerPatrick Mours <pmours@nvidia.com>
Thu, 26 Mar 2020 12:00:09 +0000 (13:00 +0100)
Random Walk subsurface scattering did look different with OptiX because transmittance is
calculated based on the hit distance, but the OptiX implementation of `scene_intersect_local`
would return the distance in world space, while the Cycles BVH version returns it in object
space. This fixes the problem by simply skipping the object->world transforms in all the
places using the result of `scene_intersect_local` with OptiX.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D7232

intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
intern/cycles/kernel/geom/geom_triangle_intersect.h
intern/cycles/kernel/kernel_subsurface.h

index 49d4829af38fdfead6fd0763c7f0630ccbfa2a6f..859d919f0bb4aa68a90df290142e0cc827d4a565 100644 (file)
@@ -103,17 +103,21 @@ ccl_device_inline
                                  const Ray *ray,
                                  float3 verts[3])
 {
+#  ifdef __KERNEL_OPTIX__
+  /* isect->t is always in world space with OptiX. */
+  return motion_triangle_refine(kg, sd, isect, ray, verts);
+#  else
   float3 P = ray->P;
   float3 D = ray->D;
   float t = isect->t;
 
-#  ifdef __INTERSECTION_REFINE__
+#    ifdef __INTERSECTION_REFINE__
   if (isect->object != OBJECT_NONE) {
-#    ifdef __OBJECT_MOTION__
+#      ifdef __OBJECT_MOTION__
     Transform tfm = sd->ob_itfm;
-#    else
+#      else
     Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#    endif
+#      endif
 
     P = transform_point(&tfm, P);
     D = transform_direction(&tfm, D);
@@ -135,19 +139,20 @@ ccl_device_inline
   P = P + D * rt;
 
   if (isect->object != OBJECT_NONE) {
-#    ifdef __OBJECT_MOTION__
+#      ifdef __OBJECT_MOTION__
     Transform tfm = sd->ob_tfm;
-#    else
+#      else
     Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#    endif
+#      endif
 
     P = transform_point(&tfm, P);
   }
 
   return P;
-#  else  /* __INTERSECTION_REFINE__ */
+#    else  /* __INTERSECTION_REFINE__ */
   return P + D * t;
-#  endif /* __INTERSECTION_REFINE__ */
+#    endif /* __INTERSECTION_REFINE__ */
+#  endif
 }
 #endif /* __BVH_LOCAL__ */
 
index 68075199402baa43cb6475db45074f4cc82f6ad4..6604806f73b3890928f1a057822316ee896f8ed8 100644 (file)
@@ -690,16 +690,20 @@ ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
                                                const Intersection *isect,
                                                const Ray *ray)
 {
+#ifdef __KERNEL_OPTIX__
+  /* isect->t is always in world space with OptiX. */
+  return triangle_refine(kg, sd, isect, ray);
+#else
   float3 P = ray->P;
   float3 D = ray->D;
   float t = isect->t;
 
   if (isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
+#  ifdef __OBJECT_MOTION__
     Transform tfm = sd->ob_itfm;
-#else
+#  else
     Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
+#  endif
 
     P = transform_point(&tfm, P);
     D = transform_direction(&tfm, D);
@@ -708,7 +712,7 @@ ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
 
   P = P + D * t;
 
-#ifdef __INTERSECTION_REFINE__
+#  ifdef __INTERSECTION_REFINE__
   const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
   const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0),
                tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1),
@@ -728,19 +732,20 @@ ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
     float rt = dot(edge2, qvec) / det;
     P = P + D * rt;
   }
-#endif /* __INTERSECTION_REFINE__ */
+#  endif /* __INTERSECTION_REFINE__ */
 
   if (isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
+#  ifdef __OBJECT_MOTION__
     Transform tfm = sd->ob_tfm;
-#else
+#  else
     Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
+#  endif
 
     P = transform_point(&tfm, P);
   }
 
   return P;
+#endif
 }
 
 CCL_NAMESPACE_END
index 23e30db1b08932acd1cd51f5c721bec29d7ce968..ed8572467ea90cdc89aacc27cf71d525d1d64ecc 100644 (file)
@@ -428,12 +428,17 @@ ccl_device_noinline
     hit = (ss_isect->num_hits > 0);
 
     if (hit) {
+#ifdef __KERNEL_OPTIX__
+      /* t is always in world space with OptiX. */
+      t = ss_isect->hits[0].t;
+#else
       /* Compute world space distance to surface hit. */
       float3 D = ray->D;
       object_inverse_dir_transform(kg, sd, &D);
       D = normalize(D) * ss_isect->hits[0].t;
       object_dir_transform(kg, sd, &D);
       t = len(D);
+#endif
     }
 
     /* Advance to new scatter location. */