diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index b35bdf8f511..8950b4f83c4 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -528,7 +528,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): ob = context.object - return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'} # todo: 'LAMP' + return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'} def draw(self, context): layout = self.layout diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 5dbb46bda2e..75f0c48a8a2 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -159,6 +159,12 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling"); light->samples = get_int(clamp, "samples"); + /* visibility */ + uint visibility = object_ray_visibility(b_ob); + light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; + light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0; + light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0; + /* tag */ light->tag_update(scene); } diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 557990d7220..e6307f23b32 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -232,12 +232,9 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu L->direct_transmission += throughput*bsdf_eval->transmission*shadow; if(is_lamp) { - float3 sum = throughput*(bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission); - L->shadow.x += shadow.x*shadow_fac; L->shadow.y += shadow.y*shadow_fac; L->shadow.z += shadow.z*shadow_fac; - L->shadow.w += average(sum); } } else { diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 74f768c899c..869c8539809 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -102,8 +102,6 @@ __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int li if(is_zero(light_eval)) return false; - /* todo: use visibility flag to skip lights */ - /* evaluate BSDF at shading point */ float bsdf_pdf; @@ -117,6 +115,18 @@ __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int li bsdf_eval_mul(eval, light_eval/ls.pdf); +#ifdef __PASSES__ + /* use visibility flag to skip lights */ + if(ls.shader & SHADER_EXCLUDE_ANY) { + if(ls.shader & SHADER_EXCLUDE_DIFFUSE) + eval->diffuse = make_float3(0.0f, 0.0f, 0.0f); + if(ls.shader & SHADER_EXCLUDE_GLOSSY) + eval->glossy = make_float3(0.0f, 0.0f, 0.0f); + if(ls.shader & SHADER_EXCLUDE_TRANSMIT) + eval->transmission = make_float3(0.0f, 0.0f, 0.0f); + } +#endif + if(bsdf_eval_is_zero(eval)) return false; @@ -185,7 +195,19 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p if(!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls)) return false; - + +#ifdef __PASSES__ + /* use visibility flag to skip lights */ + if(ls.shader & SHADER_EXCLUDE_ANY) { + if((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (path_flag & PATH_RAY_DIFFUSE)) + return false; + if((ls.shader & SHADER_EXCLUDE_GLOSSY) && (path_flag & PATH_RAY_GLOSSY)) + return false; + if((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) + return false; + } +#endif + /* todo: missing texture coordinates */ float u = 0.0f; float v = 0.0f; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 9f198c6c595..4983122fb34 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -558,11 +558,11 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra if(prim >= 0) { int object = __float_as_int(l.w); #ifdef __HAIR__ - int segment = __float_as_int(l.z); + int segment = __float_as_int(l.z) & SHADER_MASK; #endif #ifdef __HAIR__ - if (segment != (int)~0) + if (segment != SHADER_MASK) curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls); else #endif @@ -571,6 +571,7 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra /* compute incoming direction, distance and pdf */ ls->D = normalize_len(ls->P - P, &ls->t); ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t); + ls->shader |= __float_as_int(l.z) & (~SHADER_MASK); } else { int lamp = -prim-1; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index abdb609b55f..11cdad6bb44 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -326,8 +326,12 @@ typedef enum ShaderFlag { SHADER_CAST_SHADOW = (1 << 30), SHADER_AREA_LIGHT = (1 << 29), SHADER_USE_MIS = (1 << 28), + SHADER_EXCLUDE_DIFFUSE = (1 << 27), + SHADER_EXCLUDE_GLOSSY = (1 << 26), + SHADER_EXCLUDE_TRANSMIT = (1 << 25), + SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT), - SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS) + SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY) } ShaderFlag; /* Light Type */ diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 1fe30376adc..43aef755ba3 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -259,6 +259,8 @@ Film::Film() mist_depth = 100.0f; mist_falloff = 1.0f; + use_light_visibility = false; + need_update = true; } @@ -279,7 +281,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) kfilm->exposure = exposure; kfilm->pass_flag = 0; kfilm->pass_stride = 0; - kfilm->use_light_pass = 0; + kfilm->use_light_pass = use_light_visibility; foreach(Pass& pass, passes) { kfilm->pass_flag |= pass.type; diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 1df0e95a48a..0147306c1e3 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -61,6 +61,8 @@ public: float mist_depth; float mist_falloff; + bool use_light_visibility; + bool need_update; Film(); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 1d2acf79b6c..71e1f57eb36 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -18,6 +18,7 @@ #include "device.h" #include "integrator.h" +#include "film.h" #include "light.h" #include "mesh.h" #include "object.h" @@ -116,6 +117,9 @@ Light::Light() cast_shadow = true; use_mis = false; + use_diffuse = true; + use_glossy = true; + use_transmission = true; shader = 0; samples = 1; @@ -221,17 +225,31 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen bool transform_applied = mesh->transform_applied; Transform tfm = object->tfm; int object_id = j; + int shader_id = SHADER_MASK; if(transform_applied) object_id = ~object_id; + if(!(object->visibility & PATH_RAY_DIFFUSE)) { + shader_id |= SHADER_EXCLUDE_DIFFUSE; + scene->film->use_light_visibility = true; + } + if(!(object->visibility & PATH_RAY_GLOSSY)) { + shader_id |= SHADER_EXCLUDE_GLOSSY; + scene->film->use_light_visibility = true; + } + if(!(object->visibility & PATH_RAY_TRANSMIT)) { + shader_id |= SHADER_EXCLUDE_TRANSMIT; + scene->film->use_light_visibility = true; + } + for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; if(shader->sample_as_light && shader->has_surface_emission) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->tri_offset); - distribution[offset].z = __int_as_float(~0); + distribution[offset].z = __int_as_float(shader_id); distribution[offset].w = __int_as_float(object_id); offset++; @@ -250,7 +268,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } } - /*sample as light disabled for strands*/ + /* sample as light disabled for strands */ #if 0 size_t i = 0; @@ -262,7 +280,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen for(int j = 0; j < curve.num_segments(); j++) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code - distribution[offset].z = __int_as_float(j); + distribution[offset].z = __int_as_float(j) & SHADER_MASK; distribution[offset].w = __int_as_float(object_id); offset++; @@ -493,6 +511,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce } } } + scene->film->use_light_visibility = false; for(size_t i = 0; i < scene->lights.size(); i++) { Light *light = scene->lights[i]; @@ -504,6 +523,19 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(!light->cast_shadow) shader_id &= ~SHADER_CAST_SHADOW; + if(!light->use_diffuse) { + shader_id |= SHADER_EXCLUDE_DIFFUSE; + scene->film->use_light_visibility = true; + } + if(!light->use_glossy) { + shader_id |= SHADER_EXCLUDE_GLOSSY; + scene->film->use_light_visibility = true; + } + if(!light->use_transmission) { + shader_id |= SHADER_EXCLUDE_TRANSMIT; + scene->film->use_light_visibility = true; + } + if(light->type == LIGHT_POINT) { shader_id &= ~SHADER_AREA_LIGHT; diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index acd1692a41f..0e833fdea1d 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -53,6 +53,9 @@ public: bool cast_shadow; bool use_mis; + bool use_diffuse; + bool use_glossy; + bool use_transmission; int shader; int samples;