Cycles: internal changes that should have no effect on user level yet, added
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 27 Sep 2011 20:37:24 +0000 (20:37 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 27 Sep 2011 20:37:24 +0000 (20:37 +0000)
shader flags for various purposes, and some code for light types other than
points.

26 files changed:
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_object.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/kernel/kernel.cpp
intern/cycles/kernel/kernel_emission.h
intern/cycles/kernel/kernel_light.h
intern/cycles/kernel/kernel_montecarlo.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_bsdf.h
intern/cycles/render/light.cpp
intern/cycles/render/light.h
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/render/osl.cpp
intern/cycles/render/scene.h
intern/cycles/render/shader.cpp
intern/cycles/render/shader.h
intern/cycles/render/svm.cpp
intern/cycles/util/util_math.h

index 89c2829175c84a395e3f64a8ed24387eb6e81781..8d3f709cdef9ae334af6e67abed409a7cf8471d4 100644 (file)
@@ -116,11 +116,23 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
         bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles material settings")
+        cls.sample_as_light = BoolProperty(name="Sample as Light", description="Use direct light sampling, to reduce noise for small or strong emitting materials", default=False)
+        cls.homogeneous_volume = BoolProperty(name="Homogeneous Volume", description="When using volume rendering, assume volume has the same density everywhere, for faster rendering", default=False)
 
     @classmethod
     def unregister(cls):
         del bpy.types.Material.cycles
 
+class CyclesLampSettings(bpy.types.PropertyGroup):
+    @classmethod
+    def register(cls):
+        bpy.types.Lamp.cycles = PointerProperty(type=cls, name="Cycles Lamp Settings", description="Cycles lamp settings")
+        cls.cast_shadow = BoolProperty(name="Cast Shadow", description="Lamp casts shadows", default=True)
+
+    @classmethod
+    def unregister(cls):
+        del bpy.types.Lamp.cycles
+
 class CyclesWorldSettings(bpy.types.PropertyGroup):
     @classmethod
     def register(cls):
@@ -168,6 +180,7 @@ def register():
     bpy.utils.register_class(CyclesRenderSettings)
     bpy.utils.register_class(CyclesCameraSettings)
     bpy.utils.register_class(CyclesMaterialSettings)
+    bpy.utils.register_class(CyclesLampSettings)
     bpy.utils.register_class(CyclesWorldSettings)
     bpy.utils.register_class(CyclesVisibilitySettings)
     bpy.utils.register_class(CyclesMeshSettings)
@@ -176,6 +189,7 @@ def unregister():
     bpy.utils.unregister_class(CyclesRenderSettings)
     bpy.utils.unregister_class(CyclesCameraSettings)
     bpy.utils.unregister_class(CyclesMaterialSettings)
+    bpy.utils.unregister_class(CyclesLampSettings)
     bpy.utils.unregister_class(CyclesWorldSettings)
     bpy.utils.unregister_class(CyclesMeshSettings)
     bpy.utils.unregister_class(CyclesVisibilitySettings)
index f9ebfdc0bb5aab4a14359553753d1df9d86dc319..ca2f7e497df125af604de600f9469ec59859377b 100644 (file)
@@ -360,7 +360,48 @@ def panel_node_draw(layout, id, output_type, input_name):
         layout.template_node_view(ntree, node, input);
 
 class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
-    bl_label = "Surface"
+    bl_label = "Lamp"
+    bl_context = "data"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        return False
+        #return context.lamp and CyclesButtonsPanel.poll(context)
+
+    def draw(self, context):
+        layout = self.layout
+
+        lamp = context.lamp
+        clamp = lamp.cycles
+
+        layout.prop(lamp, "type", expand=True)
+
+        split = layout.split()
+        col = split.column(align=True)
+
+        if lamp.type in ('POINT', 'SUN', 'SPOT'):
+            col.prop(lamp, "shadow_soft_size", text="Size")
+        elif lamp.type == 'AREA':
+            col.prop(lamp, "shape", text="")
+            sub = col.column(align=True)
+
+            if lamp.shape == 'SQUARE':
+                sub.prop(lamp, "size")
+            elif lamp.shape == 'RECTANGLE':
+                sub.prop(lamp, "size", text="Size X")
+                sub.prop(lamp, "size_y", text="Size Y")
+
+        col = split.column()
+        col.prop(clamp, "cast_shadow")
+
+        if lamp.type == 'SPOT':
+            layout.label(text="Not supported, interpreted as point lamp.")
+        elif lamp.type == 'HEMI':
+            layout.label(text="Not supported, interpreted as sun lamp.")
+   
+class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
+    bl_label = "Nodes"
     bl_context = "data"
 
     @classmethod
@@ -399,8 +440,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
         layout = self.layout
         layout.active = False
 
-        mat = context.world
-        panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Volume')
+        world = context.world
+        panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
 
 class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
     bl_label = "Surface"
@@ -429,8 +470,12 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
         layout.active = False
 
         mat = context.material
+        cmat = mat.cycles
+
         panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
 
+        layout.prop(cmat, "homogeneous_volume")
+
 class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
     bl_label = "Displacement"
     bl_context = "material"
@@ -452,17 +497,22 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
 
     @classmethod
     def poll(cls, context):
-        # return context.material and CyclesButtonsPanel.poll(context)
         return False
+        #return context.material and CyclesButtonsPanel.poll(context)
 
     def draw(self, context):
         layout = self.layout
 
         mat = context.material
+        cmat = mat.cycles
+
+        split = layout.split()
     
-        row = layout.row()
-        row.label(text="Light Group:")
-        row.prop(mat, "light_group", text="")
+        col = split.column()
+        col.prop(cmat, "sample_as_light")
+
+        col = split.column()
+        col.prop(cmat, "homogeneous_volume")
 
 class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
     bl_label = ""
index e693efb2d7f0c4981862bca55616e6cbb21efe6a..a4944a378e07f03d66f9472cda55f8edb97b5b58 100644 (file)
@@ -87,12 +87,58 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
 
        if(!light_map.sync(&light, b_ob, b_parent, key))
                return;
+       
+       BL::Lamp b_lamp(b_ob.data());
+
+       /* type */
+#if 0
+       switch(b_lamp.type()) {
+               case BL::Lamp::type_POINT: {
+                       BL::PointLamp b_point_lamp(b_lamp);
+                       light->size = b_point_lamp.shadow_soft_size();
+#endif
+                       light->type = LIGHT_POINT;
+#if 0
+                       break;
+               }
+               case BL::Lamp::type_SPOT: {
+                       BL::SpotLamp b_spot_lamp(b_lamp);
+                       light->size = b_spot_lamp.shadow_soft_size();
+                       light->type = LIGHT_POINT;
+                       break;
+               }
+               case BL::Lamp::type_HEMI: {
+                       light->type = LIGHT_DISTANT;
+                       light->size = 0.0f;
+                       break;
+               }
+               case BL::Lamp::type_SUN: {
+                       BL::SunLamp b_sun_lamp(b_lamp);
+                       light->size = b_sun_lamp.shadow_soft_size();
+                       light->type = LIGHT_DISTANT;
+                       break;
+               }
+               case BL::Lamp::type_AREA: {
+                       BL::AreaLamp b_area_lamp(b_lamp);
+                       light->size = 1.0f;
+                       light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
+                       light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
+                       light->sizeu = b_area_lamp.size();
+                       if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
+                               light->sizev = b_area_lamp.size_y();
+                       else
+                               light->sizev = light->sizeu;
+                       light->type = LIGHT_AREA;
+                       break;
+               }
+       }
+#endif
 
        /* location */
        light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
+       light->dir = make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
 
        /* shader */
-       BL::Lamp b_lamp(b_ob.data());
        vector<uint> used_shaders;
 
        find_shader(b_lamp, used_shaders);
@@ -102,6 +148,10 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
 
        light->shader = used_shaders[0];
 
+       /* shadow */
+       //PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
+       //light->cast_shadow = get_boolean(clamp, "cast_shadow");
+
        /* tag */
        light->tag_update(scene);
 }
index 3993efbce39f306077b868fd0beaa058a8ae88b6..0c962e3c5f0aa14538d042a359790456d8006dce 100644 (file)
@@ -587,6 +587,11 @@ void BlenderSync::sync_materials()
                                graph->connect(closure->output("BSDF"), out->input("Surface"));
                        }
 
+                       /* settings */
+                       PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
+                       //shader->sample_as_light = get_boolean(cmat, "sample_as_light");
+                       shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume");
+
                        shader->set_graph(graph);
                        shader->tag_update(scene);
                }
index 9bb7cb45e35c6bde03baf44252b89682a5b89f63..6f03cac315c3a8e09df8487c6b493fc7173e1ef9 100644 (file)
@@ -83,12 +83,17 @@ bool BlenderSync::sync_recalc()
                        object_map.set_recalc(*b_ob);
                        light_map.set_recalc(*b_ob);
                }
+
                if(object_is_mesh(*b_ob)) {
                        if(b_ob->recalc_data() || b_ob->data().recalc()) {
                                BL::ID key = object_is_modified(*b_ob)? *b_ob: b_ob->data();
                                mesh_map.set_recalc(key);
                        }
                }
+               else if(object_is_light(*b_ob)) {
+                       if(b_ob->recalc_data() || b_ob->data().recalc())
+                               light_map.set_recalc(*b_ob);
+               }
        }
 
        BL::BlendData::meshes_iterator b_mesh;
index 7e5fa25c662e3b52009fcf740854b257bfa2a766..52a3852aa01793fb46f51b3871917e0ccadaf21c 100644 (file)
@@ -73,82 +73,17 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
 
 void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height)
 {
-       if(strcmp(name, "__bvh_nodes") == 0) {
-               kg->__bvh_nodes.data = (float4*)mem;
-               kg->__bvh_nodes.width = width;
+       if(0) {
        }
-       else if(strcmp(name, "__objects") == 0) {
-               kg->__objects.data = (float4*)mem;
-               kg->__objects.width = width;
-       }
-       else if(strcmp(name, "__tri_normal") == 0) {
-               kg->__tri_normal.data = (float4*)mem;
-               kg->__tri_normal.width = width;
-       }
-       else if(strcmp(name, "__tri_woop") == 0) {
-               kg->__tri_woop.data = (float4*)mem;
-               kg->__tri_woop.width = width;
-       }
-       else if(strcmp(name, "__prim_visibility") == 0) {
-               kg->__prim_visibility.data = (uint*)mem;
-               kg->__prim_visibility.width = width;
-       }
-       else if(strcmp(name, "__prim_index") == 0) {
-               kg->__prim_index.data = (uint*)mem;
-               kg->__prim_index.width = width;
-       }
-       else if(strcmp(name, "__prim_object") == 0) {
-               kg->__prim_object.data = (uint*)mem;
-               kg->__prim_object.width = width;
-       }
-       else if(strcmp(name, "__object_node") == 0) {
-               kg->__object_node.data = (uint*)mem;
-               kg->__object_node.width = width;
-       }
-       else if(strcmp(name, "__tri_vnormal") == 0) {
-               kg->__tri_vnormal.data = (float4*)mem;
-               kg->__tri_vnormal.width = width;
-       }
-       else if(strcmp(name, "__tri_vindex") == 0) {
-               kg->__tri_vindex.data = (float4*)mem;
-               kg->__tri_vindex.width = width;
-       }
-       else if(strcmp(name, "__tri_verts") == 0) {
-               kg->__tri_verts.data = (float4*)mem;
-               kg->__tri_verts.width = width;
-       }
-       else if(strcmp(name, "__light_distribution") == 0) {
-               kg->__light_distribution.data = (float4*)mem;
-               kg->__light_distribution.width = width;
-       }
-       else if(strcmp(name, "__light_point") == 0) {
-               kg->__light_point.data = (float4*)mem;
-               kg->__light_point.width = width;
-       }
-       else if(strcmp(name, "__svm_nodes") == 0) {
-               kg->__svm_nodes.data = (uint4*)mem;
-               kg->__svm_nodes.width = width;
-       }
-       else if(strcmp(name, "__filter_table") == 0) {
-               kg->__filter_table.data = (float*)mem;
-               kg->__filter_table.width = width;
-       }
-       else if(strcmp(name, "__sobol_directions") == 0) {
-               kg->__sobol_directions.data = (uint*)mem;
-               kg->__sobol_directions.width = width;
-       }
-       else if(strcmp(name, "__attributes_map") == 0) {
-               kg->__attributes_map.data = (uint4*)mem;
-               kg->__attributes_map.width = width;
-       }
-       else if(strcmp(name, "__attributes_float") == 0) {
-               kg->__attributes_float.data = (float*)mem;
-               kg->__attributes_float.width = width;
-       }
-       else if(strcmp(name, "__attributes_float3") == 0) {
-               kg->__attributes_float3.data = (float4*)mem;
-               kg->__attributes_float3.width = width;
+
+#define KERNEL_TEX(type, ttype, tname) \
+       else if(strcmp(name, #tname) == 0) { \
+               kg->tname.data = (type*)mem; \
+               kg->tname.width = width; \
        }
+#define KERNEL_IMAGE_TEX(type, ttype, tname)
+#include "kernel_textures.h"
+
        else if(strstr(name, "__tex_image")) {
                texture_image_uchar4 *tex = NULL;
                int id = atoi(name + strlen("__tex_image_"));
index 58c9183e58a1472d8f75c80d45c72c37a2bafda3..13c48464088836082753b5be2e8d29e1f913fcff 100644 (file)
@@ -63,15 +63,11 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
                light_sample(kg, randt, randu, randv, sd->P, &ls);
        }
 
-       /* compute incoming direction and distance */
-       float t;
-       float3 omega_in = normalize_len(ls.P - sd->P, &t);
-
        /* compute pdf */
-       float pdf = light_sample_pdf(kg, &ls, -omega_in, t);
+       float pdf = light_sample_pdf(kg, &ls, -ls.D, ls.t);
 
        /* evaluate closure */
-       *eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -omega_in);
+       *eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D);
 
        if(is_zero(*eval) || pdf == 0.0f)
                return false;
@@ -80,7 +76,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
 
        /* evaluate BSDF at shading point */
        float bsdf_pdf;
-       float3 bsdf_eval = shader_bsdf_eval(kg, sd, omega_in, &bsdf_pdf);
+       float3 bsdf_eval = shader_bsdf_eval(kg, sd, ls.D, &bsdf_pdf);
 
        *eval *= bsdf_eval/pdf;
 
@@ -92,29 +88,34 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
                float mis_weight = power_heuristic(pdf, bsdf_pdf);
                *eval *= mis_weight;
        }
-       else {
+       else if(!(ls.shader & SHADER_AREA_LIGHT)) {
                /* ensure point light works in Watts, this should be handled
                 * elsewhere but for now together with the diffuse emission
                 * closure it works out to the right value */
                *eval *= 0.25f;
+
+               /* XXX verify with other light types */
        }
 
-#if 0
-       /* todo: implement this in light */
-       bool no_shadow = true;
+       if(ls.shader & SHADER_CAST_SHADOW) {
+               /* setup ray */
+               ray->P = ray_offset(sd->P, sd->Ng);
 
-       if(no_shadow) {
-               ray->t = 0.0f;
+               if(ls.t == FLT_MAX) {
+                       /* distant light */
+                       ray->D = ls.D;
+                       ray->t = ls.t;
+               }
+               else {
+                       /* other lights, avoid self-intersection */
+                       ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
+                       ray->D = normalize_len(ray->D, &ray->t);
+               }
        }
        else {
-#endif
-               /* setup ray */
-               ray->P = ray_offset(sd->P, sd->Ng);
-               ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
-               ray->D = normalize_len(ray->D, &ray->t);
-#if 0
+               /* signal to not cast shadow ray */
+               ray->t = 0.0f;
        }
-#endif
 
        return true;
 }
@@ -126,7 +127,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
        /* evaluate emissive closure */
        float3 L = shader_emissive_eval(kg, sd);
 
-       if(!(path_flag & PATH_RAY_SINGULAR)) {
+       if(!(path_flag & PATH_RAY_SINGULAR) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
                /* multiple importance sampling */
                float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
                float mis_weight = power_heuristic(bsdf_pdf, pdf);
index 77e73e932ef77952916dab25042fd3ecef38cd84..68d08a2655f2eb97a66eb0405f5feae5c93b271d 100644 (file)
@@ -20,30 +20,112 @@ CCL_NAMESPACE_BEGIN
 
 typedef struct LightSample {
        float3 P;
+       float3 D;
        float3 Ng;
+       float t;
        int object;
        int prim;
        int shader;
-       float weight;
 } LightSample;
 
-/* Point Light */
+/* Regular Light */
 
-__device void point_light_sample(KernelGlobals *kg, int point,
+__device float3 disk_light_sample(float3 v, float randu, float randv)
+{
+       float3 ru, rv;
+
+       make_orthonormals(v, &ru, &rv);
+       to_unit_disk(&randu, &randv);
+
+       return ru*randu + rv*randv;
+}
+
+__device float3 distant_light_sample(float3 D, float size, float randu, float randv)
+{
+       return normalize(D + disk_light_sample(D, randu, randv)*size);
+}
+
+__device float3 sphere_light_sample(float3 P, float3 center, float size, float randu, float randv)
+{
+       return disk_light_sample(normalize(P - center), randu, randv)*size;
+}
+
+__device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv)
+{
+       randu = randu - 0.5f;
+       randv = randv - 0.5f;
+
+       return axisu*randu + axisv*randv;
+}
+
+__device void regular_light_sample(KernelGlobals *kg, int point,
        float randu, float randv, float3 P, LightSample *ls)
 {
-       float4 f = kernel_tex_fetch(__light_point, point);
+       float4 data0 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 0);
+       float4 data1 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 1);
+
+       LightType type = (LightType)__float_as_int(data0.x);
+
+       if(type == LIGHT_DISTANT) {
+               /* distant light */
+               float3 D = make_float3(data0.y, data0.z, data0.w);
+               float size = data1.y;
+
+               if(size > 0.0f)
+                       D = distant_light_sample(D, size, randu, randv);
+
+               ls->P = D;
+               ls->Ng = -D;
+               ls->D = D;
+               ls->t = FLT_MAX;
+       }
+       else {
+               ls->P = make_float3(data0.y, data0.z, data0.w);
+
+               if(type == LIGHT_POINT) {
+                       float size = data1.y;
+
+                       /* sphere light */
+                       if(size > 0.0f)
+                               ls->P += sphere_light_sample(P, ls->P, size, randu, randv);
+
+                       ls->Ng = normalize(P - ls->P);
+               }
+               else {
+                       /* area light */
+                       float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2);
+                       float4 data3 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 3);
+
+                       float3 axisu = make_float3(data1.y, data1.z, data2.w);
+                       float3 axisv = make_float3(data2.y, data2.z, data2.w);
+                       float3 D = make_float3(data3.y, data3.z, data3.w);
+
+                       ls->P += area_light_sample(axisu, axisv, randu, randv);
+                       ls->Ng = D;
+               }
+
+               ls->t = 0.0f;
+       }
 
-       ls->P = make_float3(f.x, f.y, f.z);
-       ls->Ng = normalize(ls->P - P);
-       ls->shader = __float_as_int(f.w);
+       ls->shader = __float_as_int(data1.x);
        ls->object = ~0;
        ls->prim = ~0;
 }
 
-__device float point_light_pdf(KernelGlobals *kg, float t)
+__device float regular_light_pdf(KernelGlobals *kg,
+       const float3 Ng, const float3 I, float t)
 {
-       return t*t*kernel_data.integrator.pdf_lights;
+       float pdf = kernel_data.integrator.pdf_lights;
+
+       if(t == FLT_MAX)
+               return pdf;
+
+       float cos_pi = fabsf(dot(Ng, I));
+
+       if(cos_pi == 0.0f)
+               return 0.0f;
+
+       return t*t*pdf/cos_pi;
 }
 
 /* Triangle Light */
@@ -56,6 +138,7 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
        ls->Ng = triangle_normal_MT(kg, prim, &ls->shader);
        ls->object = object;
        ls->prim = prim;
+       ls->t = 0.0f;
 
 #ifdef __INSTANCING__
        /* instance transform */
@@ -117,7 +200,6 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
        /* fetch light data */
        float4 l = kernel_tex_fetch(__light_distribution, index);
        int prim = __float_as_int(l.y);
-       ls->weight = l.z;
 
        if(prim >= 0) {
                int object = __float_as_int(l.w);
@@ -125,8 +207,12 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
        }
        else {
                int point = -prim-1;
-               point_light_sample(kg, point, randu, randv, P, ls);
+               regular_light_sample(kg, point, randu, randv, P, ls);
        }
+
+       /* compute incoming direction and distance */
+       if(ls->t != FLT_MAX)
+               ls->D = normalize_len(ls->P - P, &ls->t);
 }
 
 __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
@@ -136,19 +222,19 @@ __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, fl
        if(ls->prim != ~0)
                pdf = triangle_light_pdf(kg, ls->Ng, I, t);
        else
-               pdf = point_light_pdf(kg, t);
+               pdf = regular_light_pdf(kg, ls->Ng, I, t);
        
        return pdf;
 }
 
 __device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls)
 {
-       point_light_sample(kg, index, randu, randv, P, ls);
+       regular_light_sample(kg, index, randu, randv, P, ls);
 }
 
 __device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
 {
-       return point_light_pdf(kg, t);
+       return regular_light_pdf(kg, ls->Ng, I, t);
 }
 
 CCL_NAMESPACE_END
index 5d9afb6418fb040750682647acad94dc7b4c32de..df291b66b231746c193442c351efa953fed688ce 100644 (file)
@@ -67,17 +67,6 @@ __device void to_unit_disk(float *x, float *y)
        *y = r * sinf(phi);
 }
 
-__device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
-{
-       if(N.x != N.y || N.x != N.z)
-               *a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x);  //(1,1,1)x N
-       else
-               *a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x);  //(-1,1,1)x N
-
-       *a = normalize(*a);
-       *b = cross(N, *a);
-}
-
 __device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b)
 {
        *b = cross(N, T);
index d6977c24c5399e8baa311ac0a4f648331c9442cc..e438780b1c84519edd9d31d84e332c5f7f372b35 100644 (file)
@@ -162,19 +162,6 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
        return average(throughput);
 }
 
-#ifdef __TRANSPARENT_SHADOWS__
-__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
-{
-       int prim = kernel_tex_fetch(__prim_index, isect->prim);
-       float4 Ns = kernel_tex_fetch(__tri_normal, prim);
-       int shader = __float_as_int(Ns.w);
-
-       /* todo: add shader flag to check this */
-
-       return true;
-}
-#endif
-
 __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
 {
        if(ray->t == 0.0f)
@@ -229,12 +216,10 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
                                throughput *= shader_bsdf_transparency(kg, &sd);
 
                                ray->P = ray_offset(sd.P, -sd.Ng);
-                               ray->t = len(Pend - ray->P);
+                               ray->t = (ray->t == FLT_MAX)? FLT_MAX: len(Pend - ray->P);
 
                                bounce++;
                        }
-
-                       return true;
                }
        }
 #endif
@@ -298,10 +283,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
 
 #ifdef __EMISSION__
                /* emission */
-               if(kernel_data.integrator.use_emission) {
-                       if(sd.flag & SD_EMISSION)
-                               L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
-               }
+               if(sd.flag & SD_EMISSION)
+                       L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
 #endif
 
                /* path termination. this is a strange place to put the termination, it's
@@ -316,7 +299,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
                throughput /= probability;
 
 #ifdef __EMISSION__
-               if(kernel_data.integrator.use_emission) {
+               if(kernel_data.integrator.use_direct_light) {
                        /* sample illumination from lights to find path contribution */
                        if(sd.flag & SD_BSDF_HAS_EVAL) {
                                float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
index 0cf2091590c38df29577f253e1a7a54336c0358e..c1bcbb067b56b8d09133be3e091f96a216bf17c9 100644 (file)
@@ -60,7 +60,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
        sd->N = Ng;
        sd->I = -ray->D;
        sd->shader = shader;
-       sd->flag = 0;
 
        /* triangle */
 #ifdef __INSTANCING__
@@ -73,10 +72,10 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
 #endif
 
        /* smooth normal */
-       if(sd->shader < 0) {
+       if(sd->shader & SHADER_SMOOTH_NORMAL)
                sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
-               sd->shader = -sd->shader;
-       }
+
+       sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
 
 #ifdef __DPDU__
        /* dPdu/dPdv */
@@ -103,7 +102,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
        bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
 
        if(backfacing) {
-               sd->flag = SD_BACKFACING;
+               sd->flag |= SD_BACKFACING;
                sd->Ng = -sd->Ng;
                sd->N = -sd->N;
 #ifdef __DPDU__
@@ -132,7 +131,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
        sd->Ng = Ng;
        sd->I = I;
        sd->shader = shader;
-       sd->flag = 0;
 
        /* primitive */
 #ifdef __INSTANCING__
@@ -159,9 +157,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 #endif
 
        /* smooth normal */
-       if(sd->shader < 0) {
+       if(sd->shader & SHADER_SMOOTH_NORMAL) {
                sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
-               sd->shader = -sd->shader;
 
 #ifdef __INSTANCING__
                if(instanced)
@@ -169,6 +166,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
 #endif
        }
 
+       sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
+
 #ifdef __DPDU__
        /* dPdu/dPdv */
        if(sd->prim == ~0) {
@@ -192,7 +191,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
                bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
 
                if(backfacing) {
-                       sd->flag = SD_BACKFACING;
+                       sd->flag |= SD_BACKFACING;
                        sd->Ng = -sd->Ng;
                        sd->N = -sd->N;
 #ifdef __DPDU__
@@ -245,7 +244,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
        sd->Ng = -sd->P;
        sd->I = -sd->P;
        sd->shader = kernel_data.background.shader;
-       sd->flag = 0;
+       sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
 
 #ifdef __INSTANCING__
        sd->object = ~0;
@@ -410,7 +409,7 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
        for(int i = 0; i< sd->num_closure; i++) {
                ShaderClosure *sc = &sd->closure[i];
 
-               if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // XXX osl
+               if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
                        eval += sc->weight;
        }
 
@@ -428,8 +427,9 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
 
 __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
 {
+       float3 eval;
 #ifdef __MULTI_CLOSURE__
-       float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+       eval = make_float3(0.0f, 0.0f, 0.0f);
 
        for(int i = 0; i < sd->num_closure; i++) {
                ShaderClosure *sc = &sd->closure[i];
@@ -442,11 +442,11 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
 #endif
                }
        }
-
-       return eval;
 #else
-       return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
+       eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
 #endif
+
+       return eval;
 }
 
 /* Holdout */
@@ -581,6 +581,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
 #endif
 }
 
+/* Transparent Shadows */
+
+#ifdef __TRANSPARENT_SHADOWS__
+__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
+{
+       int prim = kernel_tex_fetch(__prim_index, isect->prim);
+       float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+       int shader = __float_as_int(Ns.w);
+       int flag = kernel_tex_fetch(__shader_flag, shader & SHADER_MASK);
+
+       return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
+}
+#endif
+
 /* Free ShaderData */
 
 __device void shader_release(KernelGlobals *kg, ShaderData *sd)
index 19635b2664c799ece78f320adcd0e2e18b63ea9b..2bfb1b3b88e4470a9a2f1f4fef968ee683cc4719 100644 (file)
@@ -32,10 +32,11 @@ KERNEL_TEX(float4, texture_float4, __attributes_float3)
 
 /* lights */
 KERNEL_TEX(float4, texture_float4, __light_distribution)
-KERNEL_TEX(float4, texture_float4, __light_point)
+KERNEL_TEX(float4, texture_float4, __light_data)
 
 /* shaders */
 KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
+KERNEL_TEX(uint, texture_uint, __shader_flag)
 
 /* camera/film */
 KERNEL_TEX(float, texture_float, __filter_table)
index e09eaa8284c9ae9d702706cea26e3c9f0df65667..bda037e88cc6a2401e73b1843e4d9c86bd5dfaa2 100644 (file)
@@ -26,6 +26,7 @@
 CCL_NAMESPACE_BEGIN
 
 #define OBJECT_SIZE 16
+#define LIGHT_SIZE     4
 
 #define __SOBOL__
 #define __INSTANCING__
@@ -43,12 +44,12 @@ CCL_NAMESPACE_BEGIN
 #define __EMISSION__
 #define __TEXTURES__
 #define __HOLDOUT__
+//#define __MULTI_CLOSURE__
+//#define __TRANSPARENT_SHADOWS__
+//#define __MULTI_LIGHT__
 #endif
 
 #ifdef __KERNEL_CPU__
-//#define __MULTI_CLOSURE__
-//#define __MULTI_LIGHT__
-//#define __TRANSPARENT_SHADOWS__
 //#define __OSL__
 #endif
 
@@ -79,6 +80,7 @@ enum PathTraceDimension {
 /* these flag values correspond exactly to OSL defaults, so be careful not to
  * change this, or if you do, set the "raytypes" shading system attribute with
  * your own new ray types and bitflag values */
+
 enum PathRayFlag {
        PATH_RAY_CAMERA = 1,
        PATH_RAY_SHADOW = 2,
@@ -92,28 +94,6 @@ enum PathRayFlag {
        PATH_RAY_ALL = (1|2|4|8|16|32|64|128)
 };
 
-/* Bidirectional Path Tracing */
-
-enum BidirTraceDimension {
-       BRNG_FILTER_U = 0,
-       BRNG_FILTER_V = 1,
-       BRNG_LENS_U = 2,
-       BRNG_LENS_V = 3,
-       BRNG_LIGHT_U = 4,
-       BRNG_LIGHT_V = 5,
-       BRNG_LIGHT = 6,
-       BRNG_LIGHT_F = 7,
-       BRNG_EMISSIVE_U = 8,
-       BRNG_EMISSIVE_V = 9,
-       BRNG_BASE_NUM = 10,
-
-       BRNG_BSDF_U = 0,
-       BRNG_BSDF_V = 1,
-       BRNG_BSDF = 2,
-       BRNG_TERMINATE = 3,
-       BRNG_BOUNCE_NUM = 4
-};
-
 /* Closure Label */
 
 typedef enum ClosureLabel {
@@ -132,16 +112,23 @@ typedef enum ClosureLabel {
        LABEL_STOP = 2048
 } ClosureLabel;
 
-/* Ray Type */
+/* Shader Flag */
+
+typedef enum ShaderFlag {
+       SHADER_SMOOTH_NORMAL = (1 << 31),
+       SHADER_CAST_SHADOW = (1 << 30),
+       SHADER_AREA_LIGHT = (1 << 29),
 
-typedef enum RayType {
-       RayTypeCamera = 1,
-       RayTypeShadow = 2,
-       RayTypeReflection = 4,
-       RayTypeRefraction = 8,
-       RayTypeDiffuse = 16,
-       RayTypeGlossy = 32
-} RayType;
+       SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT)
+} ShaderFlag;
+
+/* Light Type */
+
+typedef enum LightType {
+       LIGHT_POINT,
+       LIGHT_DISTANT,
+       LIGHT_AREA
+} LightType;
 
 /* Differential */
 
@@ -213,13 +200,20 @@ typedef struct ShaderClosure {
  * are in world space. */
 
 enum ShaderDataFlag {
+       /* runtime flags */
        SD_BACKFACING = 1,              /* backside of surface? */
        SD_EMISSION = 2,                /* have emissive closure? */
        SD_BSDF = 4,                    /* have bsdf closure? */
        SD_BSDF_HAS_EVAL = 8,   /* have non-singular bsdf closure? */
        SD_BSDF_GLOSSY = 16,    /* have glossy bsdf */
        SD_HOLDOUT = 32,                /* have holdout closure? */
-       SD_VOLUME = 64                  /* have volume closure? */
+       SD_VOLUME = 64,                 /* have volume closure? */
+
+       /* shader flags */
+       SD_SAMPLE_AS_LIGHT = 128,                       /* direct light sample */
+       SD_HAS_SURFACE_TRANSPARENT = 256,       /* has surface transparency */
+       SD_HAS_VOLUME = 512,                            /* has volume shader */
+       SD_HOMOGENEOUS_VOLUME = 1024            /* has homogeneous volume */
 };
 
 typedef struct ShaderData {
@@ -351,7 +345,7 @@ typedef struct KernelSunSky {
 
 typedef struct KernelIntegrator {
        /* emission */
-       int use_emission;
+       int use_direct_light;
        int num_distribution;
        int num_all_lights;
        float pdf_triangles;
index 3f0b1610181e6a9b1ff159eeb7373a79903643d7..18a8e974492cc82328cc0530eb97519b0265b095 100644 (file)
@@ -216,8 +216,10 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
        shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
 
        /* execute shader for this point */
-       if(kg->osl.surface_state[sd->shader])
-               ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
+       int shader = sd->shader & SHADER_MASK;
+
+       if(kg->osl.surface_state[shader])
+               ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
 
        /* flatten closure tree */
        sd->num_closure = 0;
@@ -351,7 +353,10 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
        shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
 
        /* execute shader */
-       ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[sd->shader]), *globals);
+       int shader = sd->shader & SHADER_MASK;
+
+       if(kg->osl.volume_state[shader])
+               ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals);
 
        /* retrieve resulting closures */
        sd->osl_closure.volume_sample_sum = 0.0f;
@@ -377,7 +382,10 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
        shaderdata_to_shaderglobals(kg, sd, 0, globals);
 
        /* execute shader */
-       ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[sd->shader]), *globals);
+       int shader = sd->shader & SHADER_MASK;
+
+       if(kg->osl.displacement_state[shader])
+               ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);
 
        /* get back position */
        sd->P = TO_FLOAT3(globals->P);
index bd5c07753adfb10ca918f01d3dc873b7460f8f0b..62e02f1a01a98ddd55691869872b33d574894ee9 100644 (file)
@@ -152,7 +152,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
 {
        float stack[SVM_STACK_SIZE];
        float closure_weight = 1.0f;
-       int offset = sd->shader;
+       int offset = sd->shader & SHADER_MASK;
 
 #ifdef __MULTI_CLOSURE__
        sd->num_closure = 0;
index a1b39c6ca1e22fdcdb55c8af8d127812cc4cbcf0..411efc8be8f6ba4971daa3a8491bf3c32ec8cdb5 100644 (file)
@@ -90,6 +90,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
                        case CLOSURE_BSDF_DIFFUSE_ID:
                                eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
+#ifdef __SVM__
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
                                eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
@@ -124,6 +125,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
                        case CLOSURE_BSDF_WESTIN_SHEEN_ID:
                                eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
                                break;
+#endif
                        default:
                                eval = make_float3(0.0f, 0.0f, 0.0f);
                                break;
@@ -134,6 +136,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
                        case CLOSURE_BSDF_DIFFUSE_ID:
                                eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
+#ifdef __SVM__
                        case CLOSURE_BSDF_TRANSLUCENT_ID:
                                eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
@@ -168,6 +171,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
                        case CLOSURE_BSDF_WESTIN_SHEEN_ID:
                                eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
                                break;
+#endif
                        default:
                                eval = make_float3(0.0f, 0.0f, 0.0f);
                                break;
@@ -183,6 +187,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
                case CLOSURE_BSDF_DIFFUSE_ID:
                        bsdf_diffuse_blur(sc, roughness);
                        break;
+#ifdef __SVM__
                case CLOSURE_BSDF_TRANSLUCENT_ID:
                        bsdf_translucent_blur(sc, roughness);
                        break;
@@ -217,6 +222,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
                case CLOSURE_BSDF_WESTIN_SHEEN_ID:
                        bsdf_westin_sheen_blur(sc, roughness);
                        break;
+#endif
                default:
                        break;
        }
index b13cab554045db9351f10d21da7643647e0f9ac1..74943fd0ff7c549f35ebd6a3ee9dbcdcc939af97 100644 (file)
@@ -32,8 +32,19 @@ CCL_NAMESPACE_BEGIN
 
 Light::Light()
 {
+       type = LIGHT_POINT;
+
        co = make_float3(0.0f, 0.0f, 0.0f);
-       radius = 0.0f;
+
+       dir = make_float3(0.0f, 0.0f, 0.0f);
+       size = 0.0f;
+
+       axisu = make_float3(0.0f, 0.0f, 0.0f);
+       sizeu = 1.0f;
+       axisv = make_float3(0.0f, 0.0f, 0.0f);
+       sizev = 1.0f;
+
+       cast_shadow = true;
        shader = 0;
 }
 
@@ -68,7 +79,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 
                /* skip if we have no emission shaders */
                foreach(uint sindex, mesh->used_shaders) {
-                       if(scene->shaders[sindex]->has_surface_emission) {
+                       Shader *shader = scene->shaders[sindex];
+
+                       if(shader->sample_as_light && shader->has_surface_emission) {
                                have_emission = true;
                                break;
                        }
@@ -79,7 +92,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
                        for(size_t i = 0; i < mesh->triangles.size(); i++) {
                                Shader *shader = scene->shaders[mesh->shader[i]];
 
-                               if(shader->has_surface_emission)
+                               if(shader->sample_as_light && shader->has_surface_emission)
                                        num_triangles++;
                        }
                }
@@ -104,7 +117,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 
                /* skip if we have no emission shaders */
                foreach(uint sindex, mesh->used_shaders) {
-                       if(scene->shaders[sindex]->has_surface_emission) {
+                       Shader *shader = scene->shaders[sindex];
+
+                       if(shader->sample_as_light && shader->has_surface_emission) {
                                have_emission = true;
                                break;
                        }
@@ -118,7 +133,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
                        for(size_t i = 0; i < mesh->triangles.size(); i++) {
                                Shader *shader = scene->shaders[mesh->shader[i]];
 
-                               if(shader->has_surface_emission) {
+                               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 = 1.0f;
@@ -150,7 +165,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
                        distribution[offset].x = totarea;
                        distribution[offset].y = __int_as_float(-i-1);
                        distribution[offset].z = 1.0f;
-                       distribution[offset].w = scene->lights[i]->radius;
+                       distribution[offset].w = scene->lights[i]->size;
                        totarea += lightarea;
                }
        }
@@ -171,9 +186,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
 
        /* update device */
        KernelIntegrator *kintegrator = &dscene->data.integrator;
-       kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights);
+       kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights);
 
-       if(kintegrator->use_emission) {
+       if(kintegrator->use_direct_light) {
                /* number of emissives */
                kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
 
@@ -219,16 +234,45 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
        if(scene->lights.size() == 0)
                return;
 
-       float4 *light_point = dscene->light_point.resize(scene->lights.size());
+       float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
 
        for(size_t i = 0; i < scene->lights.size(); i++) {
-               float3 co = scene->lights[i]->co;
+               Light *light = scene->lights[i];
+               float3 co = light->co;
+               float3 dir = normalize(light->dir);
                int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
 
-               light_point[i] = make_float4(co.x, co.y, co.z, __int_as_float(shader_id));
+               if(!light->cast_shadow)
+                       shader_id &= ~SHADER_CAST_SHADOW;
+
+               if(light->type == LIGHT_POINT) {
+                       shader_id &= ~SHADER_AREA_LIGHT;
+
+                       light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
+                       light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 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(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               else if(light->type == LIGHT_DISTANT) {
+                       shader_id &= ~SHADER_AREA_LIGHT;
+
+                       light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
+                       light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 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(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               else if(light->type == LIGHT_AREA) {
+                       float3 axisu = light->axisu*(light->sizeu*light->size);
+                       float3 axisv = light->axisv*(light->sizev*light->size);
+
+                       light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.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(0.0f, axisv.x, axisv.y, axisv.z);
+                       light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z);
+               }
        }
        
-       device->tex_alloc("__light_point", dscene->light_point);
+       device->tex_alloc("__light_data", dscene->light_data);
 }
 
 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -250,10 +294,10 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce
 void LightManager::device_free(Device *device, DeviceScene *dscene)
 {
        device->tex_free(dscene->light_distribution);
-       device->tex_free(dscene->light_point);
+       device->tex_free(dscene->light_data);
 
        dscene->light_distribution.clear();
-       dscene->light_point.clear();
+       dscene->light_data.clear();
 }
 
 void LightManager::tag_update(Scene *scene)
index dbc333260eeb109527e69f42103b1c7d4e3869a4..19cbcb55386c0760512a5db3ddf883605c66f838 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __LIGHT_H__
 #define __LIGHT_H__
 
+#include "kernel_types.h"
+
 #include "util_types.h"
 #include "util_vector.h"
 
@@ -33,8 +35,19 @@ class Light {
 public:
        Light();
 
+       LightType type;
        float3 co;
-       float radius; /* not implemented yet */
+
+       float3 dir;
+       float size;
+
+       float3 axisu;
+       float sizeu;
+       float3 axisv;
+       float sizev;
+
+       bool cast_shadow;
+
        int shader;
 
        void tag_update(Scene *scene);
index 4fd562b540c8ff2bcb4b237e8ca92a26c3d057ce..9e7e2a8a81da17cbe70774163a669aa8173f9eb9 100644 (file)
@@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler)
 
 TransparentBsdfNode::TransparentBsdfNode()
 {
+       name = "transparent";
        closure = CLOSURE_BSDF_TRANSPARENT_ID;
 }
 
index fec1ab7f4c8ab66678370344d0c9d0e1dc371017..b91531ac4628c175e6dc3058d106be0d73cdf93a 100644 (file)
@@ -88,9 +88,12 @@ void Object::tag_update(Scene *scene)
                if(mesh->transform_applied)
                        mesh->need_update = true;
 
-               foreach(uint sindex, mesh->used_shaders)
-                       if(scene->shaders[sindex]->has_surface_emission)
+               foreach(uint sindex, mesh->used_shaders) {
+                       Shader *shader = scene->shaders[sindex];
+
+                       if(shader->sample_as_light && shader->has_surface_emission)
                                scene->light_manager->need_update = true;
+               }
        }
 
        scene->mesh_manager->need_update = true;
index 446cf72f5d6da50b4bc63d72731b7ff535798673..b0173334c76c97f5e66f42e4c3283ce0956be3ea 100644 (file)
@@ -91,7 +91,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
 
                if(progress.get_cancel()) return;
 
-               if(shader->has_surface_emission)
+               if(shader->sample_as_light && shader->has_surface_emission)
                        scene->light_manager->need_update = true;
 
                OSLCompiler compiler((void*)ss);
@@ -112,12 +112,16 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
        
        /* set texture system */
        scene->image_manager->set_osl_texture_system((void*)ts);
+
+       device_update_common(device, dscene, scene, progress);
 }
 
 void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
 {
        OSLGlobals *og = (OSLGlobals*)device->osl_memory();
 
+       device_free_common(device, dscene);
+
        /* clear shader engine */
        og->use = false;
        og->ss = NULL;
@@ -340,6 +344,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
 
                                        if(node->name == ustring("emission"))
                                                current_shader->has_surface_emission = true;
+                                       if(node->name == ustring("transparent"))
+                                               current_shader->has_surface_transparent = true;
                                }
                                else
                                        nodes_done = false;
@@ -403,6 +409,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
 
        shader->has_surface = false;
        shader->has_surface_emission = false;
+       shader->has_surface_transparent = false;
        shader->has_volume = false;
        shader->has_displacement = false;
 
index 93d8ebf1301ca157d422e0471ac6430a9888ab2d..a969dd66c4c2fe21c392d24749556b489b571368 100644 (file)
@@ -77,10 +77,11 @@ public:
 
        /* lights */
        device_vector<float4> light_distribution;
-       device_vector<float4> light_point;
+       device_vector<float4> light_data;
 
        /* shaders */
        device_vector<uint4> svm_nodes;
+       device_vector<uint> shader_flag;
 
        /* filter */
        device_vector<float> filter_table;
index 548beaaecdd5fdeaeaad7982af6235b650cf6a52..6e827ec94bb623af7d499a30c6a57b51c0686987 100644 (file)
@@ -39,7 +39,11 @@ Shader::Shader()
        graph = NULL;
        graph_bump = NULL;
 
+       sample_as_light = true;
+       homogeneous_volume = false;
+
        has_surface = false;
+       has_surface_transparent = false;
        has_surface_emission = false;
        has_volume = false;
        has_displacement = false;
@@ -72,7 +76,7 @@ void Shader::tag_update(Scene *scene)
        /* if the shader previously was emissive, update light distribution,
         * if the new shader is emissive, a light manager update tag will be
         * done in the shader manager device update. */
-       if(has_surface_emission)
+       if(sample_as_light && has_surface_emission)
                scene->light_manager->need_update = true;
 
        /* get requested attributes. this could be optimized by pruning unused
@@ -146,13 +150,52 @@ int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
        /* index depends bump since this setting is not in the shader */
        if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
                id += 1;
-       /* stuff in smooth flag too */
+       /* smooth flag */
        if(smooth)
-               id= -id;
+               id |= SHADER_SMOOTH_NORMAL;
+       
+       /* default flags */
+       id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
        
        return id;
 }
 
+void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+       device_free_common(device, dscene);
+
+       if(scene->shaders.size() == 0)
+               return;
+
+       uint shader_flag_size = scene->shaders.size()*2;
+       uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
+       uint i = 0;
+
+       foreach(Shader *shader, scene->shaders) {
+               uint flag = 0;
+
+               if(shader->sample_as_light)
+                       flag |= SD_SAMPLE_AS_LIGHT;
+               if(shader->has_surface_transparent)
+                       flag |= SD_HAS_SURFACE_TRANSPARENT;
+               if(shader->has_volume)
+                       flag |= SD_HAS_VOLUME;
+               if(shader->homogeneous_volume)
+                       flag |= SD_HOMOGENEOUS_VOLUME;
+
+               shader_flag[i++] = flag;
+               shader_flag[i++] = flag;
+       }
+
+       device->tex_alloc("__shader_flag", dscene->shader_flag);
+}
+
+void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
+{
+       device->tex_free(dscene->shader_flag);
+       dscene->shader_flag.clear();
+}
+
 void ShaderManager::add_default(Scene *scene)
 {
        Shader *shader;
index cc8bc473a3f1364e708b3e6b934423fca34147d4..45efa123ef678e1ab5d57c9d0e4eeb3f59bc3155 100644 (file)
@@ -56,6 +56,10 @@ public:
           level setting, so we need to handle both */
        ShaderGraph *graph_bump;
 
+       /* sampling */
+       bool sample_as_light;
+       bool homogeneous_volume;
+
        /* synchronization */
        bool need_update;
        bool need_update_attributes;
@@ -63,6 +67,7 @@ public:
        /* information about shader after compiling */
        bool has_surface;
        bool has_surface_emission;
+       bool has_surface_transparent;
        bool has_volume;
        bool has_displacement;
 
@@ -92,6 +97,9 @@ public:
        virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0;
        virtual void device_free(Device *device, DeviceScene *dscene) = 0;
 
+       void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+       void device_free_common(Device *device, DeviceScene *dscene);
+
        /* get globally unique id for a type of attribute */
        uint get_attribute_id(ustring name);
        uint get_attribute_id(Attribute::Standard std);
index 8b527691bd973f355631715982d52fecad2c07ab..a1687ae5e290b809f5e975a1ad7c5550b96b5710 100644 (file)
@@ -66,7 +66,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
 
                assert(shader->graph);
 
-               if(shader->has_surface_emission)
+               if(shader->sample_as_light && shader->has_surface_emission)
                        scene->light_manager->need_update = true;
 
                SVMCompiler compiler(scene->shader_manager, scene->image_manager,
@@ -86,11 +86,15 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
                shader->need_update = false;
        }
 
+       device_update_common(device, dscene, scene, progress);
+
        need_update = false;
 }
 
 void SVMShaderManager::device_free(Device *device, DeviceScene *dscene)
 {
+       device_free_common(device, dscene);
+
        device->tex_free(dscene->svm_nodes);
        dscene->svm_nodes.clear();
 }
@@ -461,6 +465,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
 
                if(node->name == ustring("emission"))
                        current_shader->has_surface_emission = true;
+               if(node->name == ustring("transparent"))
+                       current_shader->has_surface_transparent = true;
 
                /* end node is added outside of this */
        }
@@ -538,6 +544,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
 
                if(node->name == ustring("emission"))
                        current_shader->has_surface_emission = true;
+               if(node->name == ustring("transparent"))
+                       current_shader->has_surface_transparent = true;
 
                /* end node is added outside of this */
        }
@@ -641,6 +649,7 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
 
        shader->has_surface = false;
        shader->has_surface_emission = false;
+       shader->has_surface_transparent = false;
        shader->has_volume = false;
        shader->has_displacement = false;
 
index c0418b3d8fdcbf3320ab86d1a199170db9811db3..38e90f0b2b2a2d42576d9403575e0a646a652c9b 100644 (file)
@@ -780,6 +780,19 @@ __device_inline float triangle_area(const float3 v1, const float3 v2, const floa
 
 #endif
 
+/* Orthonormal vectors */
+
+__device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
+{
+       if(N.x != N.y || N.x != N.z)
+               *a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x);  //(1,1,1)x N
+       else
+               *a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x);  //(-1,1,1)x N
+
+       *a = normalize(*a);
+       *b = cross(N, *a);
+}
+
 CCL_NAMESPACE_END
 
 #endif /* __UTIL_MATH_H__ */