diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-03-05 16:55:30 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-03-05 16:55:30 +0300 |
commit | 9489205c5c0b9b432d02be4a3d0d15fc62ee6cb9 (patch) | |
tree | 3888e597a1eb7c96bd375fd45741621fb2c805a9 /intern/cycles | |
parent | eb16b04b9dac7703042048f676b832894784244e (diff) |
Fix T43865: Cycles: Watertight rendering produces artifacts on a huge plane
The issue was caused by numerical instability whrn having ray origin close to a huge
triangle, which could have aused bad ray distance check.
Watertight Woop intersection isn't really addressing such cases, it's dealing with
small triangles far away from the ray origin instead, so it's a bit tricky yo make
it working reliably.
While we're quite close to the release it's safer to do check in Pleaucker coordinates
if ray close to a huge triangle. Likely this additional check combined with some other
tweaks to the code doesn't cause measurable slowdown in the scenes tested here.
After the release we can play a bit more with this code in order to make it more
stable without Pleucker fallback.
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/kernel/geom/geom_triangle_intersect.h | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index 6defa80fd01..06917dc16d8 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -153,14 +153,16 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, /* 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; + const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz; - if ((xor_signmast(T, sign_mask) < 0.0f) || - (xor_signmast(T, sign_mask) > isect->t * xor_signmast(det, sign_mask))) - { + /* 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) { return false; } @@ -172,12 +174,37 @@ 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 * inv_det; + isect->t = t; return true; } return false; |