Fix #107365: keep ls->D
fixed in MNEE for area light with zero spread
This commit is contained in:
parent
ee08b2ddff
commit
1a1f06bd9a
@ -398,6 +398,7 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_private ShaderData *sd_vtx,
|
||||
ccl_private const LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices)
|
||||
{
|
||||
@ -413,7 +414,6 @@ ccl_device_forceinline bool mnee_newton_solver(KernelGlobals kg,
|
||||
projection_ray.time = sd->time;
|
||||
Intersection projection_isect;
|
||||
|
||||
const bool light_fixed_direction = (ls->t == FLT_MAX);
|
||||
const float3 light_sample = light_fixed_direction ? ls->D : ls->P;
|
||||
|
||||
/* We start gently, potentially ramping up to beta = 1, since target configurations
|
||||
@ -639,6 +639,7 @@ ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderCl
|
||||
/* Compute transfer matrix determinant |T1| = |dx1/dxn| (and |dh/dx| in the process) */
|
||||
ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const ShaderData *sd,
|
||||
ccl_private const LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices,
|
||||
ccl_private float *dx1_dxlight,
|
||||
@ -692,7 +693,7 @@ ccl_device_forceinline bool mnee_compute_transfer_matrix(ccl_private const Shade
|
||||
float dxn_dwn;
|
||||
float4 dc_dlight;
|
||||
|
||||
if (ls->t == FLT_MAX) {
|
||||
if (light_fixed_direction) {
|
||||
/* Constant direction toward light sample. */
|
||||
float3 wo = ls->D;
|
||||
|
||||
@ -764,6 +765,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private ShaderData *sd_mnee,
|
||||
ccl_private LightSample *ls,
|
||||
const bool light_fixed_direction,
|
||||
int vertex_count,
|
||||
ccl_private ManifoldVertex *vertices,
|
||||
ccl_private BsdfEval *throughput)
|
||||
@ -807,7 +809,8 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
|
||||
float dh_dx;
|
||||
float dx1_dxlight;
|
||||
if (!mnee_compute_transfer_matrix(sd, ls, vertex_count, vertices, &dx1_dxlight, &dh_dx))
|
||||
if (!mnee_compute_transfer_matrix(
|
||||
sd, ls, light_fixed_direction, vertex_count, vertices, &dx1_dxlight, &dh_dx))
|
||||
return false;
|
||||
|
||||
/* Receiver bsdf eval above already contains |n.wo|. */
|
||||
@ -882,7 +885,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
kg, state, sd_mnee, NULL, PATH_RAY_DIFFUSE, true);
|
||||
|
||||
/* Set light looking dir. */
|
||||
wo = (vi == vertex_count - 1) ? (ls->t == FLT_MAX ? ls->D : ls->P - v.p) :
|
||||
wo = (vi == vertex_count - 1) ? (light_fixed_direction ? ls->D : ls->P - v.p) :
|
||||
vertices[vi + 1].p - v.p;
|
||||
wo = normalize_len(wo, &wo_len);
|
||||
|
||||
@ -1039,12 +1042,22 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
|
||||
* discontinuity is visible between direct and indirect contributions */
|
||||
INTEGRATOR_STATE_WRITE(state, path, mnee) |= PATH_MNEE_VALID;
|
||||
|
||||
/* 2. Walk on the specular manifold to find vertices on the
|
||||
* casters that satisfy snell's law for each interface
|
||||
*/
|
||||
if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
|
||||
/* Distant or environment light. */
|
||||
bool light_fixed_direction = (ls->t == FLT_MAX);
|
||||
if (ls->type == LIGHT_AREA) {
|
||||
const ccl_global KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
|
||||
if (klight->area.tan_half_spread == 0.0f) {
|
||||
/* Area light with zero spread also has fixed direction. */
|
||||
light_fixed_direction = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. Walk on the specular manifold to find vertices on the casters that satisfy snell's law for
|
||||
* each interface. */
|
||||
if (mnee_newton_solver(kg, sd, sd_mnee, ls, light_fixed_direction, vertex_count, vertices)) {
|
||||
/* 3. If a solution exists, calculate contribution of the corresponding path */
|
||||
if (!mnee_path_contribution(kg, state, sd, sd_mnee, ls, vertex_count, vertices, throughput))
|
||||
if (!mnee_path_contribution(
|
||||
kg, state, sd, sd_mnee, ls, light_fixed_direction, vertex_count, vertices, throughput))
|
||||
return 0;
|
||||
|
||||
return vertex_count;
|
||||
|
@ -340,8 +340,14 @@ ccl_device_forceinline void area_light_update_position(const ccl_global KernelLi
|
||||
const float3 P)
|
||||
{
|
||||
const float invarea = fabsf(klight->area.invarea);
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = invarea;
|
||||
if (klight->area.tan_half_spread == 0) {
|
||||
/* Update position on the light to keep the direction fixed. */
|
||||
area_light_sample<false>(klight, 0.0f, 0.0f, P, ls);
|
||||
}
|
||||
else {
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = invarea;
|
||||
}
|
||||
|
||||
if (klight->area.normalize_spread > 0) {
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
Loading…
Reference in New Issue
Block a user