Cycles: Make per-object random value output also work for Lamps
authorLukas Stockner <lukas.stockner@freenet.de>
Sun, 5 Nov 2017 20:59:17 +0000 (21:59 +0100)
committerLukas Stockner <lukas.stockner@freenet.de>
Tue, 14 Nov 2017 03:17:54 +0000 (04:17 +0100)
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/kernel/geom/geom_object.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm_geometry.h
intern/cycles/render/light.cpp
intern/cycles/render/light.h

index eb573b75e9ef1b81a8c3d4aba98daa8ef06a28f2..f02d54961126babded56f933ccbb038896e0952c 100644 (file)
@@ -112,6 +112,7 @@ static uint object_ray_visibility(BL::Object& b_ob)
 void BlenderSync::sync_light(BL::Object& b_parent,
                              int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
                              BL::Object& b_ob,
+                             BL::DupliObject& b_dupli_ob,
                              Transform& tfm,
                              bool *use_portal)
 {
@@ -193,6 +194,13 @@ void BlenderSync::sync_light(BL::Object& b_parent,
 
        light->max_bounces = get_int(clamp, "max_bounces");
 
+       if(b_dupli_ob) {
+               light->random_id = b_dupli_ob.random_id();
+       }
+       else {
+               light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0);
+       }
+
        if(light->type == LIGHT_AREA)
                light->is_portal = get_boolean(clamp, "is_portal");
        else
@@ -271,7 +279,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
        if(object_is_light(b_ob)) {
                /* don't use lamps for excluded layers used as mask layer */
                if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer)))
-                       sync_light(b_parent, persistent_id, b_ob, tfm, use_portal);
+                       sync_light(b_parent, persistent_id, b_ob, b_dupli_ob, tfm, use_portal);
 
                return NULL;
        }
index 11e279b81c488d9dbe17fe10170b00ff60c9301c..e7b71ae9310ec9f93dd122c3ea3d6b6fd0029f5b 100644 (file)
@@ -131,6 +131,7 @@ private:
        void sync_light(BL::Object& b_parent,
                        int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
                        BL::Object& b_ob,
+                       BL::DupliObject& b_dupli_ob,
                        Transform& tfm,
                        bool *use_portal);
        void sync_background_light(bool use_portal);
index 1ffc143be34dfba186c4b1283c3d5d63535fd0ca..a276096a7459b446f7589b4e88170247a9bfc830 100644 (file)
@@ -244,6 +244,17 @@ ccl_device_inline float object_pass_id(KernelGlobals *kg, int object)
        return f.y;
 }
 
+/* Per lamp random number for shader variation */
+
+ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp)
+{
+       if(lamp == LAMP_NONE)
+               return 0.0f;
+
+       float4 f = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 4);
+       return f.y;
+}
+
 /* Per object random number for shader variation */
 
 ccl_device_inline float object_random_number(KernelGlobals *kg, int object)
index 239c6b12bdfcfb909550954769f912b8d45522b4..26d3fcf15b23eb786142ebb7f9aa9a32eb29d08d 100644 (file)
@@ -57,6 +57,7 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
 #ifdef __INSTANCING__
        sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
 #endif
+       sd->lamp = LAMP_NONE;
 
        sd->type = isect->type;
        sd->flag = 0;
@@ -265,6 +266,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
 #ifdef __INSTANCING__
        sd->object = object;
 #endif
+       sd->lamp = LAMP_NONE;
        /* currently no access to bvh prim index for strand sd->prim*/
        sd->prim = prim;
 #ifdef __UV__
@@ -286,6 +288,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
        else if(lamp != LAMP_NONE) {
                sd->ob_tfm  = lamp_fetch_transform(kg, lamp, false);
                sd->ob_itfm = lamp_fetch_transform(kg, lamp, true);
+               sd->lamp = lamp;
 #endif
        }
 
@@ -391,6 +394,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
 #ifdef __INSTANCING__
        sd->object = PRIM_NONE;
 #endif
+       sd->lamp = LAMP_NONE;
        sd->prim = PRIM_NONE;
 #ifdef __UV__
        sd->u = 0.0f;
@@ -431,6 +435,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
 #  ifdef __INSTANCING__
        sd->object = PRIM_NONE; /* todo: fill this for texture coordinates */
 #  endif
+       sd->lamp = LAMP_NONE;
        sd->prim = PRIM_NONE;
        sd->type = PRIMITIVE_NONE;
 
@@ -1143,6 +1148,7 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
                /* setup shaderdata from stack. it's mostly setup already in
                 * shader_setup_from_volume, this switching should be quick */
                sd->object = stack[i].object;
+               sd->lamp = LAMP_NONE;
                sd->shader = stack[i].shader;
 
                sd->flag &= ~SD_SHADER_FLAGS;
index 919dafbc780478bd72f554b24d12b5fa5a1cd35c..5b8b760c48c1aabc2fe83d989d4d95773e8aa297 100644 (file)
@@ -957,6 +957,8 @@ typedef ccl_addr_space struct ShaderData {
        float v;
        /* object id if there is one, ~0 otherwise */
        int object;
+       /* lamp id if there is one, ~0 otherwise */
+       int lamp;
 
        /* motion blur sample time */
        float time;
index cce4e89e7158a3ce0204e71d98d3de6b750e6441..9af4a0182d9520b88566111f852cc699622dc46a 100644 (file)
@@ -90,7 +90,15 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s
                }
                case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
                case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
-               case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
+               case NODE_INFO_OB_RANDOM: {
+                       if(sd->lamp != LAMP_NONE) {
+                               data = lamp_random_number(kg, sd->lamp);
+                       }
+                       else {
+                               data = object_random_number(kg, sd->object);
+                       }
+                       break;
+               }
                default: data = 0.0f; break;
        }
 
index b37a0768b53bb48598d4213477b538bffb0fa830..b62453cf5fc9a0241bd00a9c11559adeccfed747 100644 (file)
@@ -134,6 +134,7 @@ NODE_DEFINE(Light)
 
        SOCKET_INT(samples, "Samples", 1);
        SOCKET_INT(max_bounces, "Max Bounces", 1024);
+       SOCKET_UINT(random_id, "Random ID", 0);
 
        SOCKET_BOOLEAN(is_portal, "Is Portal", false);
        SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
@@ -638,6 +639,7 @@ void LightManager::device_update_points(Device *,
                int shader_id = scene->shader_manager->get_shader_id(shader);
                float samples = __int_as_float(light->samples);
                float max_bounces = __int_as_float(light->max_bounces);
+               float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF);
 
                if(!light->cast_shadow)
                        shader_id &= ~SHADER_CAST_SHADOW;
@@ -758,7 +760,7 @@ void LightManager::device_update_points(Device *,
                        light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
                }
 
-               light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
+               light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, random, 0.0f, 0.0f);
 
                Transform tfm = light->tfm;
                Transform itfm = transform_inverse(tfm);
index 7e9014eb823bb919f7cab695c8ce623a266e1fb0..97b7b971c732e52853179dd5a571ebfb9922fefb 100644 (file)
@@ -70,6 +70,7 @@ public:
        Shader *shader;
        int samples;
        int max_bounces;
+       uint random_id;
 
        void tag_update(Scene *scene);