diff options
Diffstat (limited to 'intern/cycles/kernel/integrator/shade_surface.h')
-rw-r--r-- | intern/cycles/kernel/integrator/shade_surface.h | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index df9af6ca107..c5dd9fe27f4 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -6,6 +6,8 @@ #include "kernel/film/accumulate.h" #include "kernel/film/passes.h" +#include "kernel/integrator/mnee.h" + #include "kernel/integrator/path_state.h" #include "kernel/integrator/shader_eval.h" #include "kernel/integrator/subsurface.h" @@ -92,6 +94,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, #ifdef __EMISSION__ /* Path tracing: sample point on light and evaluate light shader, then * queue shadow ray to be traced. */ +template<uint node_feature_mask> ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *sd, @@ -124,34 +127,65 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, * integrate_surface_bounce, evaluate the BSDF, and only then evaluate * the light shader. This could also move to its own kernel, for * non-constant light sources. */ - ShaderDataTinyStorage emission_sd_storage; + ShaderDataCausticsStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); - if (is_zero(light_eval)) { - return; - } - - /* Evaluate BSDF. */ - const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D); + Ray ray ccl_optional_struct_init; BsdfEval bsdf_eval ccl_optional_struct_init; - const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader); - bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf); + const bool is_transmission = shader_bsdf_is_transmission(sd, ls.D); - if (ls.shader & SHADER_USE_MIS) { - const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf); - bsdf_eval_mul(&bsdf_eval, mis_weight); +# ifdef __MNEE__ + bool skip_nee = false; + IF_KERNEL_NODES_FEATURE(RAYTRACE) + { + if (ls.lamp != LAMP_NONE) { + /* Is this a caustic light? */ + const bool use_caustics = kernel_tex_fetch(__lights, ls.lamp).use_caustics; + if (use_caustics) { + /* Are we on a caustic caster? */ + if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) + return; + + /* Are we on a caustic receiver? */ + if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) + skip_nee = kernel_path_mnee_sample( + kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval); + } + } + } + if (skip_nee) { + /* Create shadow ray after successful manifold walk: + * emission_sd contains the last interface intersection and + * the light sample ls has been updated */ + light_sample_to_surface_shadow_ray(kg, emission_sd, &ls, &ray); } + else +# endif /* __MNEE__ */ + { + const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); + if (is_zero(light_eval)) { + return; + } - /* Path termination. */ - const float terminate = path_state_rng_light_termination(kg, rng_state); - if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) { - return; + /* Evaluate BSDF. */ + const float bsdf_pdf = shader_bsdf_eval(kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader); + bsdf_eval_mul3(&bsdf_eval, light_eval / ls.pdf); + + if (ls.shader & SHADER_USE_MIS) { + const float mis_weight = light_sample_mis_weight_nee(kg, ls.pdf, bsdf_pdf); + bsdf_eval_mul(&bsdf_eval, mis_weight); + } + + /* Path termination. */ + const float terminate = path_state_rng_light_termination(kg, rng_state); + if (light_sample_terminate(kg, &ls, &bsdf_eval, terminate)) { + return; + } + + /* Create shadow ray. */ + light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray); } - /* Create shadow ray. */ - Ray ray ccl_optional_struct_init; - light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray); const bool is_light = light_sample_is_light(&ls); /* Branch off shadow kernel. */ @@ -501,7 +535,7 @@ ccl_device bool integrate_surface(KernelGlobals kg, /* Direct light. */ PROFILING_EVENT(PROFILING_SHADE_SURFACE_DIRECT_LIGHT); - integrate_surface_direct_light(kg, state, &sd, &rng_state); + integrate_surface_direct_light<node_feature_mask>(kg, state, &sd, &rng_state); #if defined(__AO__) /* Ambient occlusion pass. */ |