diff options
author | Sebastian Herholz <sherholz> | 2021-11-24 16:04:34 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-12-01 22:20:12 +0300 |
commit | cb334428b012294a4503a34e1e2eca5c84d516bd (patch) | |
tree | cd056cf8ed110943dae4d6b4c5e74fe665761256 /intern/cycles/util | |
parent | 9afd6e7b70d5d236843480c9cad879740b2bfb0a (diff) |
Cycles: fix bugs in point and spot light multiple importance sampling
* Spot lights are now handled as disks aligned with the direction of the
spotlight instead of view aligned disks.
* Point light is now handled separately from the spot light, to fix a case
where multiple lights are intersected in a row. Before the origin of the
ray was the previously intersected light and not the origin of the initial
ray traced from the last surface/volume interaction.
This makes both strategies in multiple importance sampling converge to the same
result. It changes the render results in some scenes, for example the junkshop
scene where there are large point lights overlapping scene geometry and each
other.
Differential Revision: https://developer.blender.org/D13233
Diffstat (limited to 'intern/cycles/util')
-rw-r--r-- | intern/cycles/util/math_intersect.h | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/intern/cycles/util/math_intersect.h b/intern/cycles/util/math_intersect.h index 54ce3ab4b66..0fce9ff24fd 100644 --- a/intern/cycles/util/math_intersect.h +++ b/intern/cycles/util/math_intersect.h @@ -85,6 +85,35 @@ ccl_device bool ray_aligned_disk_intersect(float3 ray_P, return true; } +ccl_device bool ray_disk_intersect(float3 ray_P, + float3 ray_D, + float ray_t, + float3 disk_P, + float3 disk_N, + float disk_radius, + ccl_private float3 *isect_P, + ccl_private float *isect_t) +{ + const float3 vp = ray_P - disk_P; + const float dp = dot(vp, disk_N); + const float cos_angle = dot(disk_N, -ray_D); + if (dp * cos_angle > 0.f) // front of light + { + float t = dp / cos_angle; + if (t < 0.f) { /* Ray points away from the light. */ + return false; + } + float3 P = ray_P + t * ray_D; + float3 T = P - disk_P; + if (dot(T, T) < sqr(disk_radius) /*&& t > 0.f*/ && t <= ray_t) { + *isect_P = ray_P + t * ray_D; + *isect_t = t; + return true; + } + } + return false; +} + ccl_device_forceinline bool ray_triangle_intersect(float3 ray_P, float3 ray_dir, float ray_t, |