diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-28 00:37:24 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-28 00:37:24 +0400 |
commit | cdee3435c67abebb633cb09410c4a87d42ff61e3 (patch) | |
tree | 9647e36a3661caab918e7726a5971b58b444d403 | |
parent | 136d27b350355232ebe4d0a13427777445334b05 (diff) |
Cycles: internal changes that should have no effect on user level yet, added
shader flags for various purposes, and some code for light types other than
points.
26 files changed, 512 insertions, 229 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 89c2829175c..8d3f709cdef 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -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) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index f9ebfdc0bb5..ca2f7e497df 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -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 = "" diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index e693efb2d7f..a4944a378e0 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -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); } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 3993efbce39..0c962e3c5f0 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -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); } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 9bb7cb45e35..6f03cac315c 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -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; diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 7e5fa25c662..52a3852aa01 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -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_")); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 58c9183e58a..13c48464088 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -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); diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 77e73e932ef..68d08a2655f 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -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 diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index 5d9afb6418f..df291b66b23 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -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); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index d6977c24c53..e438780b1c8 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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); diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 0cf2091590c..c1bcbb067b5 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -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) diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 19635b2664c..2bfb1b3b88e 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -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) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index e09eaa8284c..bda037e88cc 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 3f0b1610181..18a8e974492 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -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); diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index bd5c07753ad..62e02f1a01a 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -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; diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index a1b39c6ca1e..411efc8be8f 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -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; } diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index b13cab55404..74943fd0ff7 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -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) diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index dbc333260ee..19cbcb55386 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -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); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4fd562b540c..9e7e2a8a81d 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler) TransparentBsdfNode::TransparentBsdfNode() { + name = "transparent"; closure = CLOSURE_BSDF_TRANSPARENT_ID; } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index fec1ab7f4c8..b91531ac462 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -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; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 446cf72f5d6..b0173334c76 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -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; diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 93d8ebf1301..a969dd66c4c 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -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; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 548beaaecdd..6e827ec94bb 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -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; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index cc8bc473a3f..45efa123ef6 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -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); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8b527691bd9..a1687ae5e29 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -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; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index c0418b3d8fd..38e90f0b2b2 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -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__ */ |