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
This commit is contained in:
@@ -653,6 +653,12 @@ class CyclesLampSettings(bpy.types.PropertyGroup):
|
|||||||
min=1, max=10000,
|
min=1, max=10000,
|
||||||
default=1,
|
default=1,
|
||||||
)
|
)
|
||||||
|
cls.max_bounces = IntProperty(
|
||||||
|
name="Max Bounces",
|
||||||
|
description="Maximum number of bounces the light will contribute to the render",
|
||||||
|
min=0, max=1024,
|
||||||
|
default=1024,
|
||||||
|
)
|
||||||
cls.use_multiple_importance_sampling = BoolProperty(
|
cls.use_multiple_importance_sampling = BoolProperty(
|
||||||
name="Multiple Importance Sample",
|
name="Multiple Importance Sample",
|
||||||
description="Use multiple importance sampling for the lamp, "
|
description="Use multiple importance sampling for the lamp, "
|
||||||
|
@@ -729,11 +729,11 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
|
|||||||
|
|
||||||
if cscene.progressive == 'BRANCHED_PATH':
|
if cscene.progressive == 'BRANCHED_PATH':
|
||||||
col.prop(clamp, "samples")
|
col.prop(clamp, "samples")
|
||||||
|
col.prop(clamp, "max_bounces")
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(clamp, "cast_shadow")
|
col.prop(clamp, "cast_shadow")
|
||||||
|
col.prop(clamp, "use_multiple_importance_sampling")
|
||||||
layout.prop(clamp, "use_multiple_importance_sampling")
|
|
||||||
|
|
||||||
if lamp.type == 'HEMI':
|
if lamp.type == 'HEMI':
|
||||||
layout.label(text="Not supported, interpreted as sun lamp")
|
layout.label(text="Not supported, interpreted as sun lamp")
|
||||||
|
@@ -168,6 +168,8 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
|
|||||||
else
|
else
|
||||||
light->samples = samples;
|
light->samples = samples;
|
||||||
|
|
||||||
|
light->max_bounces = get_int(clamp, "max_bounces");
|
||||||
|
|
||||||
/* visibility */
|
/* visibility */
|
||||||
uint visibility = object_ray_visibility(b_ob);
|
uint visibility = object_ray_visibility(b_ob);
|
||||||
light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
|
light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
|
||||||
|
@@ -648,7 +648,13 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
|
|||||||
|
|
||||||
/* Generic Light */
|
/* 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 */
|
/* sample index */
|
||||||
int index = light_distribution_sample(kg, randt);
|
int index = light_distribution_sample(kg, randt);
|
||||||
@@ -670,6 +676,12 @@ ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int lamp = -prim-1;
|
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);
|
lamp_light_sample(kg, lamp, randu, randv, P, ls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,9 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN
|
|||||||
if(sample_all_lights) {
|
if(sample_all_lights) {
|
||||||
/* lamp sampling */
|
/* lamp sampling */
|
||||||
for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
|
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));
|
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);
|
float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
|
||||||
RNG lamp_rng = cmj_hash(*rng, i);
|
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;
|
light_t = 0.5f*light_t;
|
||||||
|
|
||||||
LightSample ls;
|
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)) {
|
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
|
||||||
/* trace shadow ray */
|
/* 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);
|
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
|
||||||
|
|
||||||
LightSample ls;
|
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 */
|
/* sample random light */
|
||||||
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
|
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
|
#endif
|
||||||
|
|
||||||
LightSample ls;
|
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)) {
|
if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) {
|
||||||
/* trace shadow ray */
|
/* trace shadow ray */
|
||||||
|
@@ -40,7 +40,7 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
|
|||||||
light_ray.time = sd->time;
|
light_ray.time = sd->time;
|
||||||
#endif
|
#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)
|
if(ls.pdf == 0.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -124,6 +124,9 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
|
|||||||
if(sample_all_lights) {
|
if(sample_all_lights) {
|
||||||
/* lamp sampling */
|
/* lamp sampling */
|
||||||
for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
|
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));
|
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);
|
float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
|
||||||
RNG lamp_rng = cmj_hash(*rng, i);
|
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;
|
light_t = 0.5f*light_t;
|
||||||
|
|
||||||
LightSample ls;
|
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;
|
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);
|
kernel_assert(result == VOLUME_PATH_SCATTERED);
|
||||||
|
|
||||||
/* todo: split up light_sample so we don't have to call it again with new position */
|
/* 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)
|
if(ls.pdf == 0.0f)
|
||||||
continue;
|
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);
|
path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
|
||||||
|
|
||||||
LightSample ls;
|
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;
|
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);
|
kernel_assert(result == VOLUME_PATH_SCATTERED);
|
||||||
|
|
||||||
/* todo: split up light_sample so we don't have to call it again with new position */
|
/* 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)
|
if(ls.pdf == 0.0f)
|
||||||
return;
|
return;
|
||||||
|
@@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN
|
|||||||
/* constants */
|
/* constants */
|
||||||
#define OBJECT_SIZE 11
|
#define OBJECT_SIZE 11
|
||||||
#define OBJECT_VECTOR_SIZE 6
|
#define OBJECT_VECTOR_SIZE 6
|
||||||
#define LIGHT_SIZE 4
|
#define LIGHT_SIZE 5
|
||||||
#define FILTER_TABLE_SIZE 256
|
#define FILTER_TABLE_SIZE 256
|
||||||
#define RAMP_TABLE_SIZE 256
|
#define RAMP_TABLE_SIZE 256
|
||||||
#define PARTICLE_SIZE 5
|
#define PARTICLE_SIZE 5
|
||||||
|
@@ -125,6 +125,7 @@ Light::Light()
|
|||||||
|
|
||||||
shader = 0;
|
shader = 0;
|
||||||
samples = 1;
|
samples = 1;
|
||||||
|
max_bounces = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Light::tag_update(Scene *scene)
|
void Light::tag_update(Scene *scene)
|
||||||
@@ -489,6 +490,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
float3 co = light->co;
|
float3 co = light->co;
|
||||||
int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
|
int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
|
||||||
float samples = __int_as_float(light->samples);
|
float samples = __int_as_float(light->samples);
|
||||||
|
float max_bounces = __int_as_float(light->max_bounces);
|
||||||
|
|
||||||
if(!light->cast_shadow)
|
if(!light->cast_shadow)
|
||||||
shader_id &= ~SHADER_CAST_SHADOW;
|
shader_id &= ~SHADER_CAST_SHADOW;
|
||||||
@@ -523,6 +525,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
|
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
|
||||||
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||||
|
light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if(light->type == LIGHT_DISTANT) {
|
else if(light->type == LIGHT_DISTANT) {
|
||||||
shader_id &= ~SHADER_AREA_LIGHT;
|
shader_id &= ~SHADER_AREA_LIGHT;
|
||||||
@@ -544,6 +547,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
|
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
|
||||||
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||||
|
light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if(light->type == LIGHT_BACKGROUND) {
|
else if(light->type == LIGHT_BACKGROUND) {
|
||||||
uint visibility = scene->background->visibility;
|
uint visibility = scene->background->visibility;
|
||||||
@@ -572,6 +576,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
|
||||||
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||||
|
light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if(light->type == LIGHT_AREA) {
|
else if(light->type == LIGHT_AREA) {
|
||||||
float3 axisu = light->axisu*(light->sizeu*light->size);
|
float3 axisu = light->axisu*(light->sizeu*light->size);
|
||||||
@@ -590,6 +595,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
|
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
|
||||||
light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
|
light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
|
||||||
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
|
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
|
||||||
|
light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
else if(light->type == LIGHT_SPOT) {
|
else if(light->type == LIGHT_SPOT) {
|
||||||
shader_id &= ~SHADER_AREA_LIGHT;
|
shader_id &= ~SHADER_AREA_LIGHT;
|
||||||
@@ -610,6 +616,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
|||||||
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
|
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
|
||||||
light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
|
light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
|
||||||
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
|
||||||
|
light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -58,6 +58,7 @@ public:
|
|||||||
|
|
||||||
int shader;
|
int shader;
|
||||||
int samples;
|
int samples;
|
||||||
|
int max_bounces;
|
||||||
|
|
||||||
void tag_update(Scene *scene);
|
void tag_update(Scene *scene);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user