Cycles: ray visibility options now work for lamps and mesh lights, with and without
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 7 Jun 2013 18:59:23 +0000 (18:59 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 7 Jun 2013 18:59:23 +0000 (18:59 +0000)
multiple importance sampling, so you can disable them for diffuse/glossy/transmission.

The Light Path node here is still weak and does not give this info. To make that
work we'd need to evaluate the shader multiple times which is slow and we can't
detect well enough when it is actually needed.

intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_object.cpp
intern/cycles/kernel/kernel_accumulate.h
intern/cycles/kernel/kernel_emission.h
intern/cycles/kernel/kernel_light.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/film.cpp
intern/cycles/render/film.h
intern/cycles/render/light.cpp
intern/cycles/render/light.h

index b35bdf8f511352b78ff3d27da7089759a20274ee..8950b4f83c41cef3dbe8e923ccf9325d06ad28d4 100644 (file)
@@ -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
index 5dbb46bda2e59f0560166209fd34684acb11cfe2..75f0c48a8a2d6026d05f88fe9f16f9dcd116e1d0 100644 (file)
@@ -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);
 }
index 557990d7220db4a527c71ff4164e10738ffb0a85..e6307f23b32f2e5f0cb828dd921246ba86809f93 100644 (file)
@@ -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 {
index 74f768c899cb90a57c0fbe1b70dd905305a4c219..869c853980908c8baae84c563bfe6e8fc2a4efc6 100644 (file)
@@ -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;
index 9f198c6c595bdfc4dbc3d0e1704023d09cd1f623..4983122fb346b2f2a11dcd5042b6f98be99528c7 100644 (file)
@@ -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;
index abdb609b55fdbb05a5f62f477a67411b3d5345f3..11cdad6bb44d2df0f2abdb825e1ed145db069496 100644 (file)
@@ -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 */
index 1fe30376adcc095f2a384a70f6799dc3d8b759f4..43aef755ba3105af0e510fafbead3d81db02be4c 100644 (file)
@@ -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;
index 1df0e95a48ab7d377d474c6a3582411ce37e9ea3..0147306c1e30e3cc2bec17e7ed2604618433848a 100644 (file)
@@ -61,6 +61,8 @@ public:
        float mist_depth;
        float mist_falloff;
 
+       bool use_light_visibility;
+
        bool need_update;
 
        Film();
index 1d2acf79b6c9447492c1fb1a76cb7fed133c955e..71e1f57eb3679f2b8e19d69894318e5ddb10bce1 100644 (file)
@@ -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;
 
index acd1692a41feb704a20ea33696f7343026cf9c11..0e833fdea1d39ca7265e83701a0bf19f6e9ff09a 100644 (file)
@@ -53,6 +53,9 @@ public:
 
        bool cast_shadow;
        bool use_mis;
+       bool use_diffuse;
+       bool use_glossy;
+       bool use_transmission;
 
        int shader;
        int samples;