From fb820c063831a36b9780a8948219e0eb9ff27da2 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 5 Nov 2014 22:48:45 +0100 Subject: Cycles: Add "Max Bounce" control for lamps With this setting, we can limit the influence of a lamp to a certain amount of bounces. 0 = Only direct light contribution 1 = 1 light bounce ... Differential revision: https://developer.blender.org/D860 You can find an example render in the release logs: http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.73/Cycles --- intern/cycles/kernel/kernel_light.h | 14 +++++++++++++- intern/cycles/kernel/kernel_path_surface.h | 9 ++++++--- intern/cycles/kernel/kernel_path_volume.h | 13 ++++++++----- intern/cycles/kernel/kernel_types.h | 2 +- 4 files changed, 28 insertions(+), 10 deletions(-) (limited to 'intern/cycles/kernel') diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 659c4a113ca..f9ac86e49d6 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -648,7 +648,13 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt) /* Generic Light */ -ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls) +ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce) +{ + float4 data4 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 4); + return (bounce > __float_as_int(data4.x)); +} + +ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, int bounce, LightSample *ls) { /* sample index */ int index = light_distribution_sample(kg, randt); @@ -670,6 +676,12 @@ ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float } else { int lamp = -prim-1; + + if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) { + ls->pdf = 0.0f; + return; + } + lamp_light_sample(kg, lamp, randu, randv, P, ls); } } diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 9553c2da0df..e5ba1f41c47 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -38,6 +38,9 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN if(sample_all_lights) { /* lamp sampling */ for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { + if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) + continue; + int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i)); float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); @@ -82,7 +85,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN light_t = 0.5f*light_t; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ @@ -103,7 +106,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); /* sample random light */ if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { @@ -200,7 +203,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG #endif LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index d8143832294..11d3d94657b 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -40,7 +40,7 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng, light_ray.time = sd->time; #endif - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) return; @@ -124,6 +124,9 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG if(sample_all_lights) { /* lamp sampling */ for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { + if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) + continue; + int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i)); float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); @@ -188,7 +191,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG light_t = 0.5f*light_t; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -203,7 +206,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG kernel_assert(result == VOLUME_PATH_SCATTERED); /* todo: split up light_sample so we don't have to call it again with new position */ - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) continue; @@ -227,7 +230,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -242,7 +245,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG kernel_assert(result == VOLUME_PATH_SCATTERED); /* todo: split up light_sample so we don't have to call it again with new position */ - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) return; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index cfac8d1e905..a7d269a3e54 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN /* constants */ #define OBJECT_SIZE 11 #define OBJECT_VECTOR_SIZE 6 -#define LIGHT_SIZE 4 +#define LIGHT_SIZE 5 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 #define PARTICLE_SIZE 5 -- cgit v1.2.3