Fix T97056: Cycles MNEE caustics treated as direct instead of indirect light
This fixes wrong render passs and bounce limits. Differential Revision: https://developer.blender.org/D14737
This commit is contained in:

committed by
Brecht Van Lommel

parent
4296c1fe25
commit
110eb23005
@@ -948,13 +948,13 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Manifold next event estimation path sampling. */
|
/* Manifold next event estimation path sampling. */
|
||||||
ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg,
|
||||||
IntegratorState state,
|
IntegratorState state,
|
||||||
ccl_private ShaderData *sd,
|
ccl_private ShaderData *sd,
|
||||||
ccl_private ShaderData *sd_mnee,
|
ccl_private ShaderData *sd_mnee,
|
||||||
ccl_private const RNGState *rng_state,
|
ccl_private const RNGState *rng_state,
|
||||||
ccl_private LightSample *ls,
|
ccl_private LightSample *ls,
|
||||||
ccl_private BsdfEval *throughput)
|
ccl_private BsdfEval *throughput)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* 1. send seed ray from shading point to light sample position (or along sampled light
|
* 1. send seed ray from shading point to light sample position (or along sampled light
|
||||||
@@ -998,11 +998,11 @@ ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
|||||||
|
|
||||||
/* Do we have enough slots. */
|
/* Do we have enough slots. */
|
||||||
if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS)
|
if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS)
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
/* Reject caster if it is not a triangles mesh. */
|
/* Reject caster if it is not a triangles mesh. */
|
||||||
if (!(probe_isect.type & PRIMITIVE_TRIANGLE))
|
if (!(probe_isect.type & PRIMITIVE_TRIANGLE))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
ccl_private ManifoldVertex &mv = vertices[vertex_count++];
|
ccl_private ManifoldVertex &mv = vertices[vertex_count++];
|
||||||
|
|
||||||
@@ -1013,7 +1013,7 @@ ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
|||||||
* differential geometry can be created at any point on the surface which is not possible if
|
* differential geometry can be created at any point on the surface which is not possible if
|
||||||
* normals are not smooth. */
|
* normals are not smooth. */
|
||||||
if (!(sd_mnee->shader & SHADER_SMOOTH_NORMAL))
|
if (!(sd_mnee->shader & SHADER_SMOOTH_NORMAL))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
/* Last bool argument is the MNEE flag (for TINY_MAX_CLOSURE cap in kernel_shader.h). */
|
/* Last bool argument is the MNEE flag (for TINY_MAX_CLOSURE cap in kernel_shader.h). */
|
||||||
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
|
shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW>(
|
||||||
@@ -1051,7 +1051,7 @@ ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found_transimissive_microfacet_bsdf)
|
if (!found_transimissive_microfacet_bsdf)
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
probe_ray.self.object = probe_isect.object;
|
probe_ray.self.object = probe_isect.object;
|
||||||
@@ -1065,23 +1065,22 @@ ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
|||||||
INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_VALID;
|
INTEGRATOR_STATE_WRITE(state, path, mnee) &= ~PATH_MNEE_VALID;
|
||||||
|
|
||||||
if (vertex_count == 0)
|
if (vertex_count == 0)
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
/* Check whether the transmission depth limit is reached before continuing. */
|
/* Check whether the transmission depth limit is reached before continuing. */
|
||||||
const int transmission_bounce = INTEGRATOR_STATE(state, path, transmission_bounce) +
|
if (INTEGRATOR_STATE(state, path, transmission_bounce) + vertex_count >=
|
||||||
vertex_count;
|
kernel_data.integrator.max_transmission_bounce)
|
||||||
if (transmission_bounce >= kernel_data.integrator.max_transmission_bounce)
|
return 0;
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Check whether the diffuse depth limit is reached before continuing. */
|
/* Check whether the diffuse depth limit is reached before continuing. */
|
||||||
const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce) + 1;
|
if (INTEGRATOR_STATE(state, path, diffuse_bounce) + 1 >=
|
||||||
if (diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce)
|
kernel_data.integrator.max_diffuse_bounce)
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
/* Check whether the overall depth limit is reached before continuing. */
|
/* Check whether the overall depth limit is reached before continuing. */
|
||||||
const int bounce = INTEGRATOR_STATE(state, path, bounce) + diffuse_bounce + transmission_bounce;
|
if (INTEGRATOR_STATE(state, path, bounce) + 1 + vertex_count >=
|
||||||
if (bounce >= kernel_data.integrator.max_bounce)
|
kernel_data.integrator.max_bounce)
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
/* Mark the manifold walk valid to turn off mollification regardless of how successful the walk
|
/* Mark the manifold walk valid to turn off mollification regardless of how successful the walk
|
||||||
* is: this is noticeable when another mnee is performed deeper in the path, for an internally
|
* is: this is noticeable when another mnee is performed deeper in the path, for an internally
|
||||||
@@ -1095,12 +1094,12 @@ ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg,
|
|||||||
if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
|
if (mnee_newton_solver(kg, sd, sd_mnee, ls, vertex_count, vertices)) {
|
||||||
/* 3. If a solution exists, calculate contribution of the corresponding path */
|
/* 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, vertex_count, vertices, throughput))
|
||||||
return false;
|
return 0;
|
||||||
|
|
||||||
return true;
|
return vertex_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -136,7 +136,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||||||
const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D);
|
const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D);
|
||||||
|
|
||||||
# ifdef __MNEE__
|
# ifdef __MNEE__
|
||||||
bool skip_nee = false;
|
int mnee_vertex_count = 0;
|
||||||
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
IF_KERNEL_NODES_FEATURE(RAYTRACE)
|
||||||
{
|
{
|
||||||
if (ls.lamp != LAMP_NONE) {
|
if (ls.lamp != LAMP_NONE) {
|
||||||
@@ -149,12 +149,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||||||
|
|
||||||
/* Are we on a caustic receiver? */
|
/* Are we on a caustic receiver? */
|
||||||
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER))
|
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER))
|
||||||
skip_nee = kernel_path_mnee_sample(
|
mnee_vertex_count = kernel_path_mnee_sample(
|
||||||
kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
|
kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (skip_nee) {
|
if (mnee_vertex_count > 0) {
|
||||||
/* Create shadow ray after successful manifold walk:
|
/* Create shadow ray after successful manifold walk:
|
||||||
* emission_sd contains the last interface intersection and
|
* emission_sd contains the last interface intersection and
|
||||||
* the light sample ls has been updated */
|
* the light sample ls has been updated */
|
||||||
@@ -211,8 +211,6 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||||||
INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, prim) = ray.self.light_prim;
|
INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, prim) = ray.self.light_prim;
|
||||||
|
|
||||||
/* Copy state from main path to shadow path. */
|
/* Copy state from main path to shadow path. */
|
||||||
const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce);
|
|
||||||
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
|
|
||||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
|
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
|
||||||
@@ -246,14 +244,34 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, sample) = INTEGRATOR_STATE(
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, sample) = INTEGRATOR_STATE(
|
||||||
state, path, sample);
|
state, path, sample);
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, flag) = shadow_flag;
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, flag) = shadow_flag;
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, bounce) = bounce;
|
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transparent_bounce) = transparent_bounce;
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transparent_bounce) = INTEGRATOR_STATE(
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, diffuse_bounce) = INTEGRATOR_STATE(
|
state, path, transparent_bounce);
|
||||||
state, path, diffuse_bounce);
|
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, glossy_bounce) = INTEGRATOR_STATE(
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, glossy_bounce) = INTEGRATOR_STATE(
|
||||||
state, path, glossy_bounce);
|
state, path, glossy_bounce);
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transmission_bounce) = INTEGRATOR_STATE(
|
|
||||||
state, path, transmission_bounce);
|
# ifdef __MNEE__
|
||||||
|
if (mnee_vertex_count > 0) {
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transmission_bounce) =
|
||||||
|
INTEGRATOR_STATE(state, path, transmission_bounce) + mnee_vertex_count;
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state,
|
||||||
|
shadow_path,
|
||||||
|
diffuse_bounce) = INTEGRATOR_STATE(state, path, diffuse_bounce) + 1;
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state,
|
||||||
|
shadow_path,
|
||||||
|
bounce) = INTEGRATOR_STATE(state, path, bounce) + 1 + mnee_vertex_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transmission_bounce) = INTEGRATOR_STATE(
|
||||||
|
state, path, transmission_bounce);
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, diffuse_bounce) = INTEGRATOR_STATE(
|
||||||
|
state, path, diffuse_bounce);
|
||||||
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, bounce) = INTEGRATOR_STATE(
|
||||||
|
state, path, bounce);
|
||||||
|
}
|
||||||
|
|
||||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, throughput) = throughput;
|
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, throughput) = throughput;
|
||||||
|
|
||||||
if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_PASS) {
|
if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_PASS) {
|
||||||
|
Reference in New Issue
Block a user