Cycles: spot lamp support.

This commit is contained in:
Brecht Van Lommel 2012-06-04 17:17:10 +00:00
parent 0f1fd51c21
commit 6548f7efef
9 changed files with 95 additions and 19 deletions

@ -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"

@ -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: {

@ -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;

@ -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 */

@ -283,7 +283,8 @@ typedef enum LightType {
LIGHT_DISTANT,
LIGHT_BACKGROUND,
LIGHT_AREA,
LIGHT_AO
LIGHT_AO,
LIGHT_SPOT
} LightType;
/* Camera Type */

@ -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);

@ -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);

@ -48,6 +48,9 @@ public:
int map_resolution;
float spot_angle;
float spot_smooth;
bool cast_shadow;
int shader;

@ -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__