diff options
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 27 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_emission.h | 7 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 35 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/emissive.h | 15 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 14 | ||||
-rw-r--r-- | intern/cycles/render/light.h | 3 | ||||
-rw-r--r-- | intern/cycles/util/util_math.h | 6 |
9 files changed, 95 insertions, 19 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 8480b0a5256..3b906bb4bdf 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -488,9 +488,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): 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': + if lamp.type == 'HEMI': layout.label(text="Not supported, interpreted as sun lamp.") @@ -509,6 +507,29 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel): if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'): layout.prop(lamp, "color") +class CyclesLamp_PT_spot(CyclesButtonsPanel, Panel): + bl_label = "Spot Shape" + bl_context = "data" + + @classmethod + def poll(cls, context): + lamp = context.lamp + return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context) + + def draw(self, context): + layout = self.layout + + lamp = context.lamp + + split = layout.split() + + col = split.column() + sub = col.column() + sub.prop(lamp, "spot_size", text="Size") + sub.prop(lamp, "spot_blend", text="Blend", slider=True) + + col = split.column() + col.prop(lamp, "show_cone") class CyclesWorld_PT_surface(CyclesButtonsPanel, Panel): bl_label = "Surface" diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index b04e0137e37..cea3b0256bd 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -106,7 +106,9 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, case BL::Lamp::type_SPOT: { BL::SpotLamp b_spot_lamp(b_lamp); light->size = b_spot_lamp.shadow_soft_size(); - light->type = LIGHT_POINT; + light->type = LIGHT_SPOT; + light->spot_angle = b_spot_lamp.spot_size(); + light->spot_smooth = b_spot_lamp.spot_blend(); break; } case BL::Lamp::type_HEMI: { diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 0ef1425e68a..881d25ad7ba 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -104,13 +104,8 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, float mis_weight = power_heuristic(pdf, bsdf_pdf); light_eval *= mis_weight; } - /* todo: clean up these weights */ - else if(ls.shader & SHADER_AREA_LIGHT) - light_eval *= 0.25f; /* area lamp */ - else if(ls.t != FLT_MAX) - light_eval *= 0.25f*M_1_PI_F; /* point lamp */ - bsdf_eval_mul(eval, light_eval/pdf); + bsdf_eval_mul(eval, light_eval*(ls.eval_fac/pdf)); if(bsdf_eval_is_zero(eval)) return false; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index e9e7fbd4ca1..76552400f9c 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -23,6 +23,7 @@ typedef struct LightSample { float3 D; float3 Ng; float t; + float eval_fac; int object; int prim; int shader; @@ -189,6 +190,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; + ls->eval_fac = 1.0f; } #ifdef __BACKGROUND_MIS__ else if(type == LIGHT_BACKGROUND) { @@ -199,6 +201,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->Ng = D; ls->D = -D; ls->t = FLT_MAX; + ls->eval_fac = 1.0f; } #endif else { @@ -212,6 +215,36 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->P += sphere_light_sample(P, ls->P, size, randu, randv); ls->Ng = normalize(P - ls->P); + ls->eval_fac = 0.25f*M_1_PI_F; + } + else if(type == LIGHT_SPOT) { + float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2); + float size = data1.y; + + /* spot light */ + if(size > 0.0f) + ls->P += sphere_light_sample(P, ls->P, size, randu, randv); + + float3 dir = make_float3(data1.z, data1.w, data2.x); + float3 I = normalize(P - ls->P); + + float spot_angle = data2.y; + float spot_smooth = data2.z; + + float eval_fac = fabsf(dot(dir, I)); + + if(eval_fac <= spot_angle) { + eval_fac = 0.0f; + } + else { + float t = eval_fac - spot_angle; + + if(t < spot_smooth && spot_smooth != 0.0f) + eval_fac *= smoothstepf(t/spot_smooth); + } + + ls->Ng = I; + ls->eval_fac = eval_fac*0.25f*M_1_PI_F; } else { /* area light */ @@ -224,6 +257,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point, ls->P += area_light_sample(axisu, axisv, randu, randv); ls->Ng = D; + ls->eval_fac = 0.25f; } ls->t = 0.0f; @@ -262,6 +296,7 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object, ls->prim = prim; ls->t = 0.0f; ls->type = LIGHT_AREA; + ls->eval_fac = 1.0f; #ifdef __INSTANCING__ /* instance transform */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index a64c850d35a..d119057ac67 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -283,7 +283,8 @@ typedef enum LightType { LIGHT_DISTANT, LIGHT_BACKGROUND, LIGHT_AREA, - LIGHT_AO + LIGHT_AO, + LIGHT_SPOT } LightType; /* Camera Type */ diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/svm/emissive.h index e3f99e9b729..0b0218674b8 100644 --- a/intern/cycles/kernel/svm/emissive.h +++ b/intern/cycles/kernel/svm/emissive.h @@ -34,14 +34,6 @@ CCL_NAMESPACE_BEGIN /* EMISSION CLOSURE */ -__device float3 emissive_eval(const float3 Ng, const float3 I) -{ - float cosNO = fabsf(dot(Ng, I)); - float res = (cosNO > 0.0f)? 1.0f: 0.0f; - - return make_float3(res, res, res); -} - /// Return the probability distribution function in the direction I, /// given the parameters and the light's surface normal. This MUST match /// the PDF computed by sample(). @@ -51,6 +43,13 @@ __device float emissive_pdf(const float3 Ng, const float3 I) return (cosNO > 0.0f)? 1.0f: 0.0f; } +__device float3 emissive_eval(const float3 Ng, const float3 I) +{ + float res = emissive_pdf(Ng, I); + + return make_float3(res, res, res); +} + __device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc) { return emissive_eval(sd->Ng, sd->I); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 267cb8e6d3a..1bf1cde4a1c 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -109,6 +109,9 @@ Light::Light() map_resolution = 512; + spot_angle = M_PI_F/4.0f; + spot_smooth = 0.0f; + cast_shadow = true; shader = 0; } @@ -451,6 +454,17 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce 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); } + else if(light->type == LIGHT_SPOT) { + shader_id &= ~SHADER_AREA_LIGHT; + + float spot_angle = cosf(light->spot_angle*0.5f); + float spot_smooth = (1.0f - spot_angle)*light->spot_smooth; + + 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, dir.x, dir.y); + light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f); + light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + } } device->tex_alloc("__light_data", dscene->light_data); diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 0ed143f5ad1..fb8684fa59b 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -48,6 +48,9 @@ public: int map_resolution; + float spot_angle; + float spot_smooth; + bool cast_shadow; int shader; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index fee2f10085b..cd44b7e8cda 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -162,6 +162,12 @@ __device_inline float nonzerof(float f, float eps) return f; } +__device_inline float smoothstepf(float f) +{ + float ff = f*f; + return (3.0f*ff - 2.0f*ff*f); +} + /* Float2 Vector */ #ifndef __KERNEL_OPENCL__ |