diff options
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__ */ |