diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-03-22 21:27:58 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-04-01 13:31:01 +0300 |
commit | 3f24cfb9582e1c826406301d37808df7ca6aa64c (patch) | |
tree | 23e816d0ebf5b23d4e68a4a5ec3dbcd75a218110 /intern/cycles/kernel/kernel_light.h | |
parent | a4260ac21977acd5b9cd792f2a68c3aa78dd91cd (diff) |
Cycles: light spread importance sampling for rectangular area lights
Compute a subset of the area light that actually affects the shading point
and only samples points within that.
It's not perfect as the real subset is a circle instead of a rectangle, and
the attenuation is not accounted for. However it massively reduces noise for
shading points near the area light anyway.
Ellipse shaped area lights do not have this importance sampling, but do not
have solid angle importance sampling either.
Ref D10594
Diffstat (limited to 'intern/cycles/kernel/kernel_light.h')
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 93b05f0ffce..f288ca3051a 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -119,11 +119,11 @@ ccl_device_inline bool lamp_light_sample( klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]); float3 axisv = make_float3( klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]); - float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); + float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]); float invarea = fabsf(klight->area.invarea); bool is_round = (klight->area.invarea < 0.0f); - if (dot(ls->P - P, D) > 0.0f) { + if (dot(ls->P - P, Ng) > 0.0f) { return false; } @@ -135,15 +135,25 @@ ccl_device_inline bool lamp_light_sample( ls->pdf = invarea; } else { + float3 sample_axisu = axisu; + float3 sample_axisv = axisv; + + if (klight->area.tan_spread > 0.0f) { + if (!light_spread_clamp_area_light( + P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) { + return false; + } + } + inplane = ls->P; - ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true); + ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true); inplane = ls->P - inplane; } ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f; ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f; - ls->Ng = D; + ls->Ng = Ng; ls->D = normalize_len(ls->P - P, &ls->t); ls->eval_fac = 0.25f * invarea; @@ -155,7 +165,7 @@ ccl_device_inline bool lamp_light_sample( } if (is_round) { - ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t); + ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t); } } } @@ -290,7 +300,17 @@ ccl_device bool lamp_light_eval( ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t); } else { - ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false); + float3 sample_axisu = axisu; + float3 sample_axisv = axisv; + + if (klight->area.tan_spread > 0.0f) { + if (!light_spread_clamp_area_light( + P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) { + return false; + } + } + + ls->pdf = rect_light_sample(P, &light_P, sample_axisu, sample_axisv, 0, 0, false); } ls->eval_fac = 0.25f * invarea; |