forked from bartvdbraak/blender
Cycles: spot lamp support.
This commit is contained in:
parent
0f1fd51c21
commit
6548f7efef
@ -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__
|
||||
|
Loading…
Reference in New Issue
Block a user