diff options
author | Christophe Hery <chery> | 2022-04-28 18:52:32 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-04-28 19:00:11 +0300 |
commit | 110eb2300526519681b44e154473b5fd087d191e (patch) | |
tree | 8622eec61d72c610cf2bbb9f180c5550fa9cd9b6 /intern/cycles | |
parent | 4296c1fe255f01b75e375a1b59789e4f31d89355 (diff) |
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
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/kernel/integrator/mnee.h | 49 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/shade_surface.h | 40 |
2 files changed, 53 insertions, 36 deletions
diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index c523da8d3be..455d15b28c2 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -948,13 +948,13 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, } /* Manifold next event estimation path sampling. */ -ccl_device_forceinline bool kernel_path_mnee_sample(KernelGlobals kg, - IntegratorState state, - ccl_private ShaderData *sd, - ccl_private ShaderData *sd_mnee, - ccl_private const RNGState *rng_state, - ccl_private LightSample *ls, - ccl_private BsdfEval *throughput) +ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg, + IntegratorState state, + ccl_private ShaderData *sd, + ccl_private ShaderData *sd_mnee, + ccl_private const RNGState *rng_state, + ccl_private LightSample *ls, + ccl_private BsdfEval *throughput) { /* * 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. */ if (vertex_count >= MNEE_MAX_CAUSTIC_CASTERS) - return false; + return 0; /* Reject caster if it is not a triangles mesh. */ if (!(probe_isect.type & PRIMITIVE_TRIANGLE)) - return false; + return 0; 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 * normals are not smooth. */ 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). */ 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) - return false; + return 0; } 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; if (vertex_count == 0) - return false; + return 0; /* Check whether the transmission depth limit is reached before continuing. */ - const int transmission_bounce = INTEGRATOR_STATE(state, path, transmission_bounce) + - vertex_count; - if (transmission_bounce >= kernel_data.integrator.max_transmission_bounce) - return false; + if (INTEGRATOR_STATE(state, path, transmission_bounce) + vertex_count >= + kernel_data.integrator.max_transmission_bounce) + return 0; /* Check whether the diffuse depth limit is reached before continuing. */ - const int diffuse_bounce = INTEGRATOR_STATE(state, path, diffuse_bounce) + 1; - if (diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) - return false; + if (INTEGRATOR_STATE(state, path, diffuse_bounce) + 1 >= + kernel_data.integrator.max_diffuse_bounce) + return 0; /* Check whether the overall depth limit is reached before continuing. */ - const int bounce = INTEGRATOR_STATE(state, path, bounce) + diffuse_bounce + transmission_bounce; - if (bounce >= kernel_data.integrator.max_bounce) - return false; + if (INTEGRATOR_STATE(state, path, bounce) + 1 + vertex_count >= + kernel_data.integrator.max_bounce) + return 0; /* 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 @@ -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)) { /* 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)) - return false; + return 0; - return true; + return vertex_count; } - return false; + return 0; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 55bb08044ae..1df84ba765e 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -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); # ifdef __MNEE__ - bool skip_nee = false; + int mnee_vertex_count = 0; IF_KERNEL_NODES_FEATURE(RAYTRACE) { 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? */ 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); } } } - if (skip_nee) { + if (mnee_vertex_count > 0) { /* Create shadow ray after successful manifold walk: * emission_sd contains the last interface intersection and * 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; /* 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); shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0; 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( state, path, sample); 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, diffuse_bounce) = INTEGRATOR_STATE( - state, path, diffuse_bounce); + + INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transparent_bounce) = INTEGRATOR_STATE( + state, path, transparent_bounce); INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, glossy_bounce) = INTEGRATOR_STATE( 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; if (kernel_data.kernel_features & KERNEL_FEATURE_SHADOW_PASS) { |